Compare commits

...

233 Commits

Author SHA1 Message Date
Milan Broz
1fae09d607 Update README. 2022-01-13 10:33:46 +01:00
Milan Broz
b1ef7cc3cd Fix reencrypt mangle test for older jq. 2022-01-13 10:12:45 +01:00
Milan Broz
bc2b38991b Version 2.3.7. 2022-01-13 07:08:03 +01:00
Milan Broz
3b35e438bc Add Release Notes 2022-01-13 07:08:03 +01:00
Milan Broz
4c0ae43f3a Update LUKS2 on-disk description. 2022-01-13 07:08:03 +01:00
Ondrej Kozina
d6649293a5 Allow reencryption metadata repair from cryptsetup. 2022-01-13 07:08:03 +01:00
Ondrej Kozina
624f3220a1 Add CRYPT_REENCRYPT_REPAIR_NEEDED flag.
crypt_reencrypt_status() returns this flag if old
online-reencrypt requirement is detected and reencryption
keyslot digest is missing.

crypt_reencrypt_init_by_passphrase() with same flag applied
repairs (upgrade) reencryption metadata so that
automatic reencryption recovery during activation
is again possible and reencryption operation can be resumed
post CVE-2021-4122 fix.
2022-01-13 07:08:03 +01:00
Milan Broz
2e44267891 Add reencryption mangle test 2022-01-13 07:08:03 +01:00
Ondrej Kozina
c75d740f9a Make reencryption flag and keyslot inseparable.
LUKS2 validation code now requires reencrypt keyslot together with
online-reencryption flag or none of those.
2022-01-13 07:08:03 +01:00
Ondrej Kozina
bc26c764c6 Rename LUKS2_keyslot_reencrypt_create function.
The function never writes on-disk. Also removed validation
function call-in since it will be called later before
writing on-disk and metadata does not have to be complete
at the moment of LUKS2_keyslot_reencrypt_allocate call.
2022-01-13 07:08:03 +01:00
Ondrej Kozina
ce8aab39ca Add segments validation for reencryption.
Effective segments during LUKS2 reencryption must
match key characteristics of backup segment
(cipher, sector_size, segment type).
2022-01-13 07:08:03 +01:00
Ondrej Kozina
d0169a303d Split requirements validation from config section validation. 2022-01-13 07:08:03 +01:00
Ondrej Kozina
f83e56e43e Expose json_segment_contains_flag to internal library. 2022-01-13 07:08:03 +01:00
Ondrej Kozina
4e98b65c04 Move requirement helpers for later changes. 2022-01-13 07:08:03 +01:00
Milan Broz
d45e6788e8 Add disable-luks2 reencryption configure option.
The option --disable-luks2-reencryption completely disable
LUKS2 reencryption code.

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

Devices with online reencryption in progress cannot be activated.

This option can cause some incompatibilities. Please use with care.
2022-01-13 07:07:37 +01:00
Milan Broz
18cb1eeeb9 Do not run reencryption recovery when not needed. 2022-01-12 20:49:34 +01:00
Milan Broz
7eeb45537a Reenc keyslot must have key_size == 1. 2022-01-12 20:49:34 +01:00
Ondrej Kozina
60addcffa6 Fix CVE-2021-4122 - LUKS2 reencryption crash recovery attack
Fix possible attacks against data confidentiality through LUKS2 online
reencryption extension crash recovery.

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

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

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

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

The fix introduces additional digest protection of reencryption
metadata. The digest is calculated from known keys and critical
reencryption metadata. Now an attacker cannot create correct metadata
digest without knowledge of a passphrase for used keyslots.
For more details, see LUKS2 On-Disk Format Specification version 1.1.0.
2022-01-12 20:49:34 +01:00
Milan Broz
e71c151ebb Rename reenc_keyslot_update to reencrypt_keyslot_update. 2022-01-12 20:49:34 +01:00
Milan Broz
6f2df7cd01 Rename luks2_reenc_context to luks2_reecrypt. 2022-01-12 20:49:34 +01:00
Milan Broz
8a7f590891 Rename crypt_get/set reenc_context to luks2_reencrypt. 2022-01-12 20:49:34 +01:00
Milan Broz
7319be8dad Rename LUKS2_reenc_status to LUKS2_reencrypt_status. 2022-01-12 20:49:34 +01:00
Milan Broz
5b07968c2d Rename LUKS2_reencrypt_status to LUKS2_reencrypt_get_params to avoid confusion. 2022-01-12 20:49:34 +01:00
Milan Broz
dc0ecd4288 Use LUKS2_reencrypt prefix for function defined in luks2.h.
This should clean up prefixes a little bit.
2022-01-12 20:49:34 +01:00
Milan Broz
286784c934 Do not expose json_object in luks2.h.
Later we can use different implementation of JSON parser.
Also define structs in one place.
2022-01-12 20:49:34 +01:00
Milan Broz
4b24e8e052 Remove json_object argument from area size checks.
These functions are internal to LUKS2 implementation.
2022-01-12 20:49:34 +01:00
Milan Broz
3f217dcacf Move LUKS2 internal functions to internal header.
This is the first step to remove json_object from internal API.
2022-01-12 20:48:07 +01:00
Milan Broz
c80fce5f47 Remove obsolete AC_HEADER_STDC macro.
This should be no longer used.
We do not support systems without standard headers anyway.
2022-01-12 18:50:12 +01:00
Milan Broz
3f4ce5d2b0 Update Readme.md. 2021-05-28 12:27:08 +02:00
Milan Broz
f95336e116 Prepare version 2.3.6.
Add Release notes.
2021-05-28 11:57:08 +02:00
Yuri Chornoivan
3753614517 po: update uk.po (from translationproject.org) 2021-05-28 09:59:30 +02:00
Yuri Kozlov
5fd96b75d3 po: update ru.po (from translationproject.org) 2021-05-28 09:59:30 +02:00
Jakub Bogusz
44aac4e5a3 po: update pl.po (from translationproject.org) 2021-05-28 09:59:30 +02:00
Hiroshi Takekawa
fbea879d1e po: update ja.po (from translationproject.org) 2021-05-28 09:59:30 +02:00
Frédéric Marchal
7012d031b6 po: update fr.po (from translationproject.org) 2021-05-28 09:59:30 +02:00
Roland Illig
a7f3065f6f po: update de.po (from translationproject.org) 2021-05-28 09:59:30 +02:00
Petr Pisar
f7fabbe141 po: update cs.po (from translationproject.org) 2021-05-28 09:59:30 +02:00
Klaus Zipfel
ac9a2c08e3 Fixing incorrect offsets for data/IV with TCRYPT system-encryption with a detached header
Related: #587
2021-05-26 09:36:32 +02:00
Milan Broz
bee77b2f35 Add note about --header use in TCRYPT format to man page.
Related: #587
2021-05-24 10:46:29 +02:00
Milan Broz
2d03ba3f4d Do not use Whirlpool hash in tests (some crypto backends do not implement it). 2021-05-23 11:13:44 +02:00
Milan Broz
29e4bca24b Increase interactive expect test timeout if runing under valgrind. 2021-05-22 10:27:00 +02:00
Milan Broz
2f9b22f5ff Update cryptsetup.pot. 2021-05-21 17:42:52 +02:00
Milan Broz
bbb6739d41 Set 2.3.6-rc0 version. 2021-05-21 17:30:40 +02:00
Мирослав Николић
d0c6eeea81 po: update sr.po (from translationproject.org) 2021-05-21 17:29:45 +02:00
Antonio Ceballos
4f982e9708 po: update es.po (from translationproject.org) 2021-05-21 17:29:28 +02:00
Milan Broz
df8135dfdf Check exit value for snprintf where it makes sense. 2021-05-21 14:54:00 +02:00
Milan Broz
280c821b9b Add some fixes and workarounds for gcc-11 static analyzer.
Not everything is a real bug (false positive rate is very high here),
but the code is actually more readable.
2021-05-21 14:44:15 +02:00
Ondrej Kozina
28dd0f5c05 Avoid LUKS2 decryption without detached header.
This is temporary hotfix for stable 2.3.6 release. The full
fix that requires new API will be provided in later 2.4.0
release.

For more info see issue #614.
2021-05-21 14:27:24 +02:00
Milan Broz
c7789719d8 integritysetup: mention maximal allowed key size
The error message and man page should contain this information.
2021-05-19 19:44:56 +02:00
Milan Broz
97e709788e Fix description of maximum passphrase size. 2021-05-19 19:40:59 +02:00
Milan Broz
3dbbc005d3 Add test for longer integritysetup keys. 2021-05-19 19:40:51 +02:00
Milan Broz
e1e3430c2c devmapper: avoid truncation of table features
This patch fixes several problems:
 - some optional features for dm-verity can be larger than pre-allocated buffer
 - device paths and other strings can be allocated dynamically
 - featured options with keys in dm-integrity are not wiped on stack
 - get rid of strncat()
 - always check return code of snprintf

Related #648
2021-05-19 19:35:51 +02:00
Andrii Pravorskyi
b354cdd9ad Add a note about CRC32 and other non-cryptographic checksums 2021-05-19 13:44:28 +02:00
Milan Broz
ed24d033d4 Allow CRYPT_BUSY also a a valid check for active device.
In ideal system nothing should touch test devices, but to make tests
more robust, we should expect that something is still scanning devices
after activation. So replace all checks for CRYPT_ACTIVE to allow
also CRYPT_BUSY.

(Fixes some problems seen in #633)
2021-05-19 13:44:25 +02:00
Milan Broz
5da8f5e710 Fix broken loopaes test.
We actually try to write file in /dev because the device is deactivated.

Broken since 2018 in 8728ba08e2
2021-05-19 13:44:21 +02:00
Milan Broz
800a8a4d5d Fix libintl detection for compiled tests.
Commit 99c4e83994 was incomplete.

See #633.
2021-05-19 13:44:19 +02:00
Milan Broz
0a06947e14 Add Blake2b and Blake2s hash support for crypto backend.
We support most recent crypto algorithms, so this
is only addition of the Blake hash family.

Kernel and gcrypt crypto backend supports all variants,
OpenSSL only Blake2b-512 and Blake2s-256.

There is no useable support for NSS and Nettle yet.

Crypto backend supports kernel notation e.g. "blake2b-512"
that is translated to the library backend names.
2021-05-19 13:44:15 +02:00
Milan Broz
418d068470 Allow to use backup header for tcrypt format.
TrueCrypt/VeraCrypt supports backup header, it seems to have
the same format as normal header.

Let's use --header option here, it can be used to unlock data partition
with header backup (open and dump commands).

Fixes: #587.
2021-05-19 13:43:37 +02:00
Milan Broz
9abe126016 Set devel 2.3.x version. 2021-05-19 13:08:46 +02:00
Milan Broz
59cf9969f9 Update cryptsetup.pot. 2021-03-11 12:56:15 +01:00
Milan Broz
98ec1e314a Prepare version 2.3.5. 2021-03-11 12:56:11 +01:00
Milan Broz
a9b327c12a Update Release notes version. 2021-03-11 12:55:25 +01:00
Milan Broz
eaa93a8116 Prepare Readme for version 2.3.5. 2021-03-11 12:55:09 +01:00
Milan Broz
018494b6b3 Add note for passwdqc change to release notes. 2021-03-11 11:38:21 +01:00
Dmitry V. Levin
3d7a0f741a Update libpasswdqc support
Starting with version 2.0.0, libpasswdqc can use memory allocation
when loading configuration that contains new optional parameters.
It's therefore recommended to free all memory allocated by
passwdqc_params_load using new passwdqc_params_free function
introduced in the same version of libpasswdqc.

[slightly modified by mbroz]
2021-03-11 11:38:11 +01:00
Milan Broz
3858b1815c Add stdbool.h include. 2021-03-09 20:47:39 +01:00
Yuri Chornoivan
4eca4e8fce po: update uk.po (from translationproject.org) 2021-03-09 20:40:51 +01:00
Yuri Kozlov
39abe23e0e po: update ru.po (from translationproject.org) 2021-03-09 20:40:51 +01:00
Jakub Bogusz
80faafea48 po: update pl.po (from translationproject.org) 2021-03-09 20:40:51 +01:00
Hiroshi Takekawa
f658ea6ba4 po: update ja.po (from translationproject.org) 2021-03-09 20:40:51 +01:00
Frédéric Marchal
fa0a24f726 po: update fr.po (from translationproject.org) 2021-03-09 20:40:51 +01:00
Roland Illig
24abdf4e72 po: update de.po (from translationproject.org) 2021-03-09 20:40:51 +01:00
Petr Pisar
677572a425 po: update cs.po (from translationproject.org) 2021-03-09 20:40:51 +01:00
Milan Broz
30d6a8a8f9 Update 2.3.5 release notes.
And reformat it for strange problems with mail signature (line length).
2021-03-09 20:40:45 +01:00
Milan Broz
9fc40d35d3 Remove superfluous CONST_CAST.
It only confuses cppcheck.
2021-03-09 20:39:58 +01:00
Milan Broz
5a032abc33 Fix partial reads from TTY (interactive terminal).
Some stable kernels started to return buffer from terminal
in partial buffers of maximal size 64 bytes.

This breaks all passphrases longer than 64 characters entered
through interactive input (for all crypto formats).

(The problem is probably fixed in more recent kernels, but
the read() call can always return a partial read here.)

This patch also fixes wrong password limit, the last character
of passphrase of maximal size was never handled.
Now the maximal passphrase length is really 512 characters.

Fixes: #627.
2021-03-09 20:36:44 +01:00
Milan Broz
6df6c0a363 Update Readme.md. 2021-03-04 13:16:44 +01:00
Milan Broz
e2e57e5776 Update cryptsetup.pot. 2021-03-04 11:35:50 +01:00
Milan Broz
3d8cb44c61 Fix typo. 2021-03-04 11:27:33 +01:00
Milan Broz
05dad56f75 Add release notes for 2.3.5-rc. 2021-03-03 22:21:24 +01:00
Milan Broz
69361fec1c Add a note about FEC calculation to veritysetup manual. 2021-03-03 12:20:51 +01:00
Milan Broz
4e0398aef0 Add final list of failures to valgrind-check test target. 2021-03-03 12:11:24 +01:00
Ondrej Kozina
51ab9da665 Fix reencryption recovery tests w/ cipher_null. 2021-03-02 17:25:00 +01:00
Milan Broz
855a232403 Add disappeared device test. 2021-03-02 16:44:18 +01:00
Milan Broz
96241cea6a Check internal device functions for NULL device.
Most of these functions already works even with device=NULL.

There can be some rare situations when this call could happen,
so be safe always.
(Like initialization for a device that disappears during init.)

Also see
https://bugzilla.redhat.com/show_bug.cgi?id=1932946
2021-03-02 16:44:11 +01:00
Milan Broz
9e5c87b449 Fix allocation of volume key in LUKS1 open_key.
This function should not return allocated key on error path.

Recent patch (suspend/resume) introduced a memory leak because of this.
2021-02-26 00:16:06 +01:00
Ondrej Kozina
7d1b40a3a6 Silent error messages in tests. 2021-02-26 00:16:06 +01:00
Ondrej Kozina
969be38a7a Add error message when suspending wrong device.
In case user tries to suspend LUKS data device instead
of dm-crypt mapping.

See issue#622.
2021-02-26 00:16:06 +01:00
Ondrej Kozina
93382071a5 Fix luksResume when called on non-LUKS device. 2021-02-26 00:16:06 +01:00
Ondrej Kozina
426a8b9df0 Fix reversed condition in LUKS2 api test.
get_luks2_offsets is based on get_luks_offsets from api-test.c
but for some odd reason 'metadata_device' parameter had reversed
meaning.
2021-02-26 00:16:06 +01:00
Ondrej Kozina
83811b5ea9 Fix keyslots size overflow when device too small.
It properly failed but debug message was confusing.
Now it fails later properly with "device too small"
error message.
2021-02-26 00:16:06 +01:00
Ondrej Kozina
56a01574ff Allow LUKS resume for device with cipher_null. 2021-02-26 00:16:06 +01:00
Ondrej Kozina
c68cd0a483 Unify crypt_resume_by internal code. 2021-02-26 00:16:06 +01:00
Ondrej Kozina
b2135a75e2 Do not upload VK in keyring when data cipher is null. 2021-02-26 00:16:06 +01:00
Ondrej Kozina
91e8f5ffd9 Remove redundant check.
It can't be non-LUKS2 device at this branching.
2021-02-26 00:16:06 +01:00
Ondrej Kozina
855628f796 Add tests for cipher_null suspend/resume. 2021-02-26 00:16:06 +01:00
Milan Broz
db8ce3f818 verity: run FEC check even if root hash fails.
The error correction can fix even problem with root hash.

For now, always return fail if initial check of root hash failed.

FIXME: The FEC verify code need to be rewritten to repair only
blocks where hash is wrong and the re-check hash after recovery,
inclkuding root hash.

Now we do not check hash after FEC recovery. The Reed-Solomon
decoder can then "repair" code wrongly if parity is too damaged.

For now, the information about FEC repaired errors is only
advisory, it does not mean device is fully repaireable.
2021-02-26 00:16:05 +01:00
Milan Broz
973474503a verity: do not process hash image if it is empty. 2021-02-26 00:16:05 +01:00
Milan Broz
4e2561df6d verity: do not calculate hash offset if hash area is not used.
Sometimes device is so small that there is only root hash needed
and the hash area is not used.
2021-02-26 00:16:05 +01:00
Milan Broz
b01ec20703 veritysetup: do not increase hash image size if hash area is not used.
Do not write more than needed header if hash area is not used later.

All space in hash area is then used in FEC calculation, so it makes
no sense to add unused area.
2021-02-26 00:16:05 +01:00
Ondrej Kozina
ca1b41cf96 Extend LUKS2 reencryption tests w/ cipher_null. 2021-02-26 00:16:05 +01:00
Ondrej Kozina
7825e0d4a6 Bypass keyring activation flag if cipher is null. 2021-02-26 00:16:05 +01:00
Ondrej Kozina
c8c28cf6dd Use crypt_is_cipher_null check where possible. 2021-02-26 00:16:05 +01:00
Ondrej Kozina
fb8aa6d03b Fix default xts mode key size in reencryption.
Reencryption did not take into account adjusted xts
key size configuration option. This patch fix the
issue by using same logic as in luksFormat with xts
mode selected for data encryption.
2021-02-26 00:16:05 +01:00
Ondrej Kozina
207383782a Fix reencryption test on systems w/o keyring. 2021-02-26 00:16:05 +01:00
Ondrej Kozina
f25a1c92ec Prefer default cipher when reencrypting cipher_null device.
By default when reencrypting LUKS2 device we regenerate only
the volume key. But if the device was 'encrypted' by cipher_null
this change did not make sense. The key was always empty.

Change the behaviour so that unless user specifies --cipher
parameter on command line, we change data encryption cipher
to default when old segment cipher was cipher_null.
2021-02-26 00:16:05 +01:00
Ondrej Kozina
44a9e7aa62 Improve key handling with cipher_null in reencryption. 2021-02-26 00:16:05 +01:00
Ondrej Kozina
27eee9cfcb Add debug message for activated cipher_null device. 2021-02-26 00:16:05 +01:00
Ondrej Kozina
196477d194 Replace bogus cipher_null keyslots before reencryption.
By mistake LUKS2 allowed keyslots 'not-so-encrypted' by
cipher_null (only explicitly requested by --cipher or
--keyslot-cipher parameters). If we encounter
such old key during reencryption let's replace the cipher
for new keyslot with default LUKS2 keyslot cipher.
2021-02-26 00:16:05 +01:00
Ondrej Kozina
1e68d73bc3 Fix device comparison for dm-crypt with cipher_null.
Do not compare volume keys if segment uses cipher_null.
The key is ignored by lower layer (internal libdevmapper)
anyway.
2021-02-26 00:16:05 +01:00
Ondrej Kozina
17bb1e2fdd Do not upload vk in keyring for cipher_null segment.
It does not make sense to upload volume keys in
kernel keyring if segment cipher is cipher_null.
The real volume_key is thrown away and replaced
with empty key anyway.
2021-02-26 00:16:05 +01:00
Ondrej Kozina
ba7fd45ba6 Fix broken detection of null cipher in LUKS2.
This bug enabled to create LUKS2 keyslots encrypted by
cipher_null when explicitely requested by user. LUKS2
was never meant to allow keyslot encryption with
cipher_null. cipher_null is meant for debug purposes
only as a segment cipher.
2021-02-26 00:16:05 +01:00
Ondrej Kozina
7058b81bb6 Move cipher_null check in internal function crypt_is_cipher_null.
Also removes tools helper so that we keep check in one place.
2021-02-26 00:16:05 +01:00
Ondrej Kozina
b40018860b Add tests for various keyslot cipher null bugs. 2021-02-26 00:16:05 +01:00
Milan Broz
e97ac9f58c Get rid of off_t integers and use uint64_t.
Also move uint64 multiplication overflow check to internal library.
2021-02-26 00:16:05 +01:00
Milan Broz
75447d0d80 Fix debug message displaying required hash device size.
If located on the same device with hashes, offset must be subtracted.
(Also there could be one block more for superblock.)
2021-02-26 00:16:05 +01:00
Milan Broz
c760ae36ea Get rid of the long paramete list in FEC verity function.
Also params struct will be needed in following patch.
2021-02-26 00:16:05 +01:00
Milan Broz
dbd20776bc Fix dm-verity FEC calculation if stored in the same image with hashes.
FEC (Forward Error Correction) data should cover the whole data area,
hashes (Merkle tree) and optionally additional metadata (located after hash area).

Unfortunately, if FEC data is stored in the same file as hash, the calculation
wrongly used the whole file size thus overlaps with FEC area itself.
This produces unusable and too large FEC data.

(There is not a problem if FEC image is a separate image.)

This patch fixes the problem, introducing FEC blocks calculation as:

 -If hash device is in a separate image, metadata covers the whole rest of the image after hash area.
  (Unchanged behaviour.)

 -If hash and FEC device is in the image, metadata ends on the FEC area offset.

This should probably fix several issues reported with FEC wrong calculations.

Fixes: #554
2021-02-26 00:16:05 +01:00
Milan Broz
3ebbceaef2 Fix veritysetup exit code for bad root hash with FEC enabled.
If FEC was enabled, the error for bad root hash was replaced
by error correction (datga were ok, only root hash was wrong).

Do not run recovery test if root hash is incorrect.
2021-02-26 00:16:05 +01:00
Milan Broz
d733e4d0e8 Add a missing stdbool include. 2021-02-26 00:16:05 +01:00
Milan Broz
4d6d6edcff Backport device_is_identical() changes needed for following patch. 2021-02-26 00:13:48 +01:00
Milan Broz
1380efa1c6 Fix compat interactive test to run with valgrind too. 2021-02-08 21:43:40 +01:00
Milan Broz
bce9d695e3 Coverity workaround for tainted warnings.
Password can be any string and the function allocates
string properly, so mark it is as sanitized.
2021-02-07 20:05:03 +01:00
Milan Broz
bea6e0da74 Fix an error path memory leak. 2021-02-07 20:02:20 +01:00
Vojtech Trefny
e064406f85 bitlk: Fix parsing startup key metadata
This fixes multiple issues found by coverity in the startup key
code and also makes the parsing less complicated -- we don't need
to loop through all metadata entries in the BEK file if we are
expecting only one metadata entry of a specific type.
2021-02-07 20:02:20 +01:00
Milan Broz
3d58f480ee Avoid "output may be truncated" gcc warnings.
These are false positives and gcc internal detection of this
pattern seems to be broken again.

In this path we must avoid memcpy the whole buffer, it can contain
some bytes after null char, so use MIN/strlen here.
2021-02-07 20:02:20 +01:00
Milan Broz
660edf7959 Remove WARNING from the debug message. 2021-02-07 20:02:20 +01:00
Milan Broz
312efd8582 Remove redundant EOL in the previous patch. 2021-02-07 20:02:20 +01:00
Milan Broz
ec657332c6 Rephrase lockinging dir warning and move it to debug level.
System should later provide safe transition to tempdir configuration.
2021-02-07 20:02:20 +01:00
Milan Broz
e123263975 Fix LUKS1 repair code.
We cannot trust possibly broken keyslots metadata here through LUKS_keyslots_offset().
Expect first keyslot is aligned, if not, then manual repair is neccessary.

(This situation happen if partition table signarture overwrites slot 4 area).

Also, if keyslot order is different, current repair code does not work properly
(this can happen only with downconverting LUKS2 device).
2021-02-07 20:02:20 +01:00
Milan Broz
e8f2bb4a1a Disable alternative backends in CI build for now.
These will run in release time only.
2021-02-07 20:02:20 +01:00
Ondrej Kozina
6e71e2d6ed Fix crypt_keyslot_change_by_passphrase tokens bug.
crypt_keyslot_change_by_passphrase broke token references
to keyslots while existing keyslot id was different from
new keyslot id.
2021-02-07 20:02:20 +01:00
Ondrej Kozina
2f6698d1a7 Test crypt_keyslot_change_by_passphrase does not break tokens. 2021-02-07 20:02:12 +01:00
Milan Broz
d20929194f Fix previous commit error condition.
This hints actually failed even if return code was OK.
2021-02-07 20:00:16 +01:00
Milan Broz
0a6f89cfa6 Fix dm-integrity HMAC recalculation problem.
This patch adds support for Linux kernel (since version 5.11) dm-integrity
fixes that disables integrity recalculation if keyed algorithms (HMAC) is used.

Original dm-integrity superblock version <=4 is recalculation offset
field not protected by HMAC. An attacker can move this pointer and force
the kernel to recalculate the data area, ignoring original HMAC tags.

N.B. dm-integrity was not intended to protect against intentional changes.
Better use authenticated encryption (AEAD) in combination with dm-crypt.
It is designed to protect against random data corruption caused by hardware
or storage medium faults.

Despite that, we try to keep the system secure if keyed algorithms are used.

There are two possible keyed algorithms in dm-integrity - algorithm used
to protect journal and superblock (--journal-integrity) and algorithms
for protecting data (--integrity).
The dm-integrity superblock is guarded by --journal-integrity, so if you want
to protect data with HMAC, you should always also use HMAC for --journal-integrity.
The keys are independent. If HMAC is used for data but not for the journal,
recalculation is disabled by default.

For new kernel dm-integrity, the HMAC option also uses salt in superblock
to avoid an easy way to distinguish that the HMAC key is the same for two devices
(if data are the same).

The new HMAC and superblock are enabled automatically if the kernel supports it
(you can see superblock version 5 and fix_hmac flag in dump command).

If you need to use (insecure) backward compatibility, then two new integritysetup
options are introduced:

 Use --integrity-legacy-recalc (instead of --integrity-recalc) to allow recalculation
 on legacy devices.

 Use --integrity-legacy-hmac in format action to force old insecure version
 format (with HMAC).

Libcryptsetup API also introduces flags
  CRYPT_COMPAT_LEGACY_INTEGRITY_HMAC and
  CRYPT_COMPAT_LEGACY_INTEGRITY_RECALC
to set these through crypt_set_compatibility() call.
2021-02-07 19:58:49 +01:00
Milan Broz
c74f17c6e7 Fix copy & paste typo in integrity test. 2021-02-07 19:52:32 +01:00
Ondrej Kozina
616dd5a304 Allow bitlk tests to run with valgrind. 2021-02-07 17:37:18 +01:00
Ondrej Kozina
79442539c7 Remove bogus valgrind suppressions. 2021-02-07 17:37:06 +01:00
Ondrej Kozina
92b24fd758 Fix popt string related memory leaks.
All POPT_ARG_STRING pointers must be free'd manually
in calling application. This is unfortunately not documented
well behaviour of popt and we were having memory leaks due to
it.
2021-02-07 17:36:56 +01:00
Ondrej Kozina
4a43a2773a Add utilities cleanup routine. 2021-02-07 17:36:47 +01:00
Ondrej Kozina
74c943c352 Drop unreachable code and useless conditions.
integrity_alg variable can not be NULL.
2021-02-07 17:36:38 +01:00
Ondrej Kozina
bc49c83ace Remove const from all opt_ string declarations.
Those variables contain pointers to dynamically alocated memory.
2021-02-07 17:36:24 +01:00
Ondrej Kozina
ed28583f17 Do not pass constant strings to option string variables.
This is part of effort to eliminate all memory leaks related
to options parsing in popt but for that to work we must avoid
passing constant strings to free().
2021-02-07 17:36:10 +01:00
Ondrej Kozina
5345a73ca0 Group all string options variables together. 2021-02-07 17:35:23 +01:00
Ondrej Kozina
36f424ce71 Properly prefix all popt variables in veritysetup. 2021-02-07 17:28:09 +01:00
Milan Broz
a757d84b91 Update Copyright year. 2021-02-07 16:09:13 +01:00
Luca Boccassi
255464b0ae verity: fix strncpy boundary check compiler warning
lib/verity/verity.c: In function ‘VERITY_write_sb’:
lib/verity/verity.c:200:2: warning: ‘strncpy’ specified bound 32 equals destination size [-Wstringop-truncation]
  strncpy(algorithm, params->hash_name, sizeof(sb.algorithm));
2021-02-07 16:09:13 +01:00
Luca Boccassi
4c350f4d72 verity: improve crypt_activate_by_signed_key debug log
Check if a signature is actually available before logging that the
volume is being activated with a signed key.
2021-02-07 16:09:13 +01:00
Ondrej Kozina
7cca38632f Add pedantic check for key helpers arguments. 2021-02-07 16:09:13 +01:00
Lars Wendler
d8bbfb118b cryptsetup.8: Fix no_write_workqueue option name
It's called --perf-no_write_workqueue

Signed-off-by: Lars Wendler <polynomial-c@gentoo.org>
2021-02-07 16:09:13 +01:00
Arno Wagner
178bc9ee39 Update FAQ: Clarified statement about block sizes in 5.16 2021-02-07 16:09:13 +01:00
Milan Broz
7d4d1baaa7 Fix some formatting and typos in man page. 2021-02-07 16:09:13 +01:00
Milan Broz
f82c1bf90f Remove obsolete tpm-luks project link from FAQ. 2021-02-07 16:09:13 +01:00
Milan Broz
8d856d4e17 Add lore.kernel.org list archive link. 2021-02-07 16:09:13 +01:00
Samanta Navarro
fb49d9630d lib: always clear size in crypt_safe_free
Writing into allocated memory right before calling free can be optimized
away by smart compilers. To prevent this, a volatile access must be
performed. This happens already in crypt_safe_memzero.

It was difficult to provoke GCC to remove the assignment, but I was able
to find a way to prove the theory:

* Build cryptsetup with: CFLAGS="-flto -O3 -g" ./configure --enable-static
* Create main.c:

#include <libcryptsetup.h>

int
main(void) {
        char *x = crypt_safe_alloc(64);
        crypt_safe_free(x);
        return 0;
}

* Build the program with: gcc -O3 -flto -static -o main main.c -lcryptsetup
* Disassemble: objdump -d main

My output on an amd64 system is:

0000000000401670 <main>:
  401670:       41 54                   push   %r12
  401672:       bf f0 03 00 00          mov    $0x3f0,%edi
  401677:       55                      push   %rbp
  401678:       48 83 ec 08             sub    $0x8,%rsp
  40167c:       e8 ff 4d 01 00          callq  416480 <__libc_malloc>
  401681:       48 85 c0                test   %rax,%rax
  401684:       74 2f                   je     4016b5 <main+0x45>
  401686:       48 c7 00 e8 03 00 00    movq   $0x3e8,(%rax)
  40168d:       4c 8d 60 08             lea    0x8(%rax),%r12
  401691:       48 89 c5                mov    %rax,%rbp
  401694:       be e8 03 00 00          mov    $0x3e8,%esi
  401699:       4c 89 e7                mov    %r12,%rdi
  40169c:       e8 4f 76 01 00          callq  418cf0 <explicit_bzero>
  4016a1:       48 8b 75 00             mov    0x0(%rbp),%rsi
  4016a5:       4c 89 e7                mov    %r12,%rdi
  4016a8:       e8 43 76 01 00          callq  418cf0 <explicit_bzero>
  4016ad:       48 89 ef                mov    %rbp,%rdi
  4016b0:       e8 3b 54 01 00          callq  416af0 <__free>
  4016b5:       48 83 c4 08             add    $0x8,%rsp
  4016b9:       31 c0                   xor    %eax,%eax
  4016bb:       5d                      pop    %rbp
  4016bc:       41 5c                   pop    %r12
  4016be:       c3                      retq
  4016bf:       90                      nop

You can see that the memory allocation and explicit_bzero calls were not
optimized away. But the size assignment disappeared.

Compiling without -O3 or without -flto does not inline the calls and
keeps the assignment. Also the shared library shipped with my
distribution has the assignment.
2021-02-07 16:09:13 +01:00
Samanta Navarro
7866e71d6f Fix typos.
Typos found with codespell.
2021-02-07 16:09:13 +01:00
Samanta Navarro
d2ee949d88 lib: fix utils_safe_memory function comments. 2021-02-07 16:09:13 +01:00
Ondrej Kozina
3a29cbbf5d Add missing translation anotation. 2021-02-07 16:09:13 +01:00
Milan Broz
51bf5435f9 Enable Travis test for GOST crypto in VeraCrypt (install GOST external kernel crypto modules). 2021-02-07 16:09:13 +01:00
Vojtech Trefny
505effe085 bitlk: Fix key sizes for BITLK encryption types
It makes more sense to return "real" key sizes, e.g. 256 bit for
AES-XTS 128 and 256/512 bit for AES-CBC with Elephant which has
a separate key for the Elephant mode.
2021-02-07 16:09:12 +01:00
Vojtech Trefny
82f8fb653c bitlk: Allow running bitlk_metadata_free with NULL 2021-02-07 16:09:12 +01:00
Joerg Kastning
829a2379a1 Update cryptsetup.8
* Improved information about calling luksFormat on devices.
2021-02-07 16:09:12 +01:00
Joerg Kastning
b5894ce1ab Update cryptsetup.8
* Rename "BASIC COMMANDS" to "BASIC ACTIONS"
 * Changed a sentence saying that luksFormat would work on unmapped luks containers, only.
 * Insert 6 examples of using cryptsetup for luks containers
2021-02-07 16:09:12 +01:00
lixiaokeng
1bc6caceb1 lib: fix memory leak in crypt_pbkdf_check
There is a memory leak when PBKDF2_temp > UINT32_MAX. Here,
we change return to goto out to free key.

Signed-off-by: Lixiaokeng <lixiaokeng@huawei.com>
Signed-off-by: Linfeilong <linfeilong@huawei.com>
2021-02-07 16:09:12 +01:00
lixiaokeng
78f33946f1 lib: fix potential segfault in LUKS2_token_buffer_free
The value of h may be NULL. Check it vefore visiting its
memeber to avoid segfault.

Signed-off-by: Lixiaokeng <lixiaokeng@huawei.com>
Signed-off-by: Linfeilong <linfeilong@huawei.com>
2021-02-07 16:09:12 +01:00
lixiaokeng
0d90efac88 lib: fix potential segfault in _crypt_cipher_crypt
The value of header may be NULL. Check it to avoid
segfault.

Signed-off-by: Lixiaokeng <lixiaokeng@huawei.com>
Signed-off-by: Linfeilong <linfeilong@huawei.com>
2021-02-07 16:09:12 +01:00
lixiaokeng
82490aaaa3 lib: fix potential segfault in _keyslot_repair
The value of vk may be NULL in _keyslot_repair. It will
be dereferenced in LUKS_generate_phdr. Check it to avoid
segfault.

Signed-off-by: Lixiaokeng <lixiaokeng@huawei.com>
Signed-off-by: Linfeilong <linfeilong@huawei.com>
2021-02-07 16:09:12 +01:00
lixiaokeng
782f4c5029 lib: check return value of malloc in BITLK_read_sb
The return value of malloc vmk and params->fvek is not
checked. Here we add checking.

Signed-off-by: Lixiaokeng <lixiaokeng@huawei.com>
Signed-off-by: Linfeilong <linfeilong@huawei.com>
2021-02-07 16:09:12 +01:00
Ondrej Kozina
d63d399c17 Fix cryptsetup resize using LUKS2 tokens.
Fix a bug where cryptsetup needlessly asked for passphrase
even though volume key was already unlocked via LUKS2 token.

Fixes: #601.
2021-02-07 16:09:12 +01:00
dofrupisla
745c75b5b0 Fix typo 2021-02-07 16:09:12 +01:00
Samanta Navarro
1d615cf6dd fix typo in manual page 2021-02-07 16:09:12 +01:00
Vojtech Trefny
7f0ddcbed4 bitlk: Show better error when trying to open an NTFS device
Both BitLocker version 1 and NTFS have the same bootcode eb 52 90
so when trying to open an NTFS device user will get error message
saying that BitLocker version 1 is not supported. This patch
switches to check the superblock first to inform user that the
device is not a BITLK device.
2021-02-07 16:09:12 +01:00
Vojtech Trefny
efa7c4574c bitlk: Fix test image for startup key
We zero data parts of the test images to make them as small as
possible and for the latest startup key image I deleted bigger
portion of the NTFS header by accident which caused older blkid
on CentOS/RHEL 6 to not identify the NTFS filesystem on the
cleartext device.
2021-02-07 16:09:12 +01:00
Milan Broz
e2b4479543 bitlk: Fix a compiler warning. 2021-02-07 16:09:12 +01:00
Vojtech Trefny
7c23bdb868 bitlk: Add support for startup key protected VMKs (keyslots)
Fixes: #588
2021-02-07 16:09:12 +01:00
Vojtech Trefny
fa5d46592e bitlk: Try all keyslots even if some checks fails for passphrase
We can't easily distinguish between a passphrase and other
protectors like recovery passphrase or startup key during
activation so we can't stop when attempted passphrase activation
fails because a binary startup key can't be conveted to UTF-16
during KDF.
2021-02-07 16:09:12 +01:00
Joe Richey
e5e09d889b Include correct type definition in .h files
Right now, cryptsetup makes an attempt to include the correct
definitions in all of its header files, allowing the headers to
compile regardless of the context in which they are included.

A few files were missed, this change fixes them by adding the minimal
set of #includes needed to get them to compile.

Signed-off-by: Joe Richey <joerichey@google.com>
2021-02-07 16:09:12 +01:00
Milan Broz
7dbd007ac1 Print a visible error if requesting resize on unsupported format.
Fixes: #571.
2021-02-07 16:09:12 +01:00
Ondrej Kozina
dbb80e41c7 Do not print opt_io_size warning needlessly.
In fallback path min_io_size and opt_io_size could be
same and the warning was confusing.
2021-02-07 16:09:12 +01:00
Milan Broz
33cc4739da Print warning if msgfmt utility from gettext is missing.
User have to install gettext package or manually disable translation
using --disable-nls.

Also remove links to GNU packages ftp, all of these should by provided
by native distro packaging systems.

Fixes: #591.
2021-02-07 16:09:12 +01:00
Milan Broz
5518198f97 Always store dm-verity hash algorithm in superblock in lowercase.
Fixes: #586.
2021-02-07 16:09:12 +01:00
Milan Broz
1a81925764 Fix disaplay of dm-integrity recalculating sector in dump command.
Fixes: #578.
2021-02-07 16:09:12 +01:00
Milan Broz
15df5904f2 Fix a memleak in blockwise test. 2021-02-07 16:09:12 +01:00
Milan Broz
07a06f2f40 Set 2.3.5-rc0 version. 2021-02-07 16:09:12 +01:00
Мирослав Николић
fd94f036c1 po: update sr.po (from translationproject.org) 2021-02-07 16:09:12 +01:00
Мирослав Николић
03607db1f8 po: update sr.po (from translationproject.org) 2021-02-07 16:09:12 +01:00
Josef Andersson
c2fcc7aebd po: update sv.po (from translationproject.org) 2021-02-07 16:09:12 +01:00
Josef Andersson
8dbb72e296 po: update sv.po (from translationproject.org) 2021-02-07 16:09:12 +01:00
Antonio Ceballos
513e88fd77 po: update es.po (from translationproject.org) 2021-02-07 16:09:12 +01:00
Antonio Ceballos
8360a85169 po: update es.po (from translationproject.org) 2021-02-07 16:09:12 +01:00
Roland Illig
b56a450a31 po: update de.po (from translationproject.org) 2021-02-07 16:09:12 +01:00
Milan Broz
569b485d02 Update Readme.md. 2020-09-03 20:45:35 +02:00
Milan Broz
bd888e30a6 Prepare version 2.3.4. 2020-09-03 19:11:40 +02:00
Milan Broz
b86c51afeb Add stable version release notes. 2020-09-03 19:10:45 +02:00
Yuri Chornoivan
56f47d3899 po: update uk.po (from translationproject.org) 2020-09-03 16:37:27 +02:00
Yuri Kozlov
284672c081 po: update ru.po (from translationproject.org) 2020-09-03 16:37:18 +02:00
Jakub Bogusz
6f6b54a5fd po: update pl.po (from translationproject.org) 2020-09-03 16:37:07 +02:00
Hiroshi Takekawa
154c344115 po: update ja.po (from translationproject.org) 2020-09-03 16:36:58 +02:00
Frédéric Marchal
cccb7780ec po: update fr.po (from translationproject.org) 2020-09-03 16:36:48 +02:00
Petr Pisar
aa762d5cc1 po: update cs.po (from translationproject.org) 2020-09-03 16:36:38 +02:00
Milan Broz
68cc46fc22 Update cryptsetup.pot. 2020-08-27 23:29:51 +02:00
Milan Broz
06bd23d120 Remove a gcc warning. 2020-08-27 21:24:37 +02:00
Ondrej Kozina
2f4990868e Explicitly terminate cipher strings during down conversion. 2020-08-27 14:18:17 +02:00
Ondrej Kozina
03213ac230 Fix posible buffer overflows in LUKS conversion.
cipher[31] and cipher_mode[31] buffers were passed to
crypt_parse_name_and_mode() routine where sscanf(s, "%31[^-]-%31s",
cipher, cipher_mode) was called.

In corner case it could cause terminating 0 byte written beyond
respective arrays.
2020-08-27 14:17:58 +02:00
Ondrej Kozina
fb1b287773 Add test for LUKS2 segments validation code fix. 2020-08-27 14:17:38 +02:00
Ondrej Kozina
7ceaf3f313 Simplify validation code a bit.
Keep it simple. If there's not enough memory we can't validate
segments. The LUKS2 specification does not recommend to continue
processing LUKS2 metadata if it can not be properly validated.
2020-08-27 14:17:29 +02:00
Ondrej Kozina
3f20b04e42 Avoid needlessly large allocations in LUKS2 validation code.
In case LUKS2 backup segment creates gap in between last regular
segment and backup segment report invalid metadata imediately. We stop
on first error so there's no need to allocate large memory on heap
(we may ran with mlock(MCL_FUTURE) set).

Example:
- total segments count is 3
- regular segments have keys "0" and "1"
- first backup segment has key "42"
2020-08-27 14:17:20 +02:00
Milan Broz
82e6ca7202 Set devel 2.3.x version. 2020-08-26 15:45:20 +02:00
Milan Broz
8a170d0e80 Build branch v2.3.x in Travis. 2020-08-26 15:44:51 +02:00
Milan Broz
72be05c817 Fix error message in previous commit. 2020-08-26 15:41:48 +02:00
Milan Broz
b79ccb782b Ignore optimal-io if not aligned to minimal page size
This values is bogus on some systems and causes wrong alignment
for data area. Just ignore it there.

Fixes: #585.
2020-08-26 15:41:44 +02:00
Milan Broz
9c8c636ece Print a warning if API test generates too long log. 2020-08-26 15:41:35 +02:00
Tobias Stoeckmann
63a5bd5ef6 Fixed some typos.
The large text block happened due to reformat. It's just addition
of "the" in front of problem, i.e. "If this is _the_ problem, ..."
2020-08-26 15:41:29 +02:00
Tobias Stoeckmann
e75f5de2ed Check segment gaps regardless of heap space.
Segments are validated in hdr_validate_segments. Gaps in segment keys
are detected when collecting offsets. But if an invalid segment is very
large, larger than count, it could happen that cryptsetup is unable to
allocate enough memory, not giving a clue about what actually is the
problem.

Therefore check for gaps even if not enough memory is available. This
gives much more information with debug output enabled.

Obviously cryptsetup still fails if segments are perfectly fine but not
enough RAM available. But at that stage, the user knows that it's the
fault of the system, not of an invalid segment.
2020-08-26 15:41:24 +02:00
Milan Broz
6df1a69430 Add some descriptive output to device test - performance flags. 2020-08-26 15:40:23 +02:00
Milan Broz
e7ca35091c Add no_read/write_wrokqueue to dm-crypt options.
These performance options, introduced in kernel 5.9, configures
dm-crypt to bypass read or write workqueues and run encryption
synchronously.

Also support persistent storage of these flags for LUKS2.
2020-08-26 15:39:26 +02:00
Milan Broz
03ecfe3478 Support panic_on_corruption option form dm-verity.
The panic_on_corruption switch is available since kernel 5.9 (dm-verity 1.7.0).
2020-08-26 15:26:01 +02:00
Ondrej Kozina
f5bf9ef9fa Add test for reencryption with --master-key-file argument. 2020-08-26 14:10:23 +02:00
Ondrej Kozina
f61eb8b427 Add API test for reencryption with specific new key. 2020-08-26 14:09:55 +02:00
Ingo Franzki
a4f78e1c98 Support online reencryption for PAES cipher.
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>

(With few adjustments by Ondrej Kozina)
2020-08-26 14:03:32 +02:00
Vojtech Trefny
d1c3ad2703 bitlk: Set sector size to 512 when unknown/zero
Fixes: #584
2020-08-26 13:57:48 +02:00
Milan Broz
d7279eeda1 Use Ubuntu 20.04 in Travis CI builds. 2020-08-26 13:57:16 +02:00
Milan Broz
9c2d918474 libdevmapper: always return EEXIST if a task fails because the device already exists
Allows concurrent opens to return a usable error instead of EINVAL
2020-08-26 13:55:59 +02:00
Milan Broz
16aec64d1b Fix a problem in integritysetup if a hash algorithm has dash in the name.
If users want to use blake2b/blake2s, the kernel algorithm name
includes dash - like "blake2s-256".

Because we use dash as a separator, this patch adds an exception
for this case.

Fixes: #581.
2020-08-26 13:54:53 +02:00
Milan Broz
04d2ff7689 tcrypt: Support activation of devices with a larger sector.
TrueCrypt/VeraCrypt always use 512-bytes sector for encryption,
but for devices with a larger native sector it stores this value in header.

This patch allows activating of such devices, basically ignoring
the mentioned sector size in header (it only must be multiple
of 512-bytes sector).

Fixes: #580.
2020-08-26 13:54:34 +02:00
Milan Broz
0cd7cac03f Fix crypto backend to properly handle ECB mode.
Despite it should be never used, it should still work :)

Bug introduced in version 2.3.2.
2020-08-26 13:53:55 +02:00
Milan Broz
b2c1ec2f83 Use the most recent image in travis.yml. 2020-08-26 13:53:42 +02:00
Ondrej Kozina
a15008d876 Do not create excessively large headers.
When creating LUKS2 header with specified --offset much larger
then LUKS2 header size we needlessly also wipe (allocate up to
--offset) much larger file than needed.
2020-08-26 13:52:57 +02:00
Francesco Turco
ac535923e0 fix capitalization 2020-08-26 13:52:16 +02:00
Francesco Turco
f695e155ec fix typos 2020-08-26 13:52:08 +02:00
Francesco Turco
9412d9a0f1 use HTTPS for URLs 2020-08-26 13:51:22 +02:00
Vojtech Trefny
57eba0d6f5 bitlk: Fix reading key data size in the decrypted key material
We've assumed that first 4 bytes of the decrypted key data is the
size of the key + metadata. Looks like this isn't true and only
first two bytes contain the size and the other two bytes are
unknown data, possibly related to reencryption and/or passphrase
change.

Fixes: #575
2020-08-26 13:50:39 +02:00
Milan Broz
4a9862a666 Add option for large IV to storage wrapper.
Also implement some test vectors and use the same limits
as in dm-crypt (IV offset alignnment).
2020-08-26 13:49:54 +02:00
165 changed files with 16083 additions and 10838 deletions

View File

@@ -102,7 +102,13 @@ function travis_install_script
keyutils \
libjson-c-dev \
libblkid-dev \
dkms \
linux-headers-$(uname -r) \
linux-modules-extra-$(uname -r) \
|| return
# For VeraCrypt test
sudo apt-get install gost-crypto-dkms
}
function travis_before_script

View File

@@ -1,20 +1,23 @@
language: c
sudo: required
dist: bionic
os: linux
dist: focal
group: edge
compiler:
- gcc
env:
- MAKE_CHECK="gcrypt"
# MAKE_CHECK="gcrypt"
- MAKE_CHECK="openssl"
- MAKE_CHECK="kernel"
# MAKE_CHECK="kernel"
branches:
only:
- master
- wip-luks2
- v2.3.x
before_install:
- uname -a

84
FAQ
View File

@@ -51,7 +51,7 @@ A. Contributors
security model BEFORE you face such a disaster! In particular, make
sure you have a current header backup before doing any potentially
dangerous operations. The LUKS2 header should be a bit more resilient
as critical data starts later and is stored twice, but you can decidely
as critical data starts later and is stored twice, but you can decidedly
still destroy it or a keyslot permanently by accident.
DEBUG COMMANDS: While the --debug and --debug-json options should not
@@ -112,7 +112,7 @@ A. Contributors
characters may have different encoding depending on system configuration
and your passphrase will not work with a different encoding. A table of
the standardized first 128 ASCII characters can, e.g. be found on
http://en.wikipedia.org/wiki/ASCII
https://en.wikipedia.org/wiki/ASCII
KEYBOARD NUM-PAD: Apparently some pre-boot authentication environments
(these are done by the distro, not by cryptsetup, so complain there)
@@ -173,7 +173,7 @@ A. Contributors
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
http://creativecommons.org/licenses/by-sa/3.0/ for more details of the
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
@@ -191,7 +191,7 @@ A. Contributors
* 1.7 Is there a mailing-list?
Instructions on how to subscribe to the mailing-list are at on the
Instructions on how to subscribe to the mailing-list are on the
project website. People are generally helpful and friendly on the
list.
@@ -241,7 +241,7 @@ A. Contributors
* 2.1 LUKS Container Setup mini-HOWTO
This item tries to give you a very brief list of all the steps you
should go though when creating a new LUKS encrypted container, i.e.
should go through when creating a new LUKS encrypted container, i.e.
encrypted disk, partition or loop-file.
01) All data will be lost, if there is data on the target, make a
@@ -268,7 +268,7 @@ A. Contributors
This can take a while. To get a progress indicator, you can use the
tool dd_rescue (->google) instead or use my stream meter "wcs" (source
here: http://www.tansi.org/tools/index.html) in the following fashion:
here: https://www.tansi.org/tools/index.html) in the following fashion:
cat /dev/zero | wcs > <target device>
@@ -295,7 +295,7 @@ A. Contributors
Just follow the on-screen instructions.
Note: Passprase iteration count is based on time and hence security
Note: Passphrase iteration count is based on time and hence security
level depends on CPU power of the system the LUKS container is created
on. For example on a Raspberry Pi and LUKS1, I found some time ago that
the iteration count is 15 times lower than for a regular PC (well, for
@@ -343,7 +343,7 @@ A. Contributors
See Section 6 for details.
Done. You can now use the encrypted file system to store data. Be sure
to read though the rest of the FAQ, these are just the very basics. In
to read through the rest of the FAQ, these are just the very basics. In
particular, there are a number of mistakes that are easy to make, but
will compromise your security.
@@ -473,7 +473,7 @@ A. Contributors
That is it. Reboot or start it manually to activate encrypted swap.
Manual start would look like this:
/etc/init.d/crypdisks start
/etc/init.d/cryptdisks start
swapon /dev/mapper/swap
@@ -677,7 +677,7 @@ A. Contributors
A bit more information on the process by which transactional guarantees
are implemented can be found here:
http://lwn.net/Articles/400541/
https://lwn.net/Articles/400541/
Please note that these "guarantees" are weaker than they appear to be.
One problem is that quite a few disks lie to the OS about having flushed
@@ -705,10 +705,6 @@ A. Contributors
the key from STDIN and write it there with your own tool that in turn
gets the key from the more secure key storage.
For TPM support, you may want to have a look at tpm-luks at
https://github.com/shpedoikal/tpm-luks. Note that tpm-luks is not
related to the cryptsetup project.
* 2.15 Can I resize a dm-crypt or LUKS container?
@@ -787,7 +783,7 @@ A. Contributors
The conventional recommendation if you want to do more than just a
zero-wipe is to use something like
cat /dev/urandom > <taget-device>
cat /dev/urandom > <target-device>
That used to very slow and painful at 10-20MB/s on a fast computer, but
newer kernels can give you > 200MB/s (depending on hardware). An
@@ -811,7 +807,7 @@ A. Contributors
dd_rescue -w /dev/zero /dev/mapper/to_be_wiped
Progress-indicator by my "wcs" stream meter (available from
http://www.tansi.org/tools/index.html ):
https://www.tansi.org/tools/index.html ):
cat /dev/zero | wcs > /dev/mapper/to_be_wiped
@@ -821,7 +817,7 @@ A. Contributors
Remove the mapping at the end and you are done.
* 2.20 How to I wipe only the LUKS header?
* 2.20 How do I wipe only the LUKS header?
This does _not_ describe an emergency wipe procedure, see Item 5.4 for
that. This procedure here is intended to be used when the data should
@@ -911,10 +907,10 @@ A. Contributors
much longer. Also take into account that up to 8 key-slots (LUKS2: up
to 32 key-slots) have to be tried in order to find the right one.
If this is problem, you can add another key-slot using the slow machine
with the same passphrase and then remove the old key-slot. The new
key-slot will have the unlock time adjusted to the slow machine. Use
luksKeyAdd and then luksKillSlot or luksRemoveKey. You can also use
If this is the problem, you can add another key-slot using the slow
machine with the same passphrase and then remove the old key-slot. The
new key-slot will have the unlock time adjusted to the slow machine.
Use luksKeyAdd and then luksKillSlot or luksRemoveKey. You can also use
the -i option to reduce iteration time (and security level) when setting
a passphrase. Default is 1000 (1 sec) for LUKS1 and 2000 (2sec) for
LUKS2.
@@ -973,7 +969,7 @@ A. Contributors
that is intact.
In order to find out whether a key-slot is damaged one has to look for
"non-random looking" data in it. There is a tool that automatizes this
"non-random looking" data in it. There is a tool that automates this
for LUKS1 in the cryptsetup distribution from version 1.6.0 onwards. It
is located in misc/keyslot_checker/. Instructions how to use and how to
interpret results are in the README file. Note that this tool requires
@@ -991,7 +987,7 @@ A. Contributors
LUKS and dm-crypt can give the RAM quite a workout, especially when
combined with software RAID. In particular the combination RAID5 +
LUKS1 + XFS seems to uncover RAM problems that do not cause obvious
problems otherwise. Symptoms vary, but often the problem manifest
problems otherwise. Symptoms vary, but often the problem manifests
itself when copying large amounts of data, typically several times
larger than your main memory.
@@ -1085,7 +1081,7 @@ A. Contributors
5. Security Aspects
* 5.1 How long is a secure passphrase ?
* 5.1 How long is a secure passphrase?
This is just the short answer. For more info and explanation of some of
the terms used in this item, read the rest of Section 5. The actual
@@ -1124,7 +1120,7 @@ A. Contributors
i.e. I estimated the attack to be too easy. Nobody noticed ;-) On the
plus side, the tables are now (2017) pretty much accurate.
More references can be found a the end of this document. Note that
More references can be found at the end of this document. Note that
these are estimates from the defender side, so assuming something is
easier than it actually is is fine. An attacker may still have
significantly higher cost than estimated here.
@@ -1215,7 +1211,7 @@ A. Contributors
already lock you up. Hidden containers (encryption hidden within
encryption), as possible with Truecrypt, do not help either. They will
just assume the hidden container is there and unless you hand over the
key, you will stay locked up. Don't have a hidden container? Though
key, you will stay locked up. Don't have a hidden container? Tough
luck. Anybody could claim that.
Still, if you are concerned about the LUKS header, use plain dm-crypt
@@ -1271,7 +1267,7 @@ A. Contributors
single overwrite could be enough. If in doubt, use physical destruction
in addition. Here is a link to some current research results on erasing
SSDs and FLASH drives:
http://www.usenix.org/events/fast11/tech/full_papers/Wei.pdf
https://www.usenix.org/events/fast11/tech/full_papers/Wei.pdf
Keep in mind to also erase all backups.
@@ -1295,7 +1291,7 @@ A. Contributors
medium.
If your backup is on magnetic tape, I advise physical destruction by
shredding or burning, after (!) overwriting . The problem with magnetic
shredding or burning, after (!) overwriting. The problem with magnetic
tape is that it has a higher dynamic range than HDDs and older data may
well be recoverable after overwrites. Also write-head alignment issues
can lead to data not actually being deleted during overwrites.
@@ -1317,7 +1313,7 @@ A. Contributors
Overwriting the LUKS header in part or in full is the most common reason
why access to LUKS containers is lost permanently. Overwriting can be
done in a number of fashions, like creating a new filesystem on the raw
LUKS partition, making the raw partition part of a raid array and just
LUKS partition, making the raw partition part of a RAID array and just
writing to the raw partition.
The LUKS1 header contains a 256 bit "salt" per key-slot and without that
@@ -1409,7 +1405,7 @@ A. Contributors
combination of 12 truly random letters and digits.
For passphrase generation, do not use lines from very well-known texts
(religious texts, Harry potter, etc.) as they are too easy to guess.
(religious texts, Harry Potter, etc.) as they are too easy to guess.
For example, the total Harry Potter has about 1'500'000 words (my
estimation). Trying every 64 character sequence starting and ending at
a word boundary would take only something like 20 days on a single CPU
@@ -1612,8 +1608,9 @@ A. Contributors
cryptsetup -c aes-xts-plain64 luksFormat <device>
There is a potential security issue with XTS mode and large blocks.
LUKS and dm-crypt always use 512B blocks and the issue does not apply.
There is a potential security issue with XTS mode and blocks larger
than 2^20 bytes or so. LUKS and dm-crypt always use smaller blocks
and the issue does not apply.
* 5.17 Is LUKS FIPS-140-2 certified?
@@ -1701,8 +1698,9 @@ A. Contributors
can demand encryption keys.
Here is an additional reference for some problems with plausible
deniability: http://www.schneier.com/paper-truecrypt-dfs.pdf I strongly
suggest you read it.
deniability:
https://www.schneier.com/academic/paperfiles/paper-truecrypt-dfs.pdf
I strongly suggest you read it.
So, no, I will not provide any instructions on how to do it with plain
dm-crypt or LUKS. If you insist on shooting yourself in the foot, you
@@ -1847,7 +1845,7 @@ A. Contributors
document. It does require advanced skills in this age of pervasive
surveillance.)
Hence, LUKS has not kill option because it would do much more harm than
Hence, LUKS has no kill option because it would do much more harm than
good.
Still, if you have a good use-case (i.e. non-abstract real-world
@@ -1917,7 +1915,7 @@ A. Contributors
cryptsetup --header <file> luksOpen <device> </dev/mapper/name>
If that unlocks your keys-lot, you are good. Do not forget to close
If that unlocks your key-slot, you are good. Do not forget to close
the device again.
Under some circumstances (damaged header), this fails. Then use the
@@ -2037,7 +2035,7 @@ A. Contributors
* 6.5 Do I need a backup of the full partition? Would the header
and key-slots not be enough?
and key-slots not be enough?
Backup protects you against two things: Disk loss or corruption and user
error. By far the most questions on the dm-crypt mailing list about how
@@ -2631,7 +2629,7 @@ offset length name data type description
safe under these circumstances, then you have bigger problems than this
somewhat expected behavior.
The CVE was exagerrated and should not be assigned to upstream
The CVE was exaggerated and should not be assigned to upstream
cryptsetup in the first place (it is a distro specific initrd issue).
It was driven more by a try to make a splash for self-aggrandizement,
than by any actual security concerns. Ignore it.
@@ -2780,7 +2778,7 @@ offset length name data type description
Mostly not. The header has changed in its structure, but the
crytpgraphy is the same. The one exception is that PBKDF2 has been
replaced by Argon2 to give better resilience against attacks attacks by
replaced by Argon2 to give better resilience against attacks by
graphics cards and other hardware with lots of computing power but
limited local memory per computing element.
@@ -2827,7 +2825,7 @@ offset length name data type description
there to prevent precomputation.
The problem with that is that if you use a graphics card, you can massively
speed up these computations as PBKDF2 needs very little memeory to compute
speed up these computations as PBKDF2 needs very little memory to compute
it. A graphics card is (grossly simplified) a mass of small CPUs with some
small very fast local memory per CPU and a large slow memory (the 4/6/8 GB
a current card may have). If you can keep a computation in the small,
@@ -2840,7 +2838,7 @@ offset length name data type description
if you set, for example, 4GB of memory, computing Argon2 on a graphics card
with around 100kB of memory per "CPU" makes no sense at all because it is
far too slow. An attacker has hence to use real CPUs and furthermore is
limited by main memory bandwith.
limited by main memory bandwidth.
Hence the large amount of memory used is a security feature and should not
be turned off or reduced. If you really (!) understand what you are doing
@@ -2864,7 +2862,7 @@ offset length name data type description
second/slot unlock time, LUKS2 adjusts the memory parameter down if
needed. In the other direction, it will respect available memory and not
exceed it. On a current PC, the memory parameter will be somewhere around
1GB, which should quite generous. The minimum I was able to set in an
1GB, which should be quite generous. The minimum I was able to set in an
experiment with "-i 1" was 400kB of memory and that is too low to be
secure. A Raspberry Pi would probably end up somewhere around 50MB (have
not tried it) and that should still be plenty.
@@ -2994,7 +2992,7 @@ offset length name data type description
- http://news.electricalchemy.net/2009/10/password-cracking-in-cloud-part-5.html
- http://it.slashdot.org/story/12/12/05/0623215/new-25-gpu-monster-devours-strong-passwords-in-minutes
- https://it.slashdot.org/story/12/12/05/0623215/new-25-gpu-monster-devours-strong-passwords-in-minutes
* Tools

5
README
View File

@@ -14,7 +14,8 @@ FAQ:
MAILING LIST:
E-MAIL: dm-crypt@saout.de
URL: http://www.saout.de/mailman/listinfo/dm-crypt
URL: https://www.saout.de/mailman/listinfo/dm-crypt
ARCHIVE: https://lore.kernel.org/dm-crypt/
DOWNLOAD:
@@ -28,4 +29,4 @@ SOURCE CODE:
NLS (PO TRANSLATIONS):
PO files are maintained by:
http://translationproject.org/domain/cryptsetup.html
https://translationproject.org/domain/cryptsetup.html

View File

@@ -44,22 +44,16 @@ Download
--------
All release tarballs and release notes are hosted on [kernel.org](https://www.kernel.org/pub/linux/utils/cryptsetup/).
**The latest stable cryptsetup version is 2.3.2**
* [cryptsetup-2.3.2.tar.xz](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.3/cryptsetup-2.3.2.tar.xz)
* Signature [cryptsetup-2.3.2.tar.sign](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.3/cryptsetup-2.3.2.tar.sign)
**The latest stable cryptsetup version is 2.4.3**
* [cryptsetup-2.4.3.tar.xz](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.4/cryptsetup-2.4.3.tar.xz)
* Signature [cryptsetup-2.4.3.tar.sign](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.4/cryptsetup-2.4.3.tar.sign)
_(You need to decompress file first to check signature.)_
* [Cryptsetup 2.3.2 Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.3/v2.3.2-ReleaseNotes).
* [Cryptsetup 2.4.3 Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.4/v2.4.3-ReleaseNotes).
Previous versions
* [Version 2.3.1](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.3/cryptsetup-2.3.1.tar.xz) -
[Signature](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.3/cryptsetup-2.3.1.tar.sign) -
[Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.3/v2.3.1-ReleaseNotes).
* [Version 2.2.2](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.2/cryptsetup-2.2.2.tar.xz) -
[Signature](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.2/cryptsetup-2.2.2.tar.sign) -
[Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.2/v2.2.2-ReleaseNotes).
* [Version 2.0.6](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.0/cryptsetup-2.0.6.tar.xz) -
[Signature](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.0/cryptsetup-2.0.6.tar.sign) -
[Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.0/v2.0.6-ReleaseNotes).
* [Version 2.3.7](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.3/cryptsetup-2.3.7.tar.xz) -
[Signature](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.3/cryptsetup-2.3.7.tar.sign) -
[Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.3/v2.3.7-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).
@@ -73,7 +67,7 @@ For libcryptsetup documentation see [libcryptsetup API](https://mbroz.fedorapeop
The libcryptsetup API/ABI changes are tracked in [compatibility report](https://abi-laboratory.pro/tracker/timeline/cryptsetup/).
NLS PO files are maintained by [TranslationProject](http://translationproject.org/domain/cryptsetup.html).
NLS PO files are maintained by [TranslationProject](https://translationproject.org/domain/cryptsetup.html).
Help!
-----
@@ -82,5 +76,5 @@ For cryptsetup and LUKS related questions, please use the dm-crypt mailing list,
If you want to subscribe just send an empty mail to [dm-crypt-subscribe@saout.de](mailto:dm-crypt-subscribe@saout.de).
You can also browse [list archive](http://www.saout.de/pipermail/dm-crypt/) or read it through
[web interface](https://marc.info/?l=dm-crypt).
You can also browse [list archive](https://www.saout.de/pipermail/dm-crypt/) or read and search it through
[web interface on lore.kernel.org](https://lore.kernel.org/dm-crypt/) or alternatively on [marc.info](https://marc.info/?l=dm-crypt).

View File

@@ -9,16 +9,23 @@ DIE=0
(autopoint --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "**Error**: You must have autopoint installed."
echo "Download the appropriate package for your distribution,"
echo "or see http://www.gnu.org/software/gettext"
echo "Download the appropriate package for your distribution."
DIE=1
}
(msgfmt --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "**Warning**: You should have gettext installed."
echo "Download the appropriate package for your distribution."
echo "To disable translation, you can also use --disable-nls"
echo "configure option."
}
(autoconf --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "**Error**: You must have autoconf installed to."
echo "Download the appropriate package for your distribution,"
echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
echo "**Error**: You must have autoconf installed."
echo "Download the appropriate package for your distribution."
DIE=1
}
@@ -26,8 +33,7 @@ DIE=0
(libtool --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "**Error**: You must have libtool installed."
echo "Get ftp://ftp.gnu.org/pub/gnu/"
echo "(or a newer version if it is available)"
echo "Download the appropriate package for your distribution."
DIE=1
}
}
@@ -35,8 +41,7 @@ DIE=0
(automake --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "**Error**: You must have automake installed."
echo "Get ftp://ftp.gnu.org/pub/gnu/"
echo "(or a newer version if it is available)"
echo "Download the appropriate package for your distribution."
DIE=1
NO_AUTOMAKE=yes
}
@@ -47,8 +52,6 @@ test -n "$NO_AUTOMAKE" || (aclocal --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "**Error**: Missing aclocal. The version of automake"
echo "installed doesn't appear recent enough."
echo "Get ftp://ftp.gnu.org/pub/gnu/"
echo "(or a newer version if it is available)"
DIE=1
}

View File

@@ -1,5 +1,5 @@
AC_PREREQ([2.67])
AC_INIT([cryptsetup],[2.3.3])
AC_INIT([cryptsetup],[2.3.7])
dnl library version from <major>.<minor>.<release>[-<suffix>]
LIBCRYPTSETUP_VERSION=$(echo $PACKAGE_VERSION | cut -f1 -d-)
@@ -57,7 +57,6 @@ dnl ==========================================================================
AC_C_RESTRICT
AC_HEADER_DIRENT
AC_HEADER_STDC
AC_CHECK_HEADERS(fcntl.h malloc.h inttypes.h sys/ioctl.h sys/mman.h \
sys/sysmacros.h sys/statvfs.h ctype.h unistd.h locale.h byteswap.h endian.h stdint.h)
AC_CHECK_DECLS([O_CLOEXEC],,[AC_DEFINE([O_CLOEXEC],[0], [Defined to 0 if not provided])],
@@ -146,6 +145,14 @@ AC_DEFUN([NO_FIPS], [
fi
])
dnl LUKS2 online reencryption
AC_ARG_ENABLE([luks2-reencryption],
AS_HELP_STRING([--disable-luks2-reencryption], [disable LUKS2 online reencryption extension]),
[], [enable_luks2_reencryption=yes])
if test "x$enable_luks2_reencryption" = "xyes"; then
AC_DEFINE(USE_LUKS2_REENCRYPTION, 1, [Use LUKS2 online reencryption extension])
fi
dnl ==========================================================================
dnl pwquality library (cryptsetup CLI only)
AC_ARG_ENABLE([pwquality],
@@ -176,7 +183,15 @@ AC_DEFINE_UNQUOTED([PASSWDQC_CONFIG_FILE], ["$use_passwdqc_config"], [passwdqc l
if test "x$enable_passwdqc" = "xyes"; then
AC_DEFINE(ENABLE_PASSWDQC, 1, [Enable password quality checking using passwdqc library])
PASSWDQC_LIBS="-lpasswdqc"
saved_LIBS="$LIBS"
AC_SEARCH_LIBS([passwdqc_check], [passwdqc])
case "$ac_cv_search_passwdqc_check" in
no) AC_MSG_ERROR([failed to find passwdqc_check]) ;;
-l*) PASSWDQC_LIBS="$ac_cv_search_passwdqc_check" ;;
*) PASSWDQC_LIBS= ;;
esac
AC_CHECK_FUNCS([passwdqc_params_free])
LIBS="$saved_LIBS"
fi
if test "x$enable_pwquality$enable_passwdqc" = "xyesyes"; then
@@ -596,7 +611,8 @@ CS_STR_WITH([loopaes-cipher], [cipher for loop-AES mode], [aes])
CS_NUM_WITH([loopaes-keybits],[key length in bits for loop-AES mode], [256])
CS_NUM_WITH([keyfile-size-maxkb],[maximum keyfile size (in KiB)], [8192])
CS_NUM_WITH([passphrase-size-max],[maximum keyfile size (in characters)], [512])
CS_NUM_WITH([integrity-keyfile-size-maxkb],[maximum integritysetup keyfile size (in KiB)], [4])
CS_NUM_WITH([passphrase-size-max],[maximum passphrase size (in characters)], [512])
CS_STR_WITH([verity-hash], [hash function for verity mode], [sha256])
CS_NUM_WITH([verity-data-block], [data block size for verity mode], [4096])

View File

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

112
docs/v2.3.4-ReleaseNotes Normal file
View File

@@ -0,0 +1,112 @@
Cryptsetup 2.3.4 Release Notes
==============================
Stable bug-fix release with a security fix (32-bit only).
All users of cryptsetup 2.2.x and later should upgrade to this version.
Changes since version 2.3.3
~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Fix a possible out-of-bounds memory write while validating LUKS2 data
segments metadata (CVE-2020-14382).
This problem can be triggered only on 32-bit builds (64-bit systems
are not affected).
LUKS2 format validation code contains a bug in segments validation code
where the code does not check for possible overflow on memory allocation.
Due to the bug, the libcryptsetup can be tricked to expect such allocation
was successful. Later it may read data from image crafted by an attacker and
actually write such data beyond allocated memory.
The bug was introduced in cryptsetup 2.2.0. All later releases until 2.3.4
are affected.
If you only backport the fix for this CVE, these master branch git commits
should be backported:
52f5cb8cedf22fb3e14c744814ec8af7614146c7
46ee71edcd13e1dad50815ad65c28779aa6f7503
752c9a52798f11d3b765b673ebaa3058eb25316e
Thanks to Tobias Stoeckmann for discovering this issue.
* Ignore reported optimal IO size if not aligned to minimal page size.
Some USB enclosures report bogus block device topology (see lsblk -t) that
prevents LUKS2 format with 4k sector size (reported values are not correctly
aligned). The code now ignores such values and uses the default alignment.
* Added support for new no_read/write_wrokqueue dm-crypt options (kernel 5.9).
These performance options, introduced in kernel 5.9, configure dm-crypt
to bypass read or write workqueues and run encryption synchronously.
Use --perf-no_read_workqueue or --perf-no_write_workqueue cryptsetup arguments
to use these dm-crypt flags.
These options are available only for low-level dm-crypt performance tuning,
use only if you need a change to default dm-crypt behavior.
For LUKS2, these flags can be persistently stored in metadata with
the --persistent option.
* Added support panic_on_corruption option for dm-verity devices (kernel 5.9).
Veritysetup now supports --panic-on-corruption argument that configures
the dm-verity device to panics kernel if a corruption is detected.
This option is intended for specific configurations, do not use it in
standard configurations.
* Support --master-key-file option for online LUKS2 reencryption
This can be used for reencryption of devices that uses protected key AES cipher
on some mainframes crypto accelerators.
* Always return EEXIST error code if a device already exists.
Some libcryptsetup functions (activate_by*) now return EEXIST error code,
so the caller can distinguish that call fails because some parallel process
already activated the device.
Previously all fails returned EINVAL (invalid value).
* Fix a problem in integritysetup if a hash algorithm has dash in the name.
If users want to use blake2b/blake2s, the kernel algorithm name includes
a dash (like "blake2s-256").
Theses algorithms can now be used for integritysetup devices.
* Fix crypto backend to properly handle ECB mode.
Even though it should never be used, it should still work for testing :)
This fixes a bug introduced in cryptsetup version 2.3.2.
* TrueCrypt/VeraCrypt compatible mode now supports the activation of devices
with a larger sector.
TrueCrypt/VeraCrypt always uses 512-byte sector for encryption, but for devices
with a larger native sector, it stores this value in the header.
This patch allows activation of such devices, basically ignoring
the mentioned sector size.
* LUKS2: Do not create excessively large headers.
When creating a LUKS2 header with a specified --offset larger than
the LUKS2 header size, do not create a larger file than needed.
* Fix unspecified sector size for BitLocker compatible mode.
Some BitLocker devices can contain zeroed sector size in the header.
In this case, the 512-byte sector should be used.
The bug was introduced in version 2.3.3.
* Fix reading key data size in metadata for BitLocker compatible mode.
Such devices with an unexpected entry in metadata can now be activated.
Thanks to all users reporting these problems, BitLocker metadata documentation
is not publicly available, and we depend only on these reports.
* Fix typos in documentation.

181
docs/v2.3.5-ReleaseNotes Normal file
View File

@@ -0,0 +1,181 @@
Cryptsetup 2.3.5 Release Notes
==============================
Stable bug-fix release with minor extensions.
All users of cryptsetup 2.x and later should upgrade to this version.
Changes since version 2.3.4
~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Fix partial reads of passphrase from an interactive terminal.
Some stable kernels (5.3.11) started to return buffer from a terminal
in parts of maximal size 64 bytes.
This breaks the reading of passphrases longer than 64 characters
entered through an interactive terminal. The change is already fixed
in later kernel releases, but tools now support such partial read from
terminal properly.
* Fix maximal length of password entered through a terminal.
Now the maximal interactive passphrase length is exactly
512 characters (not 511).
* integritysetup: support new dm-integrity HMAC recalculation options.
In older kernels (since version 4.19), an attacker can force
an automatic recalculation of integrity tags by modifying
the dm-integrity superblock.
This is a problem with a keyed algorithms (HMAC), where it expects
nobody can trigger such recalculation without the key.
(Automatic recalculation will start after the next activation.)
Note that dm-integrity in standalone mode was *not* supposed
to provide cryptographic data integrity protection.
Despite that, we try to keep the system secure if keyed algorithms
are used.
Thank Daniel Glöckner for the original report of this problem.
Authenticated encryption that provides data integrity protection (in
combination with dm-crypt and LUKS2) is not affected by this problem.
The fix in the kernel for this problem contains two parts.
Firstly, the dm-integrity kernel module disables integrity
recalculation if keyed algorithms (HMAC) are used.
This change is included in long-term stable kernels.
Secondly, since the kernel version 5.11, dm-integrity introduces
modified protection where a journal-integrity algorithm guards
superblock; also, journal sections are protected. An attacker cannot
copy sectors from one journal section to another, and the superblock
also contains salt to prevent header replacement from another device.
If you want to protect data with HMAC, you should always also use HMAC
for --journal-integrity. Keys can be independent.
If HMAC is used for data but not for the journal, the recalculation
option is disabled.
If you need to use (insecure) backward compatibility implementation,
two new integritysetup options are introduced:
- Use --integrity-legacy-recalc (instead of --integrity-recalc)
to allow recalculation on legacy devices.
- Use --integrity-legacy-hmac in format action to force old insecure
HMAC format.
Libcryptsetup API also introduces flags
CRYPT_COMPAT_LEGACY_INTEGRITY_HMAC and
CRYPT_COMPAT_LEGACY_INTEGRITY_RECALC
to set these through crypt_set_compatibility() call.
* integritysetup: display of recalculating sector in dump command.
* veritysetup: fix verity FEC if stored in the same image with hashes.
Optional FEC (Forward Error Correction) data should cover the whole
data area, hashes (Merkle tree), and optionally additional metadata
(located after hash area).
Unfortunately, if FEC data is stored in the same file as hash,
the calculation wrongly used the whole file size, thus overlaps with
the FEC area itself. This produced unusable and too large FEC data.
There is no problem if the FEC image is a separate image.
The problem is now fixed, introducing FEC blocks calculation as:
- If the hash device is in a separate image, metadata covers the
whole rest of the image after the hash area. (Unchanged behavior.)
- If hash and FEC device is in the image, metadata ends on the FEC
area offset.
Note: there is also a fix for FEC in the dm-verity kernel (on the way
to stable kernels) that fixes error correction with larger RS roots.
* veritysetup: run FEC repair check even if root hash fails.
Note: The userspace FEC verify command reports are only informational
for now. Code does not check verity hash after FEC recovery in
userspace. The Reed-Solomon decoder can then report the possibility
that it fixed data even if parity is too damaged.
This will be fixed in the next major release.
* veritysetup: do not process hash image if hash area is empty.
Sometimes the device is so small that there is only a root hash
needed, and the hash area is not used.
Also, the size of the hash image is not increased for hash block
alignment in this case.
* veritysetup: store verity hash algorithm in superblock in lowercase.
Otherwise, the kernel could refuse the activation of the device.
* bitlk: fix a crash if the device disappears during BitLocker scan.
* bitlk: show a better error when trying to open an NTFS device.
Both BitLocker version 1 and NTFS have the same signature.
If a user opens an NTFS device without BitLocker, it now correctly
informs that it is not a BITLK device.
* bitlk: add support for startup key protected VMKs.
The startup key can be provided in --key-file option for open command.
* Fix LUKS1 repair code (regression since version 1.7.x).
We cannot trust possibly broken keyslots metadata in repair, so the
code recalculates them instead.
This makes the repair code working again when the master boot record
signature overwrites the LUKS header.
* Fix luksKeyChange for LUKS2 with assigned tokens.
The token references are now correctly assigned to the new keyslot
number.
* Fix cryptsetup resize using LUKS2 tokens.
Code needlessly asked for passphrase even though volume key was
already unlocked via LUKS2 token.
* Print a visible error if device resize is not supported.
* Add error message when suspending wrong non-LUKS device.
* Fix default XTS mode key size in reencryption.
The same luksFormat logic (double key size because XTS uses two keys)
is applied in the reencryption code.
* Rephrase missing locking directory warning and move it to debug level.
The system should later provide a safe transition to tempdir
configuration, so creating locking directory inside libcryptsetup
call is safe.
* Many fixes for the use of cipher_null (empty debug cipher).
Support for this empty cipher was intended as a debug feature and for
measuring performance overhead. Unfortunately, many systems started to
use it as an "empty shell" for LUKS (to enable encryption later).
This use is very dangerous and it creates a false sense of security.
Anyway, to not break such systems, we try to support these
configurations.
Using cipher_null in any production system is strongly discouraged!
Fixes include:
- allow LUKS resume for a device with cipher_null.
- do not upload key in keyring when data cipher is null.
- switch to default cipher when reencrypting cipher_null device.
- replace possible bogus cipher_null keyslots before reencryption.
- fix broken detection of null cipher in LUKS2.
cipher_null is no longer possible to be used in keyslot encryption
in LUKS2, it can be used only for data for debugging purposes.
* Fixes for libpasswdqc 2.0.x (optional passphrase quality check).
* Fixes for problems discovered by various tools for code analysis.
Fixes include a rework of libpopt command line option string leaks.
* Various fixes to man pages.

56
docs/v2.3.6-ReleaseNotes Normal file
View File

@@ -0,0 +1,56 @@
Cryptsetup 2.3.6 Release Notes
==============================
Stable bug-fix release with minor extensions.
All users of cryptsetup 2.x and later should upgrade to this version.
Changes since version 2.3.5
~~~~~~~~~~~~~~~~~~~~~~~~~~~
* integritysetup: Fix possible dm-integrity mapping table truncation.
While integritysetup in standalone mode (no encryption) was not
designed to provide keyed (and cryptographically strong) data
integrity protection, some options can use such algorithms (HMAC).
If a key is used, it is directly sent to the kernel dm-integrity as
a mapping table option (no key derivation is performed).
For HMAC, such a key could be quite long (up to 4096 bytes in
integritysetup CLI).
Unfortunately, due to fixed buffers and not correctly checking string
truncation, some parameter combinations could cause truncation
of the dm-integrity mapping table.
In most cases, the table was rejected by the kernel.
The worst possible case was key truncation for HMAC options
(internal_hash and journal_mac dm-integrity table options).
This release fixes possible truncation and also adds more sanity
checks to reject truncated options.
Also, integritysetup now mentions maximal allowed key size
in --help output.
For old standalone dm-integrity devices where the key length was
truncated, you have to modify (shorten) --integrity-key-size
resp. --journal-integrity-key-size option now.
This bug is _not_ present for dm-crypt/LUKS, LUKS2 (including
integrity protection), or dm-verity devices; it affects only
standalone dm-integrity with HMAC integrity protection.
* cryptsetup: Backup header can be used to activate TCRYPT device.
Use --header option to specify the header.
* cryptsetup: Avoid LUKS2 decryption without detached header.
This feature will be added later and is currently not supported.
* Additional fixes and workarounds for common warnings produced
by some static analysis tools (like gcc-11 analyzer) and additional
code hardening.
* Fix standalone libintl detection for compiled tests.
* Add Blake2b and Blake2s hash support for crypto backends.
Kernel and gcrypt crypto backend support all variants.
OpenSSL supports only Blake2b-512 and Blake2s-256.
Crypto backend supports kernel notation e.g. "blake2b-512".

95
docs/v2.3.7-ReleaseNotes Normal file
View File

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

View File

@@ -104,6 +104,7 @@ libcryptsetup_la_SOURCES = \
lib/luks2/luks2_keyslot_luks2.c \
lib/luks2/luks2_keyslot_reenc.c \
lib/luks2/luks2_reencrypt.c \
lib/luks2/luks2_reencrypt_digest.c \
lib/luks2/luks2_segment.c \
lib/luks2/luks2_token_keyring.c \
lib/luks2/luks2_token.c \

View File

@@ -1,9 +1,9 @@
/*
* BITLK (BitLocker-compatible) volume handling
*
* Copyright (C) 2019-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2019-2020 Milan Broz
* Copyright (C) 2019-2020 Vojtech Trefny
* Copyright (C) 2019-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2019-2021 Milan Broz
* Copyright (C) 2019-2021 Vojtech Trefny
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -54,6 +54,9 @@
#define BITLK_RECOVERY_PARTS 8
#define BITLK_RECOVERY_PART_LEN 6
#define BITLK_BEK_FILE_HEADER_LEN 48
#define BITLK_STARTUP_KEY_HEADER_LEN 24
#define BITLK_KDF_HASH "sha256"
#define BITLK_KDF_ITERATION_COUNT 0x100000
@@ -162,6 +165,18 @@ struct bitlk_kdf_data {
uint64_t count;
};
struct bitlk_bek_header {
uint32_t metadata_size;
uint32_t metadata_version;
uint32_t metadata_header_size;
uint32_t metada_size_copy;
struct bitlk_guid guid;
uint32_t next_nonce;
uint16_t encryption;
uint16_t unknown;
uint64_t creation_time;
} __attribute__ ((packed));
static BITLKVMKProtection get_vmk_protection(uint16_t protection)
{
switch (protection) {
@@ -311,7 +326,9 @@ static int parse_vmk_entry(struct crypt_device *cd, uint8_t *data, int start, in
bool supported = false;
/* only passphrase or recovery passphrase vmks are supported (can be used to activate) */
supported = (*vmk)->protection == BITLK_PROTECTION_PASSPHRASE || (*vmk)->protection == BITLK_PROTECTION_RECOVERY_PASSPHRASE;
supported = (*vmk)->protection == BITLK_PROTECTION_PASSPHRASE ||
(*vmk)->protection == BITLK_PROTECTION_RECOVERY_PASSPHRASE ||
(*vmk)->protection == BITLK_PROTECTION_STARTUP_KEY;
while (end - start > 2) {
/* size of this entry */
@@ -394,6 +411,9 @@ static int parse_vmk_entry(struct crypt_device *cd, uint8_t *data, int start, in
(*vmk)->name = string;
string = NULL;
}
/* no idea what this is, lets hope it's not important */
} else if (key_entry_value == BITLK_ENTRY_VALUE_USE_KEY && (*vmk)->protection == BITLK_PROTECTION_STARTUP_KEY) {
;
} else {
if (supported) {
log_err(cd, _("Unexpected metadata entry value '%u' found when parsing supported Volume Master Key."), key_entry_value);
@@ -436,6 +456,9 @@ void BITLK_bitlk_vmk_free(struct bitlk_vmk *vmk)
void BITLK_bitlk_metadata_free(struct bitlk_metadata *metadata)
{
if (!metadata)
return;
free(metadata->guid);
if (metadata->description)
free(metadata->description);
@@ -481,18 +504,6 @@ int BITLK_read_sb(struct crypt_device *cd, struct bitlk_metadata *params)
goto out;
}
if (memcmp(sig.boot_code, BITLK_BOOTCODE_V1, sizeof(sig.boot_code)) == 0) {
log_err(cd, _("BITLK version 1 is currently not supported."));
r = -ENOTSUP;
goto out;
} else if (memcmp(sig.boot_code, BITLK_BOOTCODE_V2, sizeof(sig.boot_code)) == 0)
;
else {
log_err(cd, _("Invalid or unknown boot signature for BITLK device."));
r = -EINVAL;
goto out;
}
if (memcmp(sig.signature, BITLK_SIGNATURE, sizeof(sig.signature)) == 0) {
params->togo = false;
fve_offset = BITLK_HEADER_METADATA_OFFSET;
@@ -505,7 +516,24 @@ int BITLK_read_sb(struct crypt_device *cd, struct bitlk_metadata *params)
goto out;
}
if (memcmp(sig.boot_code, BITLK_BOOTCODE_V1, sizeof(sig.boot_code)) == 0) {
log_err(cd, _("BITLK version 1 is currently not supported."));
r = -ENOTSUP;
goto out;
} else if (memcmp(sig.boot_code, BITLK_BOOTCODE_V2, sizeof(sig.boot_code)) == 0)
;
else {
log_err(cd, _("Invalid or unknown boot signature for BITLK device."));
r = -EINVAL;
goto out;
}
params->sector_size = le16_to_cpu(sig.sector_size);
if (params->sector_size == 0) {
log_dbg(cd, "Got sector size 0, assuming 512.");
params->sector_size = SECTOR_SIZE;
}
if (!(params->sector_size == 512 || params->sector_size == 4096)) {
log_err(cd, _("Unsupported sector size %" PRIu16 "."), params->sector_size);
r = -EINVAL;
@@ -559,12 +587,12 @@ int BITLK_read_sb(struct crypt_device *cd, struct bitlk_metadata *params)
switch (le16_to_cpu(fve.encryption)) {
/* AES-CBC with Elephant difuser */
case 0x8000:
params->key_size = 128;
params->key_size = 256;
params->cipher = "aes";
params->cipher_mode = "cbc-elephant";
break;
case 0x8001:
params->key_size = 256;
params->key_size = 512;
params->cipher = "aes";
params->cipher_mode = "cbc-elephant";
break;
@@ -581,12 +609,12 @@ int BITLK_read_sb(struct crypt_device *cd, struct bitlk_metadata *params)
break;
/* AES-XTS */
case 0x8004:
params->key_size = 128;
params->key_size = 256;
params->cipher = "aes";
params->cipher_mode = "xts-plain64";
break;
case 0x8005:
params->key_size = 256;
params->key_size = 512;
params->cipher = "aes";
params->cipher_mode = "xts-plain64";
break;
@@ -623,7 +651,7 @@ int BITLK_read_sb(struct crypt_device *cd, struct bitlk_metadata *params)
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) != 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)) {
log_err(cd, _("Failed to read BITLK metadata entries from %s."), device_path(device));
r = -EINVAL;
goto out;
@@ -649,6 +677,10 @@ int BITLK_read_sb(struct crypt_device *cd, struct bitlk_metadata *params)
sizeof(entry_vmk));
vmk = malloc(sizeof(struct bitlk_vmk));
if (!vmk) {
r = -ENOMEM;
goto out;
}
memset(vmk, 0, sizeof(struct bitlk_vmk));
guid_to_string(&entry_vmk.guid, guid_buf);
@@ -677,6 +709,10 @@ int BITLK_read_sb(struct crypt_device *cd, struct bitlk_metadata *params)
/* FVEK */
} else if (entry_type == BITLK_ENTRY_TYPE_FVEK) {
params->fvek = malloc(sizeof(struct bitlk_fvek));
if (!params->fvek) {
r = -ENOMEM;
goto out;
}
memcpy(params->fvek->nonce,
fve_entries + start + BITLK_ENTRY_HEADER_LEN,
sizeof(params->fvek->nonce));
@@ -833,6 +869,120 @@ static int get_recovery_key(struct crypt_device *cd,
return 0;
}
static int parse_external_key_entry(struct crypt_device *cd, const char *data, int start, int end, struct volume_key **vk)
{
uint16_t key_entry_size = 0;
uint16_t key_entry_type = 0;
uint16_t key_entry_value = 0;
size_t key_size = 0;
const char *key = NULL;
while (end - start > 2) {
/* 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;
/* type and value of this entry */
memcpy(&key_entry_type, data + start + sizeof(key_entry_size), sizeof(key_entry_type));
memcpy(&key_entry_value,
data + start + sizeof(key_entry_size) + sizeof(key_entry_type),
sizeof(key_entry_value));
key_entry_type = le16_to_cpu(key_entry_type);
key_entry_value = le16_to_cpu(key_entry_value);
/* only properties should be in this entry */
if (key_entry_type != BITLK_ENTRY_TYPE_PROPERTY) {
log_err(cd, _("Unexpected metadata entry type '%u' found when parsing external key."), key_entry_type);
return -EINVAL;
}
if (key_entry_value == BITLK_ENTRY_VALUE_KEY) {
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);
if (*vk == NULL)
return -ENOMEM;
return 0;
/* optional "ExternalKey" string, we can safely ignore it */
} else if (key_entry_value == BITLK_ENTRY_VALUE_STRING)
;
else {
log_err(cd, _("Unexpected metadata entry value '%u' found when parsing external key."), key_entry_value);
return -EINVAL;
}
start += key_entry_size;
}
/* if we got here we failed to parse the metadata */
return -EINVAL;
}
/* check if given passphrase can be a startup key (has right format) and convert it */
static int get_startup_key(struct crypt_device *cd,
const char *password,
size_t passwordLen,
const struct bitlk_vmk *vmk,
struct volume_key **su_key)
{
struct bitlk_bek_header bek_header = {0};
char guid_buf[UUID_STR_LEN] = {0};
uint16_t key_entry_size = 0;
uint16_t key_entry_type = 0;
uint16_t key_entry_value = 0;
if (passwordLen < BITLK_BEK_FILE_HEADER_LEN)
return -EPERM;
memcpy(&bek_header, password, BITLK_BEK_FILE_HEADER_LEN);
/* metadata should contain GUID of the VMK this startup key is used for */
guid_to_string(&bek_header.guid, guid_buf);
if (strcmp(guid_buf, vmk->guid) == 0)
log_dbg(cd, "Found matching startup key for VMK %s", vmk->guid);
else
return -EPERM;
if (bek_header.metadata_version != 1) {
log_err(cd, "Unsupported BEK metadata version %" PRIu32 "", 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);
return -EINVAL;
}
/* we are expecting exactly one metadata entry starting immediately after the header */
memcpy(&key_entry_size, password + BITLK_BEK_FILE_HEADER_LEN, sizeof(key_entry_size));
key_entry_size = le16_to_cpu(key_entry_size);
if (key_entry_size < BITLK_ENTRY_HEADER_LEN) {
log_dbg(cd, "Unexpected metadata entry size %" PRIu16 " when parsing BEK file", key_entry_size);
return -EINVAL;
}
/* type and value of this entry */
memcpy(&key_entry_type, password + BITLK_BEK_FILE_HEADER_LEN + sizeof(key_entry_size), sizeof(key_entry_type));
memcpy(&key_entry_value,
password + BITLK_BEK_FILE_HEADER_LEN + sizeof(key_entry_size) + sizeof(key_entry_type),
sizeof(key_entry_value));
key_entry_type = le16_to_cpu(key_entry_type);
key_entry_value = le16_to_cpu(key_entry_value);
if (key_entry_type == BITLK_ENTRY_TYPE_STARTUP_KEY && key_entry_value == BITLK_ENTRY_VALUE_EXTERNAL_KEY) {
return parse_external_key_entry(cd, password,
BITLK_BEK_FILE_HEADER_LEN + BITLK_ENTRY_HEADER_LEN + BITLK_STARTUP_KEY_HEADER_LEN,
passwordLen, su_key);
} else {
log_err(cd, _("Unexpected metadata entry found when parsing startup key."));
log_dbg(cd, "Entry type: %u, entry value: %u", key_entry_type, key_entry_value);
return -EINVAL;
}
}
static int bitlk_kdf(struct crypt_device *cd,
const char *password,
size_t passwordLen,
@@ -908,7 +1058,7 @@ static int decrypt_key(struct crypt_device *cd,
{
char *outbuf;
int r;
uint32_t key_size = 0;
uint16_t key_size = 0;
outbuf = crypt_safe_alloc(enc_key->keylength);
if (!outbuf)
@@ -923,16 +1073,18 @@ static int decrypt_key(struct crypt_device *cd,
}
/* key_data has it's size as part of the metadata */
memcpy(&key_size, outbuf, 4);
key_size = le32_to_cpu(key_size);
memcpy(&key_size, outbuf, 2);
key_size = le16_to_cpu(key_size);
if (enc_key->keylength != key_size) {
log_err(cd, _("Wrong key size."));
log_err(cd, _("Unexpected key data size."));
log_dbg(cd, "Expected key data size: %zu, got %" PRIu16 "", enc_key->keylength, key_size);
r = -EINVAL;
goto out;
}
if (is_fvek && strcmp(crypt_get_cipher_mode(cd), "cbc-elephant") == 0 &&
crypt_get_volume_key_size(cd) == 16) {
crypt_get_volume_key_size(cd) == 32) {
/* 128bit AES-CBC with Elephant -- key size is 256 bit (2 keys) but key data is 512 bits,
data: 16B CBC key, 16B empty, 16B elephant key, 16B empty */
memcpy(outbuf + 16 + BITLK_OPEN_KEY_METADATA_LEN,
@@ -993,12 +1145,18 @@ int BITLK_activate(struct crypt_device *cd,
while (next_vmk) {
if (next_vmk->protection == BITLK_PROTECTION_PASSPHRASE) {
r = bitlk_kdf(cd, password, passwordLen, false, next_vmk->salt, &vmk_dec_key);
if (r)
return r;
if (r) {
/* something wrong happened, but we still want to check other key slots */
next_vmk = next_vmk->next;
continue;
}
} else if (next_vmk->protection == BITLK_PROTECTION_RECOVERY_PASSPHRASE) {
r = get_recovery_key(cd, password, passwordLen, &recovery_key);
if (r)
return r;
if (r) {
/* something wrong happened, but we still want to check other key slots */
next_vmk = next_vmk->next;
continue;
}
if (recovery_key == NULL) {
/* r = 0 but no key -> given passphrase is not a recovery passphrase */
r = -EPERM;
@@ -1011,8 +1169,15 @@ int BITLK_activate(struct crypt_device *cd,
crypt_free_volume_key(recovery_key);
if (r)
return r;
} else if (next_vmk->protection == BITLK_PROTECTION_STARTUP_KEY) {
r = get_startup_key(cd, password, passwordLen, next_vmk, &vmk_dec_key);
if (r) {
next_vmk = next_vmk->next;
continue;
}
log_dbg(cd, "Trying to use external key found in provided password.");
} else {
/* only passphrase and recovery passphrase VMKs supported right now */
/* only passphrase, recovery passphrase and startup key VMKs supported right now */
log_dbg(cd, "Skipping %s", get_vmk_protection_string(next_vmk->protection));
next_vmk = next_vmk->next;
if (r == 0)

View File

@@ -1,9 +1,9 @@
/*
* BITLK (BitLocker-compatible) header definition
*
* Copyright (C) 2019-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2019-2020 Milan Broz
* Copyright (C) 2019-2020 Vojtech Trefny
* Copyright (C) 2019-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2019-2021 Milan Broz
* Copyright (C) 2019-2021 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-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2020 Milan Broz
* Copyright (C) 2010-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2021 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

@@ -8,8 +8,8 @@
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
* these licenses can be found at:
*
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
* - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
*
* You should have received a copy of both of these licenses along with this
* software. If not, they may be obtained at the above URLs.
@@ -450,6 +450,8 @@ const char *argon2_error_message(int error_code) {
size_t argon2_encodedlen(uint32_t t_cost, uint32_t m_cost, uint32_t parallelism,
uint32_t saltlen, uint32_t hashlen, argon2_type type) {
if (!argon2_type2string(type, 0))
return 0;
return strlen("$$v=$m=,t=,p=$$") + strlen(argon2_type2string(type, 0)) +
numlen(t_cost) + numlen(m_cost) + numlen(parallelism) +
b64len(saltlen) + b64len(hashlen) + numlen(ARGON2_VERSION_NUMBER) + 1;

View File

@@ -8,8 +8,8 @@
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
* these licenses can be found at:
*
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
* - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
*
* You should have received a copy of both of these licenses along with this
* software. If not, they may be obtained at the above URLs.

View File

@@ -8,8 +8,8 @@
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
* these licenses can be found at:
*
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
* - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
*
* You should have received a copy of both of these licenses along with this
* software. If not, they may be obtained at the above URLs.

View File

@@ -8,8 +8,8 @@
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
* these licenses can be found at:
*
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
* - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
*
* You should have received a copy of both of these licenses along with this
* software. If not, they may be obtained at the above URLs.

View File

@@ -8,8 +8,8 @@
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
* these licenses can be found at:
*
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
* - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
*
* You should have received a copy of both of these licenses along with this
* software. If not, they may be obtained at the above URLs.

View File

@@ -8,8 +8,8 @@
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
* these licenses can be found at:
*
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
* - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
*
* You should have received a copy of both of these licenses along with this
* software. If not, they may be obtained at the above URLs.

View File

@@ -8,8 +8,8 @@
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
* these licenses can be found at:
*
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
* - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
*
* You should have received a copy of both of these licenses along with this
* software. If not, they may be obtained at the above URLs.

View File

@@ -8,8 +8,8 @@
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
* these licenses can be found at:
*
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
* - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
*
* You should have received a copy of both of these licenses along with this
* software. If not, they may be obtained at the above URLs.

View File

@@ -8,8 +8,8 @@
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
* these licenses can be found at:
*
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
* - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
*
* You should have received a copy of both of these licenses along with this
* software. If not, they may be obtained at the above URLs.

View File

@@ -8,8 +8,8 @@
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
* these licenses can be found at:
*
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
* - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
*
* You should have received a copy of both of these licenses along with this
* software. If not, they may be obtained at the above URLs.

View File

@@ -8,8 +8,8 @@
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
* these licenses can be found at:
*
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
* - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
*
* You should have received a copy of both of these licenses along with this
* software. If not, they may be obtained at the above URLs.

View File

@@ -8,8 +8,8 @@
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
* these licenses can be found at:
*
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
* - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
*
* You should have received a copy of both of these licenses along with this
* software. If not, they may be obtained at the above URLs.

View File

@@ -8,8 +8,8 @@
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
* these licenses can be found at:
*
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
* - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
*
* You should have received a copy of both of these licenses along with this
* software. If not, they may be obtained at the above URLs.

View File

@@ -8,8 +8,8 @@
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
* these licenses can be found at:
*
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
* - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
*
* You should have received a copy of both of these licenses along with this
* software. If not, they may be obtained at the above URLs.

View File

@@ -8,8 +8,8 @@
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
* these licenses can be found at:
*
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
* - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
*
* You should have received a copy of both of these licenses along with this
* software. If not, they may be obtained at the above URLs.

View File

@@ -1,8 +1,8 @@
/*
* Argon2 PBKDF2 library wrapper
*
* Copyright (C) 2016-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2016-2020 Milan Broz
* Copyright (C) 2016-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2016-2021 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-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2018-2020 Milan Broz
* Copyright (C) 2018-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2018-2021 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-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2018-2020 Milan Broz
* Copyright (C) 2018-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2018-2021 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 @@
/*
* crypto backend implementation
*
* Copyright (C) 2010-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2020 Milan Broz
* Copyright (C) 2010-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2021 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,7 +109,7 @@ int crypt_cipher_check_kernel(const char *name, const char *mode,
/* Storage encryption wrappers */
int crypt_storage_init(struct crypt_storage **ctx, size_t sector_size,
const char *cipher, const char *cipher_mode,
const void *key, size_t key_length);
const void *key, size_t key_length, bool large_iv);
void crypt_storage_destroy(struct crypt_storage *ctx);
int crypt_storage_decrypt(struct crypt_storage *ctx, uint64_t iv_offset,
uint64_t length, char *buffer);

View File

@@ -1,8 +1,8 @@
/*
* crypto backend implementation
*
* Copyright (C) 2010-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2020 Milan Broz
* Copyright (C) 2010-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2021 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-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2020 Milan Broz
* Copyright (C) 2012-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2021 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -96,11 +96,14 @@ int crypt_cipher_init_kernel(struct crypt_cipher_kernel *ctx, const char *name,
.salg_family = AF_ALG,
.salg_type = "skcipher",
};
int r;
if (!strcmp(name, "cipher_null"))
key_length = 0;
snprintf((char *)sa.salg_name, sizeof(sa.salg_name), "%s(%s)", mode, name);
r = snprintf((char *)sa.salg_name, sizeof(sa.salg_name), "%s(%s)", mode, name);
if (r < 0 || (size_t)r >= sizeof(sa.salg_name))
return -EINVAL;
return _crypt_cipher_init(ctx, key, key_length, 0, &sa);
}
@@ -152,6 +155,9 @@ static int _crypt_cipher_crypt(struct crypt_cipher_kernel *ctx,
/* Set IV */
if (iv) {
header = CMSG_NXTHDR(&msg, header);
if (!header)
return -EINVAL;
header->cmsg_level = SOL_ALG;
header->cmsg_type = ALG_SET_IV;
header->cmsg_len = iv_msg_size;
@@ -227,7 +233,10 @@ int crypt_cipher_check_kernel(const char *name, const char *mode,
}
salg_type = aead ? "aead" : "skcipher";
snprintf((char *)sa.salg_type, sizeof(sa.salg_type), "%s", salg_type);
r = snprintf((char *)sa.salg_type, sizeof(sa.salg_type), "%s", salg_type);
if (r < 0 || (size_t)r >= sizeof(sa.salg_name))
return -EINVAL;
memset(tmp_salg_name, 0, sizeof(tmp_salg_name));
/* FIXME: this is duplicating a part of devmapper backend */
@@ -240,7 +249,7 @@ int crypt_cipher_check_kernel(const char *name, const char *mode,
else
r = snprintf(tmp_salg_name, sizeof(tmp_salg_name), "%s(%s)", real_mode, name);
if (r <= 0 || r > (int)(sizeof(sa.salg_name) - 1))
if (r < 0 || (size_t)r >= sizeof(tmp_salg_name))
return -EINVAL;
memcpy(sa.salg_name, tmp_salg_name, sizeof(sa.salg_name));

View File

@@ -1,8 +1,8 @@
/*
* GCRYPT crypto backend implementation
*
* Copyright (C) 2010-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2020 Milan Broz
* Copyright (C) 2010-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2021 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,9 +51,14 @@ struct crypt_cipher {
} u;
};
struct hash_alg {
const char *name;
const char *gcrypt_name;
};
/*
* Test for wrong Whirlpool variant,
* Ref: http://lists.gnupg.org/pipermail/gcrypt-devel/2014-January/002889.html
* Ref: https://lists.gnupg.org/pipermail/gcrypt-devel/2014-January/002889.html
*/
static void crypt_hash_test_whirlpool_bug(void)
{
@@ -91,6 +96,8 @@ static void crypt_hash_test_whirlpool_bug(void)
int crypt_backend_init(void)
{
int r;
if (crypto_backend_initialised)
return 0;
@@ -120,11 +127,12 @@ int crypt_backend_init(void)
crypto_backend_initialised = 1;
crypt_hash_test_whirlpool_bug();
snprintf(version, 64, "gcrypt %s%s%s",
r = snprintf(version, sizeof(version), "gcrypt %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" : "");
if (r < 0 || (size_t)r >= sizeof(version))
return -EINVAL;
return 0;
}
@@ -150,10 +158,24 @@ uint32_t crypt_backend_flags(void)
static const char *crypt_hash_compat_name(const char *name, unsigned int *flags)
{
const char *hash_name = name;
int i;
static struct hash_alg hash_algs[] = {
{ "blake2b-160", "blake2b_160" },
{ "blake2b-256", "blake2b_256" },
{ "blake2b-384", "blake2b_384" },
{ "blake2b-512", "blake2b_512" },
{ "blake2s-128", "blake2s_128" },
{ "blake2s-160", "blake2s_160" },
{ "blake2s-224", "blake2s_224" },
{ "blake2s-256", "blake2s_256" },
{ NULL, NULL, }};
if (!name)
return NULL;
/* "whirlpool_gcryptbug" is out shortcut to flawed whirlpool
* in libgcrypt < 1.6.0 */
if (name && !strcasecmp(name, "whirlpool_gcryptbug")) {
if (!strcasecmp(name, "whirlpool_gcryptbug")) {
#if GCRYPT_VERSION_NUMBER >= 0x010601
if (flags)
*flags |= GCRY_MD_FLAG_BUGEMU1;
@@ -161,6 +183,15 @@ static const char *crypt_hash_compat_name(const char *name, unsigned int *flags)
hash_name = "whirlpool";
}
i = 0;
while (hash_algs[i].name) {
if (!strcasecmp(name, hash_algs[i].name)) {
hash_name = hash_algs[i].gcrypt_name;
break;
}
i++;
}
return hash_name;
}

View File

@@ -1,8 +1,8 @@
/*
* Linux kernel userspace API crypto backend implementation
*
* Copyright (C) 2010-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2020 Milan Broz
* Copyright (C) 2010-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2021 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -62,6 +62,14 @@ static struct hash_alg hash_algs[] = {
{ "stribog256","streebog256", 32, 64 },
{ "stribog512","streebog512", 64, 64 },
{ "sm3", "sm3", 32, 64 },
{ "blake2b-160","blake2b-160",20, 128 },
{ "blake2b-256","blake2b-256",32, 128 },
{ "blake2b-384","blake2b-384",48, 128 },
{ "blake2b-512","blake2b-512",64, 128 },
{ "blake2s-128","blake2s-128",16, 64 },
{ "blake2s-160","blake2s-160",20, 64 },
{ "blake2s-224","blake2s-224",28, 64 },
{ "blake2s-256","blake2s-256",32, 64 },
{ NULL, NULL, 0, 0 }
};
@@ -118,7 +126,7 @@ int crypt_backend_init(void)
.salg_type = "hash",
.salg_name = "sha256",
};
int tfmfd = -1, opfd = -1;
int r, tfmfd = -1, opfd = -1;
if (crypto_backend_initialised)
return 0;
@@ -126,15 +134,17 @@ int crypt_backend_init(void)
if (uname(&uts) == -1 || strcmp(uts.sysname, "Linux"))
return -EINVAL;
r = snprintf(version, sizeof(version), "%s %s kernel cryptoAPI",
uts.sysname, uts.release);
if (r < 0 || (size_t)r >= sizeof(version))
return -EINVAL;
if (crypt_kernel_socket_init(&sa, &tfmfd, &opfd, NULL, 0) < 0)
return -EINVAL;
close(tfmfd);
close(opfd);
snprintf(version, sizeof(version), "%s %s kernel cryptoAPI",
uts.sysname, uts.release);
crypto_backend_initialised = 1;
return 0;
}
@@ -255,6 +265,7 @@ int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
.salg_family = AF_ALG,
.salg_type = "hash",
};
int r;
h = malloc(sizeof(*h));
if (!h)
@@ -267,8 +278,12 @@ int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
}
h->hash_len = ha->length;
snprintf((char *)sa.salg_name, sizeof(sa.salg_name),
r = snprintf((char *)sa.salg_name, sizeof(sa.salg_name),
"hmac(%s)", ha->kernel_name);
if (r < 0 || (size_t)r >= sizeof(sa.salg_name)) {
free(h);
return -EINVAL;
}
if (crypt_kernel_socket_init(&sa, &h->tfmfd, &h->opfd, key, key_length) < 0) {
free(h);

View File

@@ -1,8 +1,8 @@
/*
* Nettle crypto backend implementation
*
* Copyright (C) 2011-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2011-2020 Milan Broz
* Copyright (C) 2011-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2011-2021 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-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2020 Milan Broz
* Copyright (C) 2010-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2021 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -77,6 +77,8 @@ static struct hash_alg *_get_alg(const char *name)
int crypt_backend_init(void)
{
int r;
if (crypto_backend_initialised)
return 0;
@@ -84,10 +86,13 @@ int crypt_backend_init(void)
return -EINVAL;
#if HAVE_DECL_NSS_GETVERSION
snprintf(version, 64, "NSS %s", NSS_GetVersion());
r = snprintf(version, sizeof(version), "NSS %s", NSS_GetVersion());
#else
snprintf(version, 64, "NSS");
r = snprintf(version, sizeof(version), "NSS");
#endif
if (r < 0 || (size_t)r >= sizeof(version))
return -EINVAL;
crypto_backend_initialised = 1;
return 0;
}

View File

@@ -1,8 +1,8 @@
/*
* OPENSSL crypto backend implementation
*
* Copyright (C) 2010-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2020 Milan Broz
* Copyright (C) 2010-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2021 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -63,6 +63,11 @@ struct crypt_cipher {
} u;
};
struct hash_alg {
const char *name;
const char *openssl_name;
};
/*
* Compatible wrappers for OpenSSL < 1.1.0 and LibreSSL < 2.7.0
*/
@@ -147,11 +152,36 @@ const char *crypt_backend_version(void)
return openssl_backend_version();
}
static const char *crypt_hash_compat_name(const char *name)
{
const char *hash_name = name;
int i;
static struct hash_alg hash_algs[] = {
{ "blake2b-512", "blake2b512" },
{ "blake2s-256", "blake2s256" },
{ NULL, NULL, }};
if (!name)
return NULL;
i = 0;
while (hash_algs[i].name) {
if (!strcasecmp(name, hash_algs[i].name)) {
hash_name = hash_algs[i].openssl_name;
break;
}
i++;
}
return hash_name;
}
/* HASH */
int crypt_hash_size(const char *name)
{
const EVP_MD *hash_id = EVP_get_digestbyname(name);
const EVP_MD *hash_id;
hash_id = EVP_get_digestbyname(crypt_hash_compat_name(name));
if (!hash_id)
return -EINVAL;
@@ -172,7 +202,7 @@ int crypt_hash_init(struct crypt_hash **ctx, const char *name)
return -ENOMEM;
}
h->hash_id = EVP_get_digestbyname(name);
h->hash_id = EVP_get_digestbyname(crypt_hash_compat_name(name));
if (!h->hash_id) {
EVP_MD_CTX_free(h->md);
free(h);
@@ -257,7 +287,7 @@ int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
return -ENOMEM;
}
h->hash_id = EVP_get_digestbyname(name);
h->hash_id = EVP_get_digestbyname(crypt_hash_compat_name(name));
if (!h->hash_id) {
HMAC_CTX_free(h->md);
free(h);
@@ -333,7 +363,7 @@ int crypt_pbkdf(const char *kdf, const char *hash,
return -EINVAL;
if (!strcmp(kdf, "pbkdf2")) {
hash_id = EVP_get_digestbyname(hash);
hash_id = EVP_get_digestbyname(crypt_hash_compat_name(hash));
if (!hash_id)
return -EINVAL;
@@ -372,7 +402,7 @@ static int _cipher_init(EVP_CIPHER_CTX **hd_enc, EVP_CIPHER_CTX **hd_dec, const
key_bits /= 2;
r = snprintf(cipher_name, sizeof(cipher_name), "%s-%d-%s", name, key_bits, mode);
if (r < 0 || r >= (int)sizeof(cipher_name))
if (r < 0 || (size_t)r >= sizeof(cipher_name))
return -EINVAL;
type = EVP_get_cipherbyname(cipher_name);

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-2020 Milan Broz
* Copyright (C) 2014-2021 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -40,7 +40,7 @@ struct crypt_sector_iv {
/* Block encryption storage context */
struct crypt_storage {
unsigned sector_shift;
size_t sector_size;
unsigned iv_shift;
struct crypt_cipher *cipher;
struct crypt_sector_iv cipher_iv;
@@ -56,14 +56,15 @@ static int int_log2(unsigned int x)
static int crypt_sector_iv_init(struct crypt_sector_iv *ctx,
const char *cipher_name, const char *mode_name,
const char *iv_name, const void *key, size_t key_length, size_t sector_size)
const char *iv_name, const void *key, size_t key_length,
size_t sector_size)
{
int r;
memset(ctx, 0, sizeof(*ctx));
ctx->iv_size = crypt_cipher_ivsize(cipher_name, mode_name);
if (ctx->iv_size < 8)
if (ctx->iv_size < 0 || (strcmp(mode_name, "ecb") && ctx->iv_size < 8))
return -ENOENT;
if (!strcmp(cipher_name, "cipher_null") ||
@@ -212,7 +213,8 @@ int crypt_storage_init(struct crypt_storage **ctx,
size_t sector_size,
const char *cipher,
const char *cipher_mode,
const void *key, size_t key_length)
const void *key, size_t key_length,
bool large_iv)
{
struct crypt_storage *s;
char mode_name[64];
@@ -250,8 +252,8 @@ int crypt_storage_init(struct crypt_storage **ctx,
return r;
}
s->sector_shift = int_log2(sector_size);
s->iv_shift = s->sector_shift - SECTOR_SHIFT;
s->sector_size = sector_size;
s->iv_shift = large_iv ? int_log2(sector_size) - SECTOR_SHIFT : 0;
*ctx = s;
return 0;
@@ -264,19 +266,20 @@ int crypt_storage_decrypt(struct crypt_storage *ctx,
uint64_t i;
int r = 0;
if (length & ((1 << ctx->sector_shift) - 1))
if (length & (ctx->sector_size - 1))
return -EINVAL;
length >>= ctx->sector_shift;
if (iv_offset & ((ctx->sector_size >> SECTOR_SHIFT) - 1))
return -EINVAL;
for (i = 0; i < length; i++) {
r = crypt_sector_iv_generate(&ctx->cipher_iv, iv_offset + (uint64_t)(i << ctx->iv_shift));
for (i = 0; i < length; i += ctx->sector_size) {
r = crypt_sector_iv_generate(&ctx->cipher_iv, (iv_offset + (i >> SECTOR_SHIFT)) >> ctx->iv_shift);
if (r)
break;
r = crypt_cipher_decrypt(ctx->cipher,
&buffer[i << ctx->sector_shift],
&buffer[i << ctx->sector_shift],
1 << ctx->sector_shift,
&buffer[i],
&buffer[i],
ctx->sector_size,
ctx->cipher_iv.iv,
ctx->cipher_iv.iv_size);
if (r)
@@ -293,19 +296,20 @@ int crypt_storage_encrypt(struct crypt_storage *ctx,
uint64_t i;
int r = 0;
if (length & ((1 << ctx->sector_shift) - 1))
if (length & (ctx->sector_size - 1))
return -EINVAL;
length >>= ctx->sector_shift;
if (iv_offset & ((ctx->sector_size >> SECTOR_SHIFT) - 1))
return -EINVAL;
for (i = 0; i < length; i++) {
r = crypt_sector_iv_generate(&ctx->cipher_iv, iv_offset + (i << ctx->iv_shift));
for (i = 0; i < length; i += ctx->sector_size) {
r = crypt_sector_iv_generate(&ctx->cipher_iv, (iv_offset + (i >> SECTOR_SHIFT)) >> ctx->iv_shift);
if (r)
break;
r = crypt_cipher_encrypt(ctx->cipher,
&buffer[i << ctx->sector_shift],
&buffer[i << ctx->sector_shift],
1 << ctx->sector_shift,
&buffer[i],
&buffer[i],
ctx->sector_size,
ctx->cipher_iv.iv,
ctx->cipher_iv.iv_size);
if (r)

View File

@@ -4,8 +4,8 @@
* Copyright (C) 2004 Free Software Foundation
*
* cryptsetup related changes
* Copyright (C) 2012-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2020 Milan Broz
* Copyright (C) 2012-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2021 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-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2020 Milan Broz
* Copyright (C) 2012-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2021 Milan Broz
* Copyright (C) 2016-2020 Ondrej Mosnacek
*
* This file is free software; you can redistribute it and/or
@@ -361,8 +361,10 @@ static int crypt_pbkdf_check(const char *kdf, const char *hash,
ms = time_ms(&rstart, &rend);
if (ms) {
PBKDF2_temp = (double)iterations * target_ms / ms;
if (PBKDF2_temp > UINT32_MAX)
return -EINVAL;
if (PBKDF2_temp > UINT32_MAX) {
r = -EINVAL;
goto out;
}
*iter_secs = (uint32_t)PBKDF2_temp;
}

View File

@@ -1,7 +1,7 @@
/*
* Integrity volume handling
*
* Copyright (C) 2016-2020 Milan Broz
* Copyright (C) 2016-2021 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -40,7 +40,7 @@ static int INTEGRITY_read_superblock(struct crypt_device *cd,
if (read_lseek_blockwise(devfd, device_block_size(cd, device),
device_alignment(device), sb, sizeof(*sb), offset) != sizeof(*sb) ||
memcmp(sb->magic, SB_MAGIC, sizeof(sb->magic)) ||
sb->version < SB_VERSION_1 || sb->version > SB_VERSION_4) {
sb->version < SB_VERSION_1 || sb->version > SB_VERSION_5) {
log_std(cd, "No integrity superblock detected on %s.\n",
device_path(device));
r = -EINVAL;
@@ -92,14 +92,15 @@ int INTEGRITY_dump(struct crypt_device *cd, struct device *device, uint64_t offs
log_std(cd, "journal_sections %u\n", sb.journal_sections);
log_std(cd, "provided_data_sectors %" PRIu64 "\n", sb.provided_data_sectors);
log_std(cd, "sector_size %u\n", SECTOR_SIZE << sb.log2_sectors_per_block);
if (sb.version == SB_VERSION_2 && (sb.flags & SB_FLAG_RECALCULATING))
if (sb.version >= SB_VERSION_2 && (sb.flags & SB_FLAG_RECALCULATING))
log_std(cd, "recalc_sector %" PRIu64 "\n", sb.recalc_sector);
log_std(cd, "log2_blocks_per_bitmap %u\n", sb.log2_blocks_per_bitmap_bit);
log_std(cd, "flags %s%s%s%s\n",
log_std(cd, "flags %s%s%s%s%s\n",
sb.flags & SB_FLAG_HAVE_JOURNAL_MAC ? "have_journal_mac " : "",
sb.flags & SB_FLAG_RECALCULATING ? "recalculating " : "",
sb.flags & SB_FLAG_DIRTY_BITMAP ? "dirty_bitmap " : "",
sb.flags & SB_FLAG_FIXED_PADDING ? "fix_padding " : "");
sb.flags & SB_FLAG_FIXED_PADDING ? "fix_padding " : "",
sb.flags & SB_FLAG_FIXED_HMAC ? "fix_hmac " : "");
return 0;
}
@@ -278,6 +279,15 @@ int INTEGRITY_activate_dmd_device(struct crypt_device *cd,
return -ENOTSUP;
}
if (r < 0 && (dmd->flags & CRYPT_ACTIVATE_RECALCULATE) &&
!(crypt_get_compatibility(cd) & CRYPT_COMPAT_LEGACY_INTEGRITY_RECALC) &&
((sb_flags & SB_FLAG_FIXED_HMAC) ?
(tgt->u.integrity.vk && !tgt->u.integrity.journal_integrity_key) :
(tgt->u.integrity.vk || tgt->u.integrity.journal_integrity_key))) {
log_err(cd, _("Kernel refuses to activate insecure recalculate option (see legacy activation options to override)."));
return -ENOTSUP;
}
return r;
}
@@ -320,7 +330,9 @@ int INTEGRITY_format(struct crypt_device *cd,
uuid_generate(tmp_uuid_bin);
uuid_unparse(tmp_uuid_bin, tmp_uuid);
snprintf(tmp_name, sizeof(tmp_name), "temporary-cryptsetup-%s", tmp_uuid);
r = snprintf(tmp_name, sizeof(tmp_name), "temporary-cryptsetup-%s", tmp_uuid);
if (r < 0 || (size_t)r >= sizeof(tmp_name))
return -EINVAL;
/* There is no data area, we can actually use fake zeroed key */
if (params && params->integrity_key_size)

View File

@@ -1,7 +1,7 @@
/*
* Integrity header definition
*
* Copyright (C) 2016-2020 Milan Broz
* Copyright (C) 2016-2021 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -35,11 +35,13 @@ struct crypt_dm_active_device;
#define SB_VERSION_2 2
#define SB_VERSION_3 3
#define SB_VERSION_4 4
#define SB_VERSION_5 5
#define SB_FLAG_HAVE_JOURNAL_MAC (1 << 0)
#define SB_FLAG_RECALCULATING (1 << 1) /* V2 only */
#define SB_FLAG_DIRTY_BITMAP (1 << 2) /* V3 only */
#define SB_FLAG_FIXED_PADDING (1 << 3) /* V4 only */
#define SB_FLAG_FIXED_HMAC (1 << 4) /* V5 only */
struct superblock {
uint8_t magic[8];

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-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2020 Milan Broz
* Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2021 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -83,7 +83,7 @@
#endif
struct crypt_device;
struct luks2_reenc_context;
struct luks2_reencrypt;
struct volume_key {
int id;
@@ -222,8 +222,8 @@ int PLAIN_activate(struct crypt_device *cd,
uint32_t flags);
void *crypt_get_hdr(struct crypt_device *cd, const char *type);
void crypt_set_reenc_context(struct crypt_device *cd, struct luks2_reenc_context *rh);
struct luks2_reenc_context *crypt_get_reenc_context(struct crypt_device *cd);
void crypt_set_luks2_reencrypt(struct crypt_device *cd, struct luks2_reencrypt *rh);
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);
@@ -266,4 +266,12 @@ int crypt_compare_dm_devices(struct crypt_device *cd,
const struct crypt_dm_active_device *tgt);
static inline void *crypt_zalloc(size_t size) { return calloc(1, size); }
static inline bool uint64_mult_overflow(uint64_t *u, uint64_t b, size_t size)
{
*u = (uint64_t)b * size;
if ((uint64_t)(*u / size) != b)
return true;
return false;
}
#endif /* INTERNAL_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-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2020 Milan Broz
* Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2021 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -652,6 +652,10 @@ uint32_t crypt_get_compatibility(struct crypt_device *cd);
/** dm-integrity device uses less effective (legacy) padding (old kernels) */
#define CRYPT_COMPAT_LEGACY_INTEGRITY_PADDING (1 << 0)
/** dm-integrity device does not protect superblock with HMAC (old kernels) */
#define CRYPT_COMPAT_LEGACY_INTEGRITY_HMAC (1 << 1)
/** dm-integrity allow recalculating of volumes with HMAC keys (old kernels) */
#define CRYPT_COMPAT_LEGACY_INTEGRITY_RECALC (1 << 2)
/**
* Convert to new type for already existing device.
@@ -1103,6 +1107,12 @@ int crypt_keyslot_destroy(struct crypt_device *cd, int keyslot);
#define CRYPT_ACTIVATE_SUSPENDED (1 << 21)
/** use IV sector counted in sector_size instead of default 512 bytes sectors */
#define CRYPT_ACTIVATE_IV_LARGE_SECTORS (1 << 22)
/** dm-verity: panic_on_corruption flag - panic kernel on corruption */
#define CRYPT_ACTIVATE_PANIC_ON_CORRUPTION (1 << 23)
/** dm-crypt: bypass internal workqueue and process read requests synchronously. */
#define CRYPT_ACTIVATE_NO_READ_WORKQUEUE (1 << 24)
/** dm-crypt: bypass internal workqueue and process write requests synchronously. */
#define CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE (1 << 25)
/**
* Active device runtime attributes
@@ -1479,11 +1489,11 @@ const char *crypt_get_cipher_mode(struct crypt_device *cd);
const char *crypt_get_uuid(struct crypt_device *cd);
/**
* Get path to underlaying device.
* Get path to underlying device.
*
* @param cd crypt device handle
*
* @return path to underlaying device name
* @return path to underlying device name
*
*/
const char *crypt_get_device_name(struct crypt_device *cd);
@@ -1493,7 +1503,7 @@ const char *crypt_get_device_name(struct crypt_device *cd);
*
* @param cd crypt device handle
*
* @return path to underlaying device name
* @return path to underlying device name
*
*/
const char *crypt_get_metadata_device_name(struct crypt_device *cd);
@@ -2194,6 +2204,8 @@ int crypt_activate_by_token(struct crypt_device *cd,
#define CRYPT_REENCRYPT_RESUME_ONLY (1 << 2)
/** Run reencryption recovery only. (in) */
#define CRYPT_REENCRYPT_RECOVERY (1 << 3)
/** Reencryption requires metadata protection. (in/out) */
#define CRYPT_REENCRYPT_REPAIR_NEEDED (1 << 4)
/**
* Reencryption direction
@@ -2289,7 +2301,7 @@ int crypt_reencrypt_init_by_keyring(struct crypt_device *cd,
* Run data reencryption.
*
* @param cd crypt device handle
* @param progress is a callback funtion reporting device \b size,
* @param progress is a callback function reporting device \b size,
* current \b offset of reencryption and provided \b usrptr identification
*
* @return @e 0 on success or negative errno value otherwise.
@@ -2330,17 +2342,15 @@ crypt_reencrypt_info crypt_reencrypt_status(struct crypt_device *cd,
*
* @param size size of memory in bytes
*
* @return pointer to allocate memory or @e NULL.
* @return pointer to allocated memory or @e NULL.
*/
void *crypt_safe_alloc(size_t size);
/**
* Release safe memory, content is safely wiped
* Release safe memory, content is safely wiped.
* The pointer must be allocated with @link crypt_safe_alloc @endlink
*
* @param data pointer to memory to be deallocated
*
* @return pointer to allocate memory or @e NULL.
*/
void crypt_safe_free(void *data);
@@ -2350,17 +2360,15 @@ void crypt_safe_free(void *data);
* @param data pointer to memory to be deallocated
* @param size new size of memory in bytes
*
* @return pointer to allocate memory or @e NULL.
* @return pointer to allocated memory or @e NULL.
*/
void *crypt_safe_realloc(void *data, size_t size);
/**
* Safe clear memory area (compile should not compile this call out).
*
* @param data pointer to memory to cleared
* @param size new size of memory in bytes
*
* @return pointer to allocate memory or @e NULL.
* @param data pointer to memory to be cleared
* @param size size of memory in bytes
*/
void crypt_safe_memzero(void *data, size_t size);

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-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2020 Milan Broz
* Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2021 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -33,7 +33,7 @@
#ifdef HAVE_SYS_SYSMACROS_H
# include <sys/sysmacros.h> /* for major, minor */
#endif
#include <assert.h>
#include "internal.h"
#define DM_UUID_LEN 129
@@ -174,6 +174,9 @@ static void _dm_set_crypt_compat(struct crypt_device *cd,
if (_dm_satisfies_version(1, 20, 0, crypt_maj, crypt_min, crypt_patch))
_dm_flags |= DM_BITLK_ELEPHANT_SUPPORTED;
if (_dm_satisfies_version(1, 22, 0, crypt_maj, crypt_min, crypt_patch))
_dm_flags |= DM_CRYPT_NO_WORKQUEUE_SUPPORTED;
_dm_crypt_checked = true;
}
@@ -205,6 +208,9 @@ static void _dm_set_verity_compat(struct crypt_device *cd,
if (_dm_satisfies_version(1, 5, 0, verity_maj, verity_min, verity_patch))
_dm_flags |= DM_VERITY_SIGNATURE_SUPPORTED;
if (_dm_satisfies_version(1, 7, 0, verity_maj, verity_min, verity_patch))
_dm_flags |= DM_VERITY_PANIC_CORRUPTION_SUPPORTED;
_dm_verity_checked = true;
}
@@ -233,6 +239,9 @@ static void _dm_set_integrity_compat(struct crypt_device *cd,
if (_dm_satisfies_version(1, 6, 0, integrity_maj, integrity_min, integrity_patch))
_dm_flags |= DM_INTEGRITY_DISCARDS_SUPPORTED;
if (_dm_satisfies_version(1, 7, 0, integrity_maj, integrity_min, integrity_patch))
_dm_flags |= DM_INTEGRITY_FIX_HMAC_SUPPORTED;
_dm_integrity_checked = true;
}
@@ -581,9 +590,14 @@ static int cipher_dm2c(char **org_c, char **org_i, const char *c_dm, const char
i = sscanf(capi, "%" CLENS "[^(](%" CLENS "[^)])", mode, cipher);
if (i == 2)
snprintf(dmcrypt_tmp, sizeof(dmcrypt_tmp), "%s-%s-%s", cipher, mode, iv);
i = snprintf(dmcrypt_tmp, sizeof(dmcrypt_tmp), "%s-%s-%s", cipher, mode, iv);
else
snprintf(dmcrypt_tmp, sizeof(dmcrypt_tmp), "%s-%s", capi, iv);
i = snprintf(dmcrypt_tmp, sizeof(dmcrypt_tmp), "%s-%s", capi, iv);
if (i < 0 || (size_t)i >= sizeof(dmcrypt_tmp)) {
free(*org_i);
*org_i = NULL;
return -EINVAL;
}
if (!(*org_c = strdup(dmcrypt_tmp))) {
free(*org_i);
@@ -594,11 +608,18 @@ static int cipher_dm2c(char **org_c, char **org_i, const char *c_dm, const char
return 0;
}
static char *_uf(char *buf, size_t buf_size, const char *s, unsigned u)
{
size_t r = snprintf(buf, buf_size, " %s:%u", s, u);
assert(r > 0 && r < buf_size);
return buf;
}
/* https://gitlab.com/cryptsetup/cryptsetup/wikis/DMCrypt */
static char *get_dm_crypt_params(const struct dm_target *tgt, uint32_t flags)
{
int r, max_size, null_cipher = 0, num_options = 0, keystr_len = 0;
char *params, *hexkey;
char *params = NULL, *hexkey = NULL;
char sector_feature[32], features[512], integrity_dm[256], cipher_dm[256];
if (!tgt)
@@ -615,47 +636,53 @@ static char *get_dm_crypt_params(const struct dm_target *tgt, uint32_t flags)
num_options++;
if (flags & CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS)
num_options++;
if (flags & CRYPT_ACTIVATE_NO_READ_WORKQUEUE)
num_options++;
if (flags & CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE)
num_options++;
if (flags & CRYPT_ACTIVATE_IV_LARGE_SECTORS)
num_options++;
if (tgt->u.crypt.integrity)
num_options++;
if (tgt->u.crypt.sector_size != SECTOR_SIZE) {
if (tgt->u.crypt.sector_size != SECTOR_SIZE)
num_options++;
snprintf(sector_feature, sizeof(sector_feature), " sector_size:%u", tgt->u.crypt.sector_size);
} else
*sector_feature = '\0';
if (num_options) {
snprintf(features, sizeof(features)-1, " %d%s%s%s%s%s%s", num_options,
if (num_options) { /* MAX length int32 + 15 + 15 + 23 + 18 + 19 + 17 + 13 + int32 + integrity_str */
r = snprintf(features, sizeof(features), " %d%s%s%s%s%s%s%s%s", num_options,
(flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) ? " allow_discards" : "",
(flags & CRYPT_ACTIVATE_SAME_CPU_CRYPT) ? " same_cpu_crypt" : "",
(flags & CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS) ? " submit_from_crypt_cpus" : "",
(flags & CRYPT_ACTIVATE_NO_READ_WORKQUEUE) ? " no_read_workqueue" : "",
(flags & CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE) ? " no_write_workqueue" : "",
(flags & CRYPT_ACTIVATE_IV_LARGE_SECTORS) ? " iv_large_sectors" : "",
sector_feature, integrity_dm);
(tgt->u.crypt.sector_size != SECTOR_SIZE) ?
_uf(sector_feature, sizeof(sector_feature), "sector_size", tgt->u.crypt.sector_size) : "",
integrity_dm);
if (r < 0 || (size_t)r >= sizeof(features))
goto out;
} else
*features = '\0';
if (!strncmp(cipher_dm, "cipher_null-", 12))
if (crypt_is_cipher_null(cipher_dm))
null_cipher = 1;
if (flags & CRYPT_ACTIVATE_KEYRING_KEY) {
if (null_cipher)
hexkey = crypt_safe_alloc(2);
else if (flags & CRYPT_ACTIVATE_KEYRING_KEY) {
keystr_len = strlen(tgt->u.crypt.vk->key_description) + int_log10(tgt->u.crypt.vk->keylength) + 10;
hexkey = crypt_safe_alloc(keystr_len);
} else
hexkey = crypt_safe_alloc(null_cipher ? 2 : (tgt->u.crypt.vk->keylength * 2 + 1));
hexkey = crypt_safe_alloc(tgt->u.crypt.vk->keylength * 2 + 1);
if (!hexkey)
return NULL;
goto out;
if (null_cipher)
strncpy(hexkey, "-", 2);
else if (flags & CRYPT_ACTIVATE_KEYRING_KEY) {
r = snprintf(hexkey, keystr_len, ":%zu:logon:%s", tgt->u.crypt.vk->keylength, tgt->u.crypt.vk->key_description);
if (r < 0 || r >= keystr_len) {
params = NULL;
if (r < 0 || r >= keystr_len)
goto out;
}
} else
hex_key(hexkey, tgt->u.crypt.vk->keylength, tgt->u.crypt.vk->key);
@@ -682,10 +709,10 @@ out:
/* https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity */
static char *get_dm_verity_params(const struct dm_target *tgt, uint32_t flags)
{
int max_size, r, num_options = 0;
int max_size, max_fec_size, max_verify_size, r, num_options = 0;
struct crypt_params_verity *vp;
char *params = NULL, *hexroot = NULL, *hexsalt = NULL;
char features[256], fec_features[256], verity_verify_args[512+32];
char features[256], *fec_features = NULL, *verity_verify_args = NULL;
if (!tgt || !tgt->u.verity.vp)
return NULL;
@@ -693,42 +720,63 @@ static char *get_dm_verity_params(const struct dm_target *tgt, uint32_t flags)
vp = tgt->u.verity.vp;
/* These flags are not compatible */
if ((flags & CRYPT_ACTIVATE_RESTART_ON_CORRUPTION) &&
(flags & CRYPT_ACTIVATE_PANIC_ON_CORRUPTION))
flags &= ~CRYPT_ACTIVATE_RESTART_ON_CORRUPTION;
if ((flags & CRYPT_ACTIVATE_IGNORE_CORRUPTION) &&
(flags & CRYPT_ACTIVATE_RESTART_ON_CORRUPTION))
(flags & (CRYPT_ACTIVATE_RESTART_ON_CORRUPTION|CRYPT_ACTIVATE_PANIC_ON_CORRUPTION)))
flags &= ~CRYPT_ACTIVATE_IGNORE_CORRUPTION;
if (flags & CRYPT_ACTIVATE_IGNORE_CORRUPTION)
num_options++;
if (flags & CRYPT_ACTIVATE_RESTART_ON_CORRUPTION)
num_options++;
if (flags & CRYPT_ACTIVATE_PANIC_ON_CORRUPTION)
num_options++;
if (flags & CRYPT_ACTIVATE_IGNORE_ZERO_BLOCKS)
num_options++;
if (flags & CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE)
num_options++;
if (tgt->u.verity.fec_device) {
max_fec_size = (tgt->u.verity.fec_device ? strlen(device_block_path(tgt->u.verity.fec_device)) : 0) + 256;
fec_features = crypt_safe_alloc(max_fec_size);
if (!fec_features)
goto out;
if (tgt->u.verity.fec_device) { /* MAX length 21 + path + 11 + int64 + 12 + int64 + 11 + int32 */
num_options += 8;
snprintf(fec_features, sizeof(fec_features)-1,
r = snprintf(fec_features, max_fec_size,
" use_fec_from_device %s fec_start %" PRIu64 " fec_blocks %" PRIu64 " fec_roots %" PRIu32,
device_block_path(tgt->u.verity.fec_device), tgt->u.verity.fec_offset,
vp->data_size + tgt->u.verity.hash_blocks, vp->fec_roots);
tgt->u.verity.fec_blocks, vp->fec_roots);
if (r < 0 || r >= max_fec_size)
goto out;
} else
*fec_features = '\0';
if (tgt->u.verity.root_hash_sig_key_desc) {
max_verify_size = (tgt->u.verity.root_hash_sig_key_desc ? strlen(tgt->u.verity.root_hash_sig_key_desc) : 0) + 32;
verity_verify_args = crypt_safe_alloc(max_verify_size);
if (!verity_verify_args)
goto out;
if (tgt->u.verity.root_hash_sig_key_desc) { /* MAX length 24 + key_str */
num_options += 2;
snprintf(verity_verify_args, sizeof(verity_verify_args)-1,
r = snprintf(verity_verify_args, max_verify_size,
" root_hash_sig_key_desc %s", tgt->u.verity.root_hash_sig_key_desc);
if (r < 0 || r >= max_verify_size)
goto out;
} else
*verity_verify_args = '\0';
if (num_options)
snprintf(features, sizeof(features)-1, " %d%s%s%s%s", num_options,
if (num_options) { /* MAX length int32 + 18 + 22 + 20 + 19 + 19 */
r = snprintf(features, sizeof(features), " %d%s%s%s%s%s", num_options,
(flags & CRYPT_ACTIVATE_IGNORE_CORRUPTION) ? " ignore_corruption" : "",
(flags & CRYPT_ACTIVATE_RESTART_ON_CORRUPTION) ? " restart_on_corruption" : "",
(flags & CRYPT_ACTIVATE_PANIC_ON_CORRUPTION) ? " panic_on_corruption" : "",
(flags & CRYPT_ACTIVATE_IGNORE_ZERO_BLOCKS) ? " ignore_zero_blocks" : "",
(flags & CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE) ? " check_at_most_once" : "");
else
if (r < 0 || (size_t)r >= sizeof(features))
goto out;
} else
*features = '\0';
hexroot = crypt_safe_alloc(tgt->u.verity.root_hash_size * 2 + 1);
@@ -762,12 +810,13 @@ static char *get_dm_verity_params(const struct dm_target *tgt, uint32_t flags)
vp->data_size, tgt->u.verity.hash_offset,
vp->hash_name, hexroot, hexsalt, features, fec_features,
verity_verify_args);
if (r < 0 || r >= max_size) {
crypt_safe_free(params);
params = NULL;
}
out:
crypt_safe_free(fec_features);
crypt_safe_free(verity_verify_args);
crypt_safe_free(hexroot);
crypt_safe_free(hexsalt);
return params;
@@ -775,149 +824,143 @@ out:
static char *get_dm_integrity_params(const struct dm_target *tgt, uint32_t flags)
{
int r, max_size, num_options = 0;
char *params, *hexkey, mode;
char features[512], feature[256];
int r, max_size, max_integrity, max_journal_integrity, max_journal_crypt, num_options = 0;
char *params_out = NULL, *params, *hexkey, mode, feature[6][32];
char *features, *integrity, *journal_integrity, *journal_crypt;
if (!tgt)
return NULL;
max_integrity = (tgt->u.integrity.integrity && tgt->u.integrity.vk ? tgt->u.integrity.vk->keylength * 2 : 0) +
(tgt->u.integrity.integrity ? strlen(tgt->u.integrity.integrity) : 0) + 32;
max_journal_integrity = (tgt->u.integrity.journal_integrity && tgt->u.integrity.journal_integrity_key ?
tgt->u.integrity.journal_integrity_key->keylength * 2 : 0) +
(tgt->u.integrity.journal_integrity ? strlen(tgt->u.integrity.journal_integrity) : 0) + 32;
max_journal_crypt = (tgt->u.integrity.journal_crypt && tgt->u.integrity.journal_crypt_key ?
tgt->u.integrity.journal_crypt_key->keylength * 2 : 0) +
(tgt->u.integrity.journal_crypt ? strlen(tgt->u.integrity.journal_crypt) : 0) + 32;
max_size = strlen(device_block_path(tgt->data_device)) +
(tgt->u.integrity.meta_device ? strlen(device_block_path(tgt->u.integrity.meta_device)) : 0) +
(tgt->u.integrity.vk ? tgt->u.integrity.vk->keylength * 2 : 0) +
(tgt->u.integrity.journal_integrity_key ? tgt->u.integrity.journal_integrity_key->keylength * 2 : 0) +
(tgt->u.integrity.journal_crypt_key ? tgt->u.integrity.journal_crypt_key->keylength * 2 : 0) +
(tgt->u.integrity.integrity ? strlen(tgt->u.integrity.integrity) : 0) +
(tgt->u.integrity.journal_integrity ? strlen(tgt->u.integrity.journal_integrity) : 0) +
(tgt->u.integrity.journal_crypt ? strlen(tgt->u.integrity.journal_crypt) : 0) + 128;
(tgt->u.integrity.meta_device ? strlen(device_block_path(tgt->u.integrity.meta_device)) : 0) +
max_integrity + max_journal_integrity + max_journal_crypt + 512;
params = crypt_safe_alloc(max_size);
if (!params)
return NULL;
features = crypt_safe_alloc(max_size);
integrity = crypt_safe_alloc(max_integrity);
journal_integrity = crypt_safe_alloc(max_journal_integrity);
journal_crypt = crypt_safe_alloc(max_journal_crypt);
if (!params || !features || !integrity || !journal_integrity || !journal_crypt)
goto out;
*features = '\0';
if (tgt->u.integrity.journal_size) {
num_options++;
snprintf(feature, sizeof(feature), "journal_sectors:%u ",
(unsigned)(tgt->u.integrity.journal_size / SECTOR_SIZE));
strncat(features, feature, sizeof(features) - strlen(features) - 1);
}
if (tgt->u.integrity.journal_watermark) {
num_options++;
snprintf(feature, sizeof(feature),
/* bitmap overloaded values */
(flags & CRYPT_ACTIVATE_NO_JOURNAL_BITMAP) ? "sectors_per_bit:%u " : "journal_watermark:%u ",
tgt->u.integrity.journal_watermark);
strncat(features, feature, sizeof(features) - strlen(features) - 1);
}
if (tgt->u.integrity.journal_commit_time) {
num_options++;
snprintf(feature, sizeof(feature),
/* bitmap overloaded values */
(flags & CRYPT_ACTIVATE_NO_JOURNAL_BITMAP) ? "bitmap_flush_interval:%u " : "commit_time:%u ",
tgt->u.integrity.journal_commit_time);
strncat(features, feature, sizeof(features) - strlen(features) - 1);
}
if (tgt->u.integrity.interleave_sectors) {
num_options++;
snprintf(feature, sizeof(feature), "interleave_sectors:%u ",
tgt->u.integrity.interleave_sectors);
strncat(features, feature, sizeof(features) - strlen(features) - 1);
}
if (tgt->u.integrity.sector_size) {
num_options++;
snprintf(feature, sizeof(feature), "block_size:%u ",
tgt->u.integrity.sector_size);
strncat(features, feature, sizeof(features) - strlen(features) - 1);
}
if (tgt->u.integrity.buffer_sectors) {
num_options++;
snprintf(feature, sizeof(feature), "buffer_sectors:%u ",
tgt->u.integrity.buffer_sectors);
strncat(features, feature, sizeof(features) - strlen(features) - 1);
}
if (tgt->u.integrity.integrity) {
if (tgt->u.integrity.integrity) { /* MAX length 16 + str_integrity + str_key */
num_options++;
if (tgt->u.integrity.vk) {
hexkey = crypt_safe_alloc(tgt->u.integrity.vk->keylength * 2 + 1);
if (!hexkey) {
crypt_safe_free(params);
return NULL;
}
if (!hexkey)
goto out;
hex_key(hexkey, tgt->u.integrity.vk->keylength, tgt->u.integrity.vk->key);
} else
hexkey = NULL;
snprintf(feature, sizeof(feature), "internal_hash:%s%s%s ",
r = snprintf(integrity, max_integrity, " internal_hash:%s%s%s",
tgt->u.integrity.integrity, hexkey ? ":" : "", hexkey ?: "");
strncat(features, feature, sizeof(features) - strlen(features) - 1);
crypt_safe_free(hexkey);
if (r < 0 || r >= max_integrity)
goto out;
}
if (tgt->u.integrity.journal_integrity) {
if (tgt->u.integrity.journal_integrity) { /* MAX length 14 + str_journal_integrity + str_key */
num_options++;
if (tgt->u.integrity.journal_integrity_key) {
hexkey = crypt_safe_alloc(tgt->u.integrity.journal_integrity_key->keylength * 2 + 1);
if (!hexkey) {
crypt_safe_free(params);
return NULL;
}
if (!hexkey)
goto out;
hex_key(hexkey, tgt->u.integrity.journal_integrity_key->keylength,
tgt->u.integrity.journal_integrity_key->key);
} else
hexkey = NULL;
snprintf(feature, sizeof(feature), "journal_mac:%s%s%s ",
r = snprintf(journal_integrity, max_journal_integrity, " journal_mac:%s%s%s",
tgt->u.integrity.journal_integrity, hexkey ? ":" : "", hexkey ?: "");
strncat(features, feature, sizeof(features) - strlen(features) - 1);
crypt_safe_free(hexkey);
if (r < 0 || r >= max_journal_integrity)
goto out;
}
if (tgt->u.integrity.journal_crypt) {
if (tgt->u.integrity.journal_crypt) { /* MAX length 15 + str_journal_crypt + str_key */
num_options++;
if (tgt->u.integrity.journal_crypt_key) {
hexkey = crypt_safe_alloc(tgt->u.integrity.journal_crypt_key->keylength * 2 + 1);
if (!hexkey) {
crypt_safe_free(params);
return NULL;
}
if (!hexkey)
goto out;
hex_key(hexkey, tgt->u.integrity.journal_crypt_key->keylength,
tgt->u.integrity.journal_crypt_key->key);
} else
hexkey = NULL;
snprintf(feature, sizeof(feature), "journal_crypt:%s%s%s ",
r = snprintf(journal_crypt, max_journal_crypt, " journal_crypt:%s%s%s",
tgt->u.integrity.journal_crypt, hexkey ? ":" : "", hexkey ?: "");
strncat(features, feature, sizeof(features) - strlen(features) - 1);
crypt_safe_free(hexkey);
}
if (tgt->u.integrity.fix_padding) {
num_options++;
snprintf(feature, sizeof(feature), "fix_padding ");
strncat(features, feature, sizeof(features) - strlen(features) - 1);
if (r < 0 || r >= max_journal_crypt)
goto out;
}
if (flags & CRYPT_ACTIVATE_RECALCULATE) {
if (tgt->u.integrity.journal_size)
num_options++;
if (tgt->u.integrity.journal_watermark)
num_options++;
if (tgt->u.integrity.journal_commit_time)
num_options++;
if (tgt->u.integrity.interleave_sectors)
num_options++;
if (tgt->u.integrity.sector_size)
num_options++;
if (tgt->u.integrity.buffer_sectors)
num_options++;
if (tgt->u.integrity.fix_padding)
num_options++;
if (tgt->u.integrity.fix_hmac)
num_options++;
if (tgt->u.integrity.legacy_recalc)
num_options++;
if (tgt->u.integrity.meta_device)
num_options++;
if (flags & CRYPT_ACTIVATE_RECALCULATE)
num_options++;
if (flags & CRYPT_ACTIVATE_ALLOW_DISCARDS)
num_options++;
snprintf(feature, sizeof(feature), "recalculate ");
strncat(features, feature, sizeof(features) - strlen(features) - 1);
}
if (flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) {
num_options++;
snprintf(feature, sizeof(feature), "allow_discards ");
strncat(features, feature, sizeof(features) - strlen(features) - 1);
}
if (tgt->u.integrity.meta_device) {
num_options++;
snprintf(feature, sizeof(feature), "meta_device:%s ",
device_block_path(tgt->u.integrity.meta_device));
strncat(features, feature, sizeof(features) - strlen(features) - 1);
}
r = snprintf(features, max_size, "%d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", num_options,
tgt->u.integrity.journal_size ? _uf(feature[0], sizeof(feature[0]), /* MAX length 17 + int32 */
"journal_sectors", (unsigned)(tgt->u.integrity.journal_size / SECTOR_SIZE)) : "",
tgt->u.integrity.journal_watermark ? _uf(feature[1], sizeof(feature[1]), /* MAX length 19 + int32 */
/* bitmap overloaded values */
(flags & CRYPT_ACTIVATE_NO_JOURNAL_BITMAP) ? "sectors_per_bit" : "journal_watermark",
tgt->u.integrity.journal_watermark) : "",
tgt->u.integrity.journal_commit_time ? _uf(feature[2], sizeof(feature[2]), /* MAX length 23 + int32 */
/* bitmap overloaded values */
(flags & CRYPT_ACTIVATE_NO_JOURNAL_BITMAP) ? "bitmap_flush_interval" : "commit_time",
tgt->u.integrity.journal_commit_time) : "",
tgt->u.integrity.interleave_sectors ? _uf(feature[3], sizeof(feature[3]), /* MAX length 20 + int32 */
"interleave_sectors", tgt->u.integrity.interleave_sectors) : "",
tgt->u.integrity.sector_size ? _uf(feature[4], sizeof(feature[4]), /* MAX length 12 + int32 */
"block_size", tgt->u.integrity.sector_size) : "",
tgt->u.integrity.buffer_sectors ? _uf(feature[5], sizeof(feature[5]), /* MAX length 16 + int32 */
"buffer_sectors", tgt->u.integrity.buffer_sectors) : "",
tgt->u.integrity.integrity ? integrity : "",
tgt->u.integrity.journal_integrity ? journal_integrity : "",
tgt->u.integrity.journal_crypt ? journal_crypt : "",
tgt->u.integrity.fix_padding ? " fix_padding" : "", /* MAX length 12 */
tgt->u.integrity.fix_hmac ? " fix_hmac" : "", /* MAX length 9 */
tgt->u.integrity.legacy_recalc ? " legacy_recalculate" : "", /* MAX length 19 */
flags & CRYPT_ACTIVATE_RECALCULATE ? " recalculate" : "", /* MAX length 12 */
flags & CRYPT_ACTIVATE_ALLOW_DISCARDS ? " allow_discards" : "", /* MAX length 15 */
tgt->u.integrity.meta_device ? " meta_device:" : "", /* MAX length 13 + str_device */
tgt->u.integrity.meta_device ? device_block_path(tgt->u.integrity.meta_device) : "");
if (r < 0 || r >= max_size)
goto out;
if (flags & CRYPT_ACTIVATE_NO_JOURNAL_BITMAP)
mode = 'B';
@@ -928,16 +971,22 @@ static char *get_dm_integrity_params(const struct dm_target *tgt, uint32_t flags
else
mode = 'J';
r = snprintf(params, max_size, "%s %" PRIu64 " %d %c %d %s",
r = snprintf(params, max_size, "%s %" PRIu64 " %d %c %s",
device_block_path(tgt->data_device), tgt->u.integrity.offset,
tgt->u.integrity.tag_size, mode,
num_options, *features ? features : "");
if (r < 0 || r >= max_size) {
crypt_safe_free(params);
params = NULL;
}
tgt->u.integrity.tag_size, mode, features);
if (r < 0 || r >= max_size)
goto out;
return params;
params_out = params;
out:
crypt_safe_free(features);
crypt_safe_free(integrity);
crypt_safe_free(journal_integrity);
crypt_safe_free(journal_crypt);
if (!params_out)
crypt_safe_free(params);
return params_out;
}
static char *get_dm_linear_params(const struct dm_target *tgt, uint32_t flags)
@@ -1172,7 +1221,7 @@ static int dm_prepare_uuid(struct crypt_device *cd, const char *name, const char
{
char *ptr, uuid2[UUID_LEN] = {0};
uuid_t uu;
unsigned i = 0;
int i = 0;
/* Remove '-' chars */
if (uuid) {
@@ -1192,9 +1241,11 @@ static int dm_prepare_uuid(struct crypt_device *cd, const char *name, const char
type ?: "", type ? "-" : "",
uuid2[0] ? uuid2 : "", uuid2[0] ? "-" : "",
name);
if (i < 0)
return 0;
log_dbg(cd, "DM-UUID is %s", buf);
if (i >= buflen)
if ((size_t)i >= buflen)
log_err(cd, _("DM-UUID for device %s was truncated."), name);
return 1;
@@ -1305,6 +1356,12 @@ err:
return r;
}
static bool dm_device_exists(struct crypt_device *cd, const char *name)
{
int r = dm_status_device(cd, name);
return (r >= 0 || r == -EEXIST);
}
static int _dm_create_device(struct crypt_device *cd, const char *name, const char *type,
const char *uuid, struct crypt_dm_active_device *dmd)
{
@@ -1354,8 +1411,11 @@ static int _dm_create_device(struct crypt_device *cd, const char *name, const ch
if (_dm_use_udev() && !_dm_task_set_cookie(dmt, &cookie, udev_flags))
goto out;
if (!dm_task_run(dmt))
if (!dm_task_run(dmt)) {
if (dm_device_exists(cd, name))
r = -EEXIST;
goto out;
}
if (dm_task_get_info(dmt, &dmi))
r = 0;
@@ -1592,6 +1652,14 @@ static int check_retry(struct crypt_device *cd, uint32_t *dmd_flags, uint32_t dm
ret = 1;
}
/* Drop no workqueue options if not supported */
if ((*dmd_flags & (CRYPT_ACTIVATE_NO_READ_WORKQUEUE | CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE)) &&
!(dmt_flags & DM_CRYPT_NO_WORKQUEUE_SUPPORTED)) {
log_dbg(cd, "dm-crypt does not support performance options");
*dmd_flags = *dmd_flags & ~(CRYPT_ACTIVATE_NO_READ_WORKQUEUE | CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE);
ret = 1;
}
return ret;
}
@@ -1614,14 +1682,29 @@ int dm_create_device(struct crypt_device *cd, const char *name,
goto out;
if (r && (dmd->segment.type == DM_CRYPT || dmd->segment.type == DM_LINEAR || dmd->segment.type == DM_ZERO) &&
check_retry(cd, &dmd->flags, dmt_flags))
check_retry(cd, &dmd->flags, dmt_flags)) {
log_dbg(cd, "Retrying open without incompatible options.");
r = _dm_create_device(cd, name, type, dmd->uuid, dmd);
}
/*
* Print warning if activating dm-crypt cipher_null device unless it's reencryption helper or
* keyslot encryption helper device (LUKS1 cipher_null devices).
*/
if (!r && !(dmd->flags & CRYPT_ACTIVATE_PRIVATE) && single_segment(dmd) && dmd->segment.type == DM_CRYPT &&
crypt_is_cipher_null(dmd->segment.u.crypt.cipher))
log_dbg(cd, "Activated dm-crypt device with cipher_null. Device is not encrypted.");
if (r == -EINVAL &&
dmd->flags & (CRYPT_ACTIVATE_SAME_CPU_CRYPT|CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS) &&
!(dmt_flags & (DM_SAME_CPU_CRYPT_SUPPORTED|DM_SUBMIT_FROM_CRYPT_CPUS_SUPPORTED)))
log_err(cd, _("Requested dm-crypt performance options are not supported."));
if (r == -EINVAL &&
dmd->flags & (CRYPT_ACTIVATE_NO_READ_WORKQUEUE | CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE) &&
!(dmt_flags & DM_CRYPT_NO_WORKQUEUE_SUPPORTED))
log_err(cd, _("Requested dm-crypt performance options are not supported."));
if (r == -EINVAL && dmd->flags & (CRYPT_ACTIVATE_IGNORE_CORRUPTION|
CRYPT_ACTIVATE_RESTART_ON_CORRUPTION|
CRYPT_ACTIVATE_IGNORE_ZERO_BLOCKS|
@@ -1629,6 +1712,10 @@ int dm_create_device(struct crypt_device *cd, const char *name,
!(dmt_flags & DM_VERITY_ON_CORRUPTION_SUPPORTED))
log_err(cd, _("Requested dm-verity data corruption handling options are not supported."));
if (r == -EINVAL && dmd->flags & CRYPT_ACTIVATE_PANIC_ON_CORRUPTION &&
!(dmt_flags & DM_VERITY_PANIC_CORRUPTION_SUPPORTED))
log_err(cd, _("Requested dm-verity data corruption handling options are not supported."));
if (r == -EINVAL && dmd->segment.type == DM_VERITY &&
dmd->segment.u.verity.fec_device && !(dmt_flags & DM_VERITY_FEC_SUPPORTED))
log_err(cd, _("Requested dm-verity FEC options are not supported."));
@@ -1675,7 +1762,10 @@ int dm_reload_device(struct crypt_device *cd, const char *name,
if (r == -EINVAL && (dmd->segment.type == DM_CRYPT || dmd->segment.type == DM_LINEAR)) {
if ((dmd->flags & (CRYPT_ACTIVATE_SAME_CPU_CRYPT|CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS)) &&
!dm_flags(cd, DM_CRYPT, &dmt_flags) && !(dmt_flags & (DM_SAME_CPU_CRYPT_SUPPORTED|DM_SUBMIT_FROM_CRYPT_CPUS_SUPPORTED)))
!dm_flags(cd, DM_CRYPT, &dmt_flags) && !(dmt_flags & (DM_SAME_CPU_CRYPT_SUPPORTED | DM_SUBMIT_FROM_CRYPT_CPUS_SUPPORTED)))
log_err(cd, _("Requested dm-crypt performance options are not supported."));
if ((dmd->flags & (CRYPT_ACTIVATE_NO_READ_WORKQUEUE | CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE)) &&
!dm_flags(cd, DM_CRYPT, &dmt_flags) && !(dmt_flags & DM_CRYPT_NO_WORKQUEUE_SUPPORTED))
log_err(cd, _("Requested dm-crypt performance options are not supported."));
if ((dmd->flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) &&
!dm_flags(cd, DM_CRYPT, &dmt_flags) && !(dmt_flags & DM_DISCARDS_SUPPORTED))
@@ -1720,6 +1810,7 @@ static int dm_status_dmi(const char *name, struct dm_info *dmi,
goto out;
}
r = -EEXIST;
dm_get_next_target(dmt, NULL, &start, &length,
&target_type, &params);
@@ -1918,6 +2009,10 @@ static int _dm_target_query_crypt(struct crypt_device *cd, uint32_t get_flags,
*act_flags |= CRYPT_ACTIVATE_SAME_CPU_CRYPT;
else if (!strcasecmp(arg, "submit_from_crypt_cpus"))
*act_flags |= CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS;
else if (!strcasecmp(arg, "no_read_workqueue"))
*act_flags |= CRYPT_ACTIVATE_NO_READ_WORKQUEUE;
else if (!strcasecmp(arg, "no_write_workqueue"))
*act_flags |= CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE;
else if (!strcasecmp(arg, "iv_large_sectors"))
*act_flags |= CRYPT_ACTIVATE_IV_LARGE_SECTORS;
else if (sscanf(arg, "integrity:%u:", &val) == 1) {
@@ -2168,6 +2263,8 @@ static int _dm_target_query_verity(struct crypt_device *cd,
*act_flags |= CRYPT_ACTIVATE_IGNORE_CORRUPTION;
else if (!strcasecmp(arg, "restart_on_corruption"))
*act_flags |= CRYPT_ACTIVATE_RESTART_ON_CORRUPTION;
else if (!strcasecmp(arg, "panic_on_corruption"))
*act_flags |= CRYPT_ACTIVATE_PANIC_ON_CORRUPTION;
else if (!strcasecmp(arg, "ignore_zero_blocks"))
*act_flags |= CRYPT_ACTIVATE_IGNORE_ZERO_BLOCKS;
else if (!strcasecmp(arg, "check_at_most_once"))
@@ -2213,8 +2310,13 @@ static int _dm_target_query_verity(struct crypt_device *cd,
str = strsep(&params, " ");
if (!str)
goto err;
if (!root_hash_sig_key_desc)
if (!root_hash_sig_key_desc) {
root_hash_sig_key_desc = strdup(str);
if (!root_hash_sig_key_desc) {
r = -ENOMEM;
goto err;
}
}
i++;
if (vp)
vp->flags |= CRYPT_VERITY_ROOT_HASH_SIGNATURE;
@@ -2418,6 +2520,10 @@ static int _dm_target_query_integrity(struct crypt_device *cd,
*act_flags |= CRYPT_ACTIVATE_RECALCULATE;
} else if (!strcmp(arg, "fix_padding")) {
tgt->u.integrity.fix_padding = true;
} else if (!strcmp(arg, "fix_hmac")) {
tgt->u.integrity.fix_hmac = true;
} else if (!strcmp(arg, "legacy_recalculate")) {
tgt->u.integrity.legacy_recalc = true;
} else if (!strcmp(arg, "allow_discards")) {
*act_flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS;
} else /* unknown option */
@@ -2857,7 +2963,9 @@ int dm_resume_and_reinstate_key(struct crypt_device *cd, const char *name,
if (!(dmt_flags & DM_KEY_WIPE_SUPPORTED))
goto out;
if (vk->key_description)
if (!vk->keylength)
msg_size = 11; // key set -
else if (vk->key_description)
msg_size = strlen(vk->key_description) + int_log10(vk->keylength) + 18;
else
msg_size = vk->keylength * 2 + 10; // key set <key>
@@ -2869,7 +2977,9 @@ int dm_resume_and_reinstate_key(struct crypt_device *cd, const char *name,
}
strcpy(msg, "key set ");
if (vk->key_description)
if (!vk->keylength)
snprintf(msg + 8, msg_size - 8, "-");
else if (vk->key_description)
snprintf(msg + 8, msg_size - 8, ":%zu:logon:%s", vk->keylength, vk->key_description);
else
hex_key(&msg[8], vk->keylength, vk->key);
@@ -2944,8 +3054,8 @@ err:
int dm_verity_target_set(struct dm_target *tgt, uint64_t seg_offset, uint64_t seg_size,
struct device *data_device, struct device *hash_device, struct device *fec_device,
const char *root_hash, uint32_t root_hash_size, const char *root_hash_sig_key_desc,
uint64_t hash_offset_block, uint64_t hash_blocks, struct crypt_params_verity *vp)
const char *root_hash, uint32_t root_hash_size, const char* root_hash_sig_key_desc,
uint64_t hash_offset_block, uint64_t fec_blocks, struct crypt_params_verity *vp)
{
if (!data_device || !hash_device || !vp)
return -EINVAL;
@@ -2963,7 +3073,7 @@ int dm_verity_target_set(struct dm_target *tgt, uint64_t seg_offset, uint64_t se
tgt->u.verity.root_hash_sig_key_desc = root_hash_sig_key_desc;
tgt->u.verity.hash_offset = hash_offset_block;
tgt->u.verity.fec_offset = vp->fec_area_offset / vp->hash_block_size;
tgt->u.verity.hash_blocks = hash_blocks;
tgt->u.verity.fec_blocks = fec_blocks;
tgt->u.verity.vp = vp;
return 0;
@@ -3004,6 +3114,15 @@ int dm_integrity_target_set(struct crypt_device *cd,
!(crypt_get_compatibility(cd) & CRYPT_COMPAT_LEGACY_INTEGRITY_PADDING))
tgt->u.integrity.fix_padding = true;
if (!dm_flags(cd, DM_INTEGRITY, &dmi_flags) &&
(dmi_flags & DM_INTEGRITY_FIX_HMAC_SUPPORTED) &&
!(crypt_get_compatibility(cd) & CRYPT_COMPAT_LEGACY_INTEGRITY_HMAC))
tgt->u.integrity.fix_hmac = true;
/* This flag can be backported, just try to set it always */
if (crypt_get_compatibility(cd) & CRYPT_COMPAT_LEGACY_INTEGRITY_RECALC)
tgt->u.integrity.legacy_recalc = true;
if (ip) {
tgt->u.integrity.journal_size = ip->journal_size;
tgt->u.integrity.journal_watermark = ip->journal_watermark;

View File

@@ -1,8 +1,8 @@
/*
* loop-AES compatible volume handling
*
* Copyright (C) 2011-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2011-2020 Milan Broz
* Copyright (C) 2011-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2011-2021 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-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2011-2020 Milan Broz
* Copyright (C) 2011-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2011-2021 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-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2021 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-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2021 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-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2020 Milan Broz
* Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2021 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -153,7 +153,7 @@ int LUKS_encrypt_to_storage(char *src, size_t srcLength,
return -EINVAL;
/* Encrypt buffer */
r = crypt_storage_init(&s, SECTOR_SIZE, cipher, cipher_mode, vk->key, vk->keylength);
r = crypt_storage_init(&s, SECTOR_SIZE, cipher, cipher_mode, vk->key, vk->keylength, false);
if (r)
log_dbg(ctx, "Userspace crypto wrapper cannot use %s-%s (%d).",
@@ -218,7 +218,7 @@ int LUKS_decrypt_from_storage(char *dst, size_t dstLength,
if (MISALIGNED_512(dstLength))
return -EINVAL;
r = crypt_storage_init(&s, SECTOR_SIZE, cipher, cipher_mode, vk->key, vk->keylength);
r = crypt_storage_init(&s, SECTOR_SIZE, cipher, cipher_mode, vk->key, vk->keylength, false);
if (r)
log_dbg(ctx, "Userspace crypto wrapper cannot use %s-%s (%d).",

View File

@@ -2,8 +2,8 @@
* LUKS - Linux Unified Key Setup
*
* Copyright (C) 2004-2006 Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2009-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2013-2020 Milan Broz
* Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2013-2021 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,8 +375,13 @@ static int _keyslot_repair(struct luks_phdr *phdr, struct crypt_device *ctx)
log_err(ctx, _("Non standard key size, manual repair required."));
return -EINVAL;
}
/* cryptsetup 1.0 did not align to 4k, cannot repair this one */
if (LUKS_keyslots_offset(phdr) < (LUKS_ALIGN_KEYSLOTS / SECTOR_SIZE)) {
/*
* cryptsetup 1.0 did not align keyslots to 4k, cannot repair this one
* Also we cannot trust possibly broken keyslots metadata here through LUKS_keyslots_offset().
* Expect first keyslot is aligned, if not, then manual repair is neccessary.
*/
if (phdr->keyblock[0].keyMaterialOffset < (LUKS_ALIGN_KEYSLOTS / SECTOR_SIZE)) {
log_err(ctx, _("Non standard keyslots alignment, manual repair required."));
return -EINVAL;
}
@@ -386,6 +391,8 @@ static int _keyslot_repair(struct luks_phdr *phdr, struct crypt_device *ctx)
return -EINVAL;
vk = crypt_alloc_volume_key(phdr->keyBytes, NULL);
if (!vk)
return -ENOMEM;
log_verbose(ctx, _("Repairing keyslots."));
@@ -955,12 +962,12 @@ static int LUKS_open_key(unsigned int keyIndex,
const char *password,
size_t passwordLen,
struct luks_phdr *hdr,
struct volume_key *vk,
struct volume_key **vk,
struct crypt_device *ctx)
{
crypt_keyslot_info ki = LUKS_keyslot_info(hdr, keyIndex);
struct volume_key *derived_key;
char *AfKey;
char *AfKey = NULL;
size_t AFEKSize;
int r;
@@ -974,8 +981,13 @@ static int LUKS_open_key(unsigned int keyIndex,
if (!derived_key)
return -ENOMEM;
assert(vk->keylength == hdr->keyBytes);
AFEKSize = AF_split_sectors(vk->keylength, hdr->keyblock[keyIndex].stripes) * SECTOR_SIZE;
*vk = crypt_alloc_volume_key(hdr->keyBytes, NULL);
if (!*vk) {
r = -ENOMEM;
goto out;
}
AFEKSize = AF_split_sectors(hdr->keyBytes, hdr->keyblock[keyIndex].stripes) * SECTOR_SIZE;
AfKey = crypt_safe_alloc(AFEKSize);
if (!AfKey) {
r = -ENOMEM;
@@ -1001,16 +1013,20 @@ static int LUKS_open_key(unsigned int keyIndex,
if (r < 0)
goto out;
r = AF_merge(ctx, AfKey, vk->key, vk->keylength, hdr->keyblock[keyIndex].stripes, hdr->hashSpec);
r = AF_merge(ctx, AfKey, (*vk)->key, (*vk)->keylength, hdr->keyblock[keyIndex].stripes, hdr->hashSpec);
if (r < 0)
goto out;
r = LUKS_verify_volume_key(hdr, vk);
r = LUKS_verify_volume_key(hdr, *vk);
/* Allow only empty passphrase with null cipher */
if (!r && !strcmp(hdr->cipherName, "cipher_null") && passwordLen)
if (!r && crypt_is_cipher_null(hdr->cipherName) && passwordLen)
r = -EPERM;
out:
if (r < 0) {
crypt_free_volume_key(*vk);
*vk = NULL;
}
crypt_safe_free(AfKey);
crypt_free_volume_key(derived_key);
return r;
@@ -1026,16 +1042,14 @@ int LUKS_open_key_with_hdr(int keyIndex,
unsigned int i, tried = 0;
int r;
*vk = crypt_alloc_volume_key(hdr->keyBytes, NULL);
if (keyIndex >= 0) {
r = LUKS_open_key(keyIndex, password, passwordLen, hdr, *vk, ctx);
r = LUKS_open_key(keyIndex, password, passwordLen, hdr, vk, ctx);
return (r < 0) ? r : keyIndex;
}
for (i = 0; i < LUKS_NUMKEYS; i++) {
r = LUKS_open_key(i, password, passwordLen, hdr, *vk, ctx);
if(r == 0)
r = LUKS_open_key(i, password, passwordLen, hdr, vk, ctx);
if (r == 0)
return i;
/* Do not retry for errors that are no -EPERM or -ENOENT,

View File

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

View File

@@ -1,8 +1,8 @@
/*
* LUKS - Linux Unified Key Setup v2
*
* Copyright (C) 2015-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2020 Milan Broz
* Copyright (C) 2015-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2021 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -23,6 +23,8 @@
#define _CRYPTSETUP_LUKS2_ONDISK_H
#include <stdbool.h>
#include <stdint.h>
#include <sys/types.h>
#include "libcryptsetup.h"
@@ -59,6 +61,10 @@
#define LUKS2_REENCRYPT_MAX_HOTZONE_LENGTH 0x40000000
struct device;
struct luks2_reencrypt;
struct crypt_lock_handle;
struct crypt_dm_active_device;
struct luks_phdr; /* LUKS1 for conversion */
/*
* LUKS2 header on-disk.
@@ -94,7 +100,6 @@ struct luks2_hdr_disk {
/*
* LUKS2 header in-memory.
*/
typedef struct json_object json_object;
struct luks2_hdr {
size_t hdr_size;
uint64_t seqid;
@@ -105,7 +110,7 @@ struct luks2_hdr {
uint8_t salt1[LUKS2_SALT_L];
uint8_t salt2[LUKS2_SALT_L];
char uuid[LUKS2_UUID_L];
json_object *jobj;
void *jobj;
};
struct luks2_keyslot_params {
@@ -127,77 +132,6 @@ struct luks2_keyslot_params {
} area;
};
struct reenc_protection {
enum { REENC_PROTECTION_NONE = 0, /* none should be 0 always */
REENC_PROTECTION_CHECKSUM,
REENC_PROTECTION_JOURNAL,
REENC_PROTECTION_DATASHIFT } type;
union {
struct {
} none;
struct {
char hash[LUKS2_CHECKSUM_ALG_L]; // or include luks.h
struct crypt_hash *ch;
size_t hash_size;
/* buffer for checksums */
void *checksums;
size_t checksums_len;
} csum;
struct {
} ds;
} p;
};
struct luks2_reenc_context {
/* reencryption window attributes */
uint64_t offset;
uint64_t progress;
uint64_t length;
uint64_t data_shift;
size_t alignment;
uint64_t device_size;
bool online;
bool fixed_length;
crypt_reencrypt_direction_info direction;
crypt_reencrypt_mode_info mode;
char *device_name;
char *hotzone_name;
char *overlay_name;
uint32_t flags;
/* reencryption window persistence attributes */
struct reenc_protection rp;
int reenc_keyslot;
/* already running reencryption */
json_object *jobj_segs_hot;
json_object *jobj_segs_post;
/* backup segments */
json_object *jobj_segment_new;
int digest_new;
json_object *jobj_segment_old;
int digest_old;
json_object *jobj_segment_moved;
struct volume_key *vks;
void *reenc_buffer;
ssize_t read;
struct crypt_storage_wrapper *cw1;
struct crypt_storage_wrapper *cw2;
uint32_t wflags1;
uint32_t wflags2;
struct crypt_lock_handle *reenc_lock;
};
crypt_reencrypt_info LUKS2_reenc_status(struct luks2_hdr *hdr);
/*
* Supportable header sizes (hdr_disk + JSON area)
* Also used as offset for the 2nd header.
@@ -220,9 +154,6 @@ crypt_reencrypt_info LUKS2_reenc_status(struct luks2_hdr *hdr);
int LUKS2_hdr_version_unlocked(struct crypt_device *cd,
const char *backup_file);
int LUKS2_device_write_lock(struct crypt_device *cd,
struct luks2_hdr *hdr, struct device *device);
int LUKS2_hdr_read(struct crypt_device *cd, struct luks2_hdr *hdr, int repair);
int LUKS2_hdr_write(struct crypt_device *cd, struct luks2_hdr *hdr);
int LUKS2_hdr_write_force(struct crypt_device *cd, struct luks2_hdr *hdr);
@@ -247,9 +178,9 @@ int LUKS2_hdr_restore(struct crypt_device *cd,
struct luks2_hdr *hdr,
const char *backup_file);
uint64_t LUKS2_hdr_and_areas_size(json_object *jobj);
uint64_t LUKS2_keyslots_size(json_object *jobj);
uint64_t LUKS2_metadata_size(json_object *jobj);
uint64_t LUKS2_hdr_and_areas_size(struct luks2_hdr *hdr);
uint64_t LUKS2_keyslots_size(struct luks2_hdr *hdr);
uint64_t LUKS2_metadata_size(struct luks2_hdr *hdr);
int LUKS2_keyslot_cipher_incompatible(struct crypt_device *cd, const char *cipher_spec);
@@ -278,28 +209,11 @@ int LUKS2_keyslot_store(struct crypt_device *cd,
const struct volume_key *vk,
const struct luks2_keyslot_params *params);
int LUKS2_keyslot_reencrypt_store(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot,
const void *buffer,
size_t buffer_length);
int LUKS2_keyslot_reencrypt_create(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot,
const struct crypt_params_reencrypt *params);
int reenc_keyslot_update(struct crypt_device *cd,
const struct luks2_reenc_context *rh);
int LUKS2_keyslot_wipe(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot,
int wipe_area_only);
int LUKS2_keyslot_dump(struct crypt_device *cd,
int keyslot);
crypt_keyslot_priority LUKS2_keyslot_priority_get(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot);
@@ -330,6 +244,12 @@ int LUKS2_token_is_assigned(struct crypt_device *cd,
int keyslot,
int token);
int LUKS2_token_assignment_copy(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot_from,
int keyslot_to,
int commit);
int LUKS2_token_create(struct crypt_device *cd,
struct luks2_hdr *hdr,
int token,
@@ -366,65 +286,6 @@ int LUKS2_token_open_and_activate_any(struct crypt_device *cd,
const char *name,
uint32_t flags);
int LUKS2_tokens_count(struct luks2_hdr *hdr);
/*
* Generic LUKS2 segment
*/
uint64_t json_segment_get_offset(json_object *jobj_segment, unsigned blockwise);
const char *json_segment_type(json_object *jobj_segment);
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);
int json_segment_get_sector_size(json_object *jobj_segment);
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);
int json_segments_segment_in_reencrypt(json_object *jobj_segments);
int LUKS2_segments_count(struct luks2_hdr *hdr);
int LUKS2_segment_first_unused_id(struct luks2_hdr *hdr);
int LUKS2_segment_set_flag(json_object *jobj_segment, const char *flag);
json_object *LUKS2_get_segment_by_flag(struct luks2_hdr *hdr, const char *flag);
int LUKS2_get_segment_id_by_flag(struct luks2_hdr *hdr, const char *flag);
int LUKS2_segments_set(struct crypt_device *cd,
struct luks2_hdr *hdr,
json_object *jobj_segments,
int commit);
uint64_t LUKS2_segment_offset(struct luks2_hdr *hdr,
int segment,
unsigned blockwise);
uint64_t LUKS2_segment_size(struct luks2_hdr *hdr,
int segment,
unsigned blockwise);
int LUKS2_segment_is_type(struct luks2_hdr *hdr,
int segment,
const char *type);
int LUKS2_segment_by_type(struct luks2_hdr *hdr,
const char *type);
int LUKS2_last_segment_by_type(struct luks2_hdr *hdr,
const char *type);
int LUKS2_get_default_segment(struct luks2_hdr *hdr);
int LUKS2_reencrypt_digest_new(struct luks2_hdr *hdr);
int LUKS2_reencrypt_digest_old(struct luks2_hdr *hdr);
int LUKS2_reencrypt_data_offset(struct luks2_hdr *hdr, bool blockwise);
/*
* Generic LUKS2 digest
*/
@@ -432,29 +293,16 @@ int LUKS2_digest_any_matching(struct crypt_device *cd,
struct luks2_hdr *hdr,
const struct volume_key *vk);
int LUKS2_digest_by_segment(struct luks2_hdr *hdr, int segment);
int LUKS2_digest_verify_by_digest(struct crypt_device *cd,
struct luks2_hdr *hdr,
int digest,
const struct volume_key *vk);
int LUKS2_digest_verify_by_segment(struct crypt_device *cd,
struct luks2_hdr *hdr,
int segment,
const struct volume_key *vk);
void LUKS2_digests_erase_unused(struct crypt_device *cd,
struct luks2_hdr *hdr);
int LUKS2_digest_verify(struct crypt_device *cd,
struct luks2_hdr *hdr,
const struct volume_key *vk,
int keyslot);
int LUKS2_digest_dump(struct crypt_device *cd,
int digest);
int LUKS2_digest_assign(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot,
@@ -471,6 +319,8 @@ int LUKS2_digest_segment_assign(struct crypt_device *cd,
int LUKS2_digest_by_keyslot(struct luks2_hdr *hdr, int keyslot);
int LUKS2_digest_by_segment(struct luks2_hdr *hdr, int segment);
int LUKS2_digest_create(struct crypt_device *cd,
const char *type,
struct luks2_hdr *hdr,
@@ -490,20 +340,12 @@ int LUKS2_activate_multi(struct crypt_device *cd,
uint64_t device_size,
uint32_t flags);
struct crypt_dm_active_device;
int LUKS2_deactivate(struct crypt_device *cd,
const char *name,
struct luks2_hdr *hdr,
struct crypt_dm_active_device *dmd,
uint32_t flags);
int LUKS2_reload(struct crypt_device *cd,
const char *name,
struct volume_key *vks,
uint64_t device_size,
uint32_t flags);
int LUKS2_generate_hdr(
struct crypt_device *cd,
struct luks2_hdr *hdr,
@@ -523,7 +365,7 @@ int LUKS2_check_metadata_area_size(uint64_t metadata_size);
int LUKS2_check_keyslots_area_size(uint64_t keyslots_size);
int LUKS2_wipe_header_areas(struct crypt_device *cd,
struct luks2_hdr *hdr);
struct luks2_hdr *hdr, bool detached_header);
uint64_t LUKS2_get_data_offset(struct luks2_hdr *hdr);
int LUKS2_get_data_size(struct luks2_hdr *hdr, uint64_t *size, bool *dynamic);
@@ -537,17 +379,12 @@ int LUKS2_get_keyslot_stored_key_size(struct luks2_hdr *hdr, int keyslot);
const char *LUKS2_get_keyslot_cipher(struct luks2_hdr *hdr, int keyslot, size_t *key_size);
int LUKS2_keyslot_find_empty(struct luks2_hdr *hdr);
int LUKS2_keyslot_active_count(struct luks2_hdr *hdr, int segment);
int LUKS2_keyslot_for_segment(struct luks2_hdr *hdr, int keyslot, int segment);
int LUKS2_find_keyslot(struct luks2_hdr *hdr, const char *type);
crypt_keyslot_info LUKS2_keyslot_info(struct luks2_hdr *hdr, int keyslot);
int LUKS2_keyslot_area(struct luks2_hdr *hdr,
int keyslot,
uint64_t *offset,
uint64_t *length);
int LUKS2_keyslot_pbkdf(struct luks2_hdr *hdr, int keyslot, struct crypt_pbkdf_type *pbkdf);
int LUKS2_set_keyslots_size(struct crypt_device *cd,
struct luks2_hdr *hdr,
uint64_t data_offset);
/*
* Permanent activation flags stored in header
@@ -561,6 +398,8 @@ int LUKS2_config_set_flags(struct crypt_device *cd, struct luks2_hdr *hdr, uint3
int LUKS2_config_get_requirements(struct crypt_device *cd, struct luks2_hdr *hdr, uint32_t *reqs);
int LUKS2_config_set_requirements(struct crypt_device *cd, struct luks2_hdr *hdr, uint32_t reqs, bool commit);
int LUKS2_config_get_reencrypt_version(struct luks2_hdr *hdr, uint32_t *version);
int LUKS2_unmet_requirements(struct crypt_device *cd, struct luks2_hdr *hdr, uint32_t reqs_mask, int quiet);
int LUKS2_key_description_by_segment(struct crypt_device *cd,
@@ -570,7 +409,6 @@ int LUKS2_volume_key_load_in_keyring_by_keyslot(struct crypt_device *cd,
int LUKS2_volume_key_load_in_keyring_by_digest(struct crypt_device *cd,
struct luks2_hdr *hdr, struct volume_key *vk, int digest);
struct luks_phdr;
int LUKS2_luks1_to_luks2(struct crypt_device *cd,
struct luks_phdr *hdr1,
struct luks2_hdr *hdr2);
@@ -589,21 +427,33 @@ int LUKS2_reencrypt_locked_recovery_by_passphrase(struct crypt_device *cd,
uint32_t flags,
struct volume_key **vks);
void LUKS2_reenc_context_free(struct crypt_device *cd, struct luks2_reenc_context *rh);
void LUKS2_reencrypt_free(struct crypt_device *cd,
struct luks2_reencrypt *rh);
int LUKS2_assembly_multisegment_dmd(struct crypt_device *cd,
struct luks2_hdr *hdr,
struct volume_key *vks,
json_object *jobj_segments,
struct crypt_dm_active_device *dmd);
crypt_reencrypt_info LUKS2_reencrypt_status(struct luks2_hdr *hdr);
crypt_reencrypt_info LUKS2_reencrypt_status(struct crypt_device *cd,
crypt_reencrypt_info LUKS2_reencrypt_get_params(struct luks2_hdr *hdr,
struct crypt_params_reencrypt *params);
int crypt_reencrypt_lock(struct crypt_device *cd, struct crypt_lock_handle **reencrypt_lock);
int crypt_reencrypt_lock_by_dm_uuid(struct crypt_device *cd, const char *dm_uuid, struct crypt_lock_handle **reencrypt_lock);
void crypt_reencrypt_unlock(struct crypt_device *cd, struct crypt_lock_handle *reencrypt_lock);
int LUKS2_reencrypt_lock(struct crypt_device *cd,
struct crypt_lock_handle **reencrypt_lock);
int luks2_check_device_size(struct crypt_device *cd, struct luks2_hdr *hdr, uint64_t check_size, uint64_t *dev_size, bool activation, bool dynamic);
int LUKS2_reencrypt_lock_by_dm_uuid(struct crypt_device *cd,
const char *dm_uuid,
struct crypt_lock_handle **reencrypt_lock);
void LUKS2_reencrypt_unlock(struct crypt_device *cd,
struct crypt_lock_handle *reencrypt_lock);
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);
int LUKS2_reencrypt_digest_verify(struct crypt_device *cd,
struct luks2_hdr *hdr,
struct volume_key *vks);
#endif

View File

@@ -1,8 +1,8 @@
/*
* LUKS - Linux Unified Key Setup v2, digest handling
*
* Copyright (C) 2015-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2020 Milan Broz
* Copyright (C) 2015-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2021 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -219,7 +219,9 @@ static int assign_one_digest(struct crypt_device *cd, struct luks2_hdr *hdr,
if (!jobj_digest_keyslots)
return -EINVAL;
snprintf(num, sizeof(num), "%d", keyslot);
if (snprintf(num, sizeof(num), "%d", keyslot) < 0)
return -EINVAL;
if (assign) {
jobj1 = LUKS2_array_jobj(jobj_digest_keyslots, num);
if (!jobj1)
@@ -304,7 +306,9 @@ static int assign_one_segment(struct crypt_device *cd, struct luks2_hdr *hdr,
if (!jobj_digest_segments)
return -EINVAL;
snprintf(num, sizeof(num), "%d", segment);
if (snprintf(num, sizeof(num), "%d", segment) < 0)
return -EINVAL;
if (assign) {
jobj1 = LUKS2_array_jobj(jobj_digest_segments, num);
if (!jobj1)

View File

@@ -1,8 +1,8 @@
/*
* LUKS - Linux Unified Key Setup v2, PBKDF2 digest handler (LUKS1 compatible)
*
* Copyright (C) 2015-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2020 Milan Broz
* Copyright (C) 2015-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2021 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,8 +1,8 @@
/*
* LUKS - Linux Unified Key Setup v2
*
* Copyright (C) 2015-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2020 Milan Broz
* Copyright (C) 2015-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2021 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -175,13 +175,13 @@ static void hdr_to_disk(struct luks2_hdr *hdr,
hdr_disk->hdr_offset = cpu_to_be64(offset);
hdr_disk->seqid = cpu_to_be64(hdr->seqid);
strncpy(hdr_disk->label, hdr->label, LUKS2_LABEL_L);
memcpy(hdr_disk->label, hdr->label, MIN(strlen(hdr->label), LUKS2_LABEL_L));
hdr_disk->label[LUKS2_LABEL_L - 1] = '\0';
strncpy(hdr_disk->subsystem, hdr->subsystem, LUKS2_LABEL_L);
memcpy(hdr_disk->subsystem, hdr->subsystem, MIN(strlen(hdr->subsystem), LUKS2_LABEL_L));
hdr_disk->subsystem[LUKS2_LABEL_L - 1] = '\0';
strncpy(hdr_disk->checksum_alg, hdr->checksum_alg, LUKS2_CHECKSUM_ALG_L);
memcpy(hdr_disk->checksum_alg, hdr->checksum_alg, MIN(strlen(hdr->checksum_alg), LUKS2_CHECKSUM_ALG_L));
hdr_disk->checksum_alg[LUKS2_CHECKSUM_ALG_L - 1] = '\0';
strncpy(hdr_disk->uuid, hdr->uuid, LUKS2_UUID_L);
memcpy(hdr_disk->uuid, hdr->uuid, MIN(strlen(hdr->uuid), LUKS2_UUID_L));
hdr_disk->uuid[LUKS2_UUID_L - 1] = '\0';
memcpy(hdr_disk->salt, secondary ? hdr->salt2 : hdr->salt1, LUKS2_SALT_L);
@@ -385,7 +385,7 @@ int LUKS2_device_write_lock(struct crypt_device *cd, struct luks2_hdr *hdr, stru
}
/* run sequence id check only on first write lock (r == 1) and w/o LUKS2 reencryption in-progress */
if (r == 1 && !crypt_get_reenc_context(cd)) {
if (r == 1 && !crypt_get_luks2_reencrypt(cd)) {
log_dbg(cd, "Checking context sequence id matches value stored on disk.");
if (LUKS2_check_sequence_id(cd, hdr, device)) {
device_write_unlock(cd, device);
@@ -413,7 +413,7 @@ int LUKS2_disk_hdr_write(struct crypt_device *cd, struct luks2_hdr *hdr, struct
return -EINVAL;
}
r = device_check_size(cd, crypt_metadata_device(cd), LUKS2_hdr_and_areas_size(hdr->jobj), 1);
r = device_check_size(cd, crypt_metadata_device(cd), LUKS2_hdr_and_areas_size(hdr), 1);
if (r)
return r;
@@ -669,9 +669,9 @@ int LUKS2_disk_hdr_read(struct crypt_device *cd, struct luks2_hdr *hdr,
/* check header with keyslots to fit the device */
if (state_hdr1 == HDR_OK)
hdr_size = LUKS2_hdr_and_areas_size(jobj_hdr1);
hdr_size = LUKS2_hdr_and_areas_size_jobj(jobj_hdr1);
else if (state_hdr2 == HDR_OK)
hdr_size = LUKS2_hdr_and_areas_size(jobj_hdr2);
hdr_size = LUKS2_hdr_and_areas_size_jobj(jobj_hdr2);
else {
r = (state_hdr1 == HDR_FAIL_IO && state_hdr2 == HDR_FAIL_IO) ? -EIO : -EINVAL;
goto err;

View File

@@ -1,8 +1,8 @@
/*
* LUKS - Linux Unified Key Setup v2
*
* Copyright (C) 2015-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2020 Milan Broz
* Copyright (C) 2015-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2021 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -44,6 +44,8 @@ int LUKS2_disk_hdr_read(struct crypt_device *cd, struct luks2_hdr *hdr,
struct device *device, int do_recovery, int do_blkprobe);
int LUKS2_disk_hdr_write(struct crypt_device *cd, struct luks2_hdr *hdr,
struct device *device, bool seqid_check);
int LUKS2_device_write_lock(struct crypt_device *cd,
struct luks2_hdr *hdr, struct device *device);
/*
* JSON struct access helpers
@@ -92,8 +94,8 @@ void LUKS2_keyslots_repair(struct crypt_device *cd, json_object *jobj_hdr);
/*
* JSON array helpers
*/
struct json_object *LUKS2_array_jobj(struct json_object *array, const char *num);
struct json_object *LUKS2_array_remove(struct json_object *array, const char *num);
json_object *LUKS2_array_jobj(json_object *array, const char *num);
json_object *LUKS2_array_remove(json_object *array, const char *num);
/*
* Plugins API
@@ -184,6 +186,8 @@ int LUKS2_find_area_gap(struct crypt_device *cd, struct luks2_hdr *hdr,
int LUKS2_find_area_max_gap(struct crypt_device *cd, struct luks2_hdr *hdr,
uint64_t *area_offset, uint64_t *area_length);
uint64_t LUKS2_hdr_and_areas_size_jobj(json_object *jobj);
int LUKS2_check_cipher(struct crypt_device *cd,
size_t keylength,
const char *cipher,
@@ -200,4 +204,127 @@ static inline const char *crypt_reencrypt_mode_to_str(crypt_reencrypt_mode_info
return "<unknown>";
}
/*
* Generic LUKS2 keyslot
*/
int LUKS2_keyslot_reencrypt_store(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot,
const void *buffer,
size_t buffer_length);
int LUKS2_keyslot_reencrypt_allocate(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot,
const struct crypt_params_reencrypt *params);
int LUKS2_keyslot_reencrypt_digest_create(struct crypt_device *cd,
struct luks2_hdr *hdr,
struct volume_key *vks);
int LUKS2_keyslot_dump(struct crypt_device *cd,
int keyslot);
int LUKS2_keyslot_jobj_area(json_object *jobj_keyslot, uint64_t *offset, uint64_t *length);
/* JSON helpers */
uint64_t json_segment_get_offset(json_object *jobj_segment, unsigned blockwise);
const char *json_segment_type(json_object *jobj_segment);
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);
int json_segment_get_sector_size(json_object *jobj_segment);
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);
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);
int LUKS2_assembly_multisegment_dmd(struct crypt_device *cd,
struct luks2_hdr *hdr,
struct volume_key *vks,
json_object *jobj_segments,
struct crypt_dm_active_device *dmd);
/*
* Generic LUKS2 segment
*/
int LUKS2_segments_count(struct luks2_hdr *hdr);
int LUKS2_segment_first_unused_id(struct luks2_hdr *hdr);
int LUKS2_segment_set_flag(json_object *jobj_segment, const char *flag);
json_object *LUKS2_get_segment_by_flag(struct luks2_hdr *hdr, const char *flag);
int LUKS2_get_segment_id_by_flag(struct luks2_hdr *hdr, const char *flag);
int LUKS2_segments_set(struct crypt_device *cd,
struct luks2_hdr *hdr,
json_object *jobj_segments,
int commit);
uint64_t LUKS2_segment_offset(struct luks2_hdr *hdr,
int segment,
unsigned blockwise);
uint64_t LUKS2_segment_size(struct luks2_hdr *hdr,
int segment,
unsigned blockwise);
int LUKS2_segment_is_type(struct luks2_hdr *hdr,
int segment,
const char *type);
int LUKS2_segment_by_type(struct luks2_hdr *hdr,
const char *type);
int LUKS2_last_segment_by_type(struct luks2_hdr *hdr,
const char *type);
int LUKS2_get_default_segment(struct luks2_hdr *hdr);
int LUKS2_reencrypt_digest_new(struct luks2_hdr *hdr);
int LUKS2_reencrypt_digest_old(struct luks2_hdr *hdr);
int LUKS2_reencrypt_data_offset(struct luks2_hdr *hdr, bool blockwise);
/*
* Generic LUKS2 digest
*/
int LUKS2_digest_verify_by_digest(struct crypt_device *cd,
struct luks2_hdr *hdr,
int digest,
const struct volume_key *vk);
void LUKS2_digests_erase_unused(struct crypt_device *cd,
struct luks2_hdr *hdr);
int LUKS2_digest_dump(struct crypt_device *cd,
int digest);
/*
* Generic LUKS2 token
*/
int LUKS2_tokens_count(struct luks2_hdr *hdr);
/*
* LUKS2 generic
*/
int LUKS2_reload(struct crypt_device *cd,
const char *name,
struct volume_key *vks,
uint64_t device_size,
uint32_t flags);
int LUKS2_keyslot_for_segment(struct luks2_hdr *hdr, int keyslot, int segment);
int LUKS2_find_keyslot(struct luks2_hdr *hdr, const char *type);
int LUKS2_set_keyslots_size(struct crypt_device *cd,
struct luks2_hdr *hdr,
uint64_t data_offset);
#endif

View File

@@ -1,8 +1,8 @@
/*
* LUKS - Linux Unified Key Setup v2, LUKS2 header format code
*
* Copyright (C) 2015-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2020 Milan Broz
* Copyright (C) 2015-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2021 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -41,7 +41,7 @@ static size_t get_min_offset(struct luks2_hdr *hdr)
static size_t get_max_offset(struct luks2_hdr *hdr)
{
return LUKS2_hdr_and_areas_size(hdr->jobj);
return LUKS2_hdr_and_areas_size(hdr);
}
int LUKS2_find_area_max_gap(struct crypt_device *cd, struct luks2_hdr *hdr,
@@ -216,7 +216,7 @@ int LUKS2_generate_hdr(
struct json_object *jobj_segment, *jobj_integrity, *jobj_keyslots, *jobj_segments, *jobj_config;
char cipher[128];
uuid_t partitionUuid;
int digest;
int r, digest;
uint64_t mdev_size;
if (!metadata_size)
@@ -244,7 +244,8 @@ int LUKS2_generate_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)))
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);
}
@@ -289,9 +290,11 @@ int LUKS2_generate_hdr(
uuid_unparse(partitionUuid, hdr->uuid);
if (*cipherMode != '\0')
snprintf(cipher, sizeof(cipher), "%s-%s", cipherName, cipherMode);
r = snprintf(cipher, sizeof(cipher), "%s-%s", cipherName, cipherMode);
else
snprintf(cipher, sizeof(cipher), "%s", cipherName);
r = snprintf(cipher, sizeof(cipher), "%s", cipherName);
if (r < 0 || (size_t)r >= sizeof(cipher))
return -EINVAL;
hdr->jobj = json_object_new_object();
@@ -337,7 +340,7 @@ err:
}
int LUKS2_wipe_header_areas(struct crypt_device *cd,
struct luks2_hdr *hdr)
struct luks2_hdr *hdr, bool detached_header)
{
int r;
uint64_t offset, length;
@@ -352,7 +355,7 @@ int LUKS2_wipe_header_areas(struct crypt_device *cd,
return -EINVAL;
/* On detached header wipe at least the first 4k */
if (length == 0) {
if (detached_header) {
length = 4096;
wipe_block = 4096;
}
@@ -368,7 +371,7 @@ int LUKS2_wipe_header_areas(struct crypt_device *cd,
/* Wipe keyslot area */
wipe_block = 1024 * 1024;
offset = get_min_offset(hdr);
length = LUKS2_keyslots_size(hdr->jobj);
length = LUKS2_keyslots_size(hdr);
log_dbg(cd, "Wiping keyslots area (0x%06" PRIx64 " - 0x%06" PRIx64") with random data.",
offset, length + offset);

View File

@@ -1,9 +1,9 @@
/*
* LUKS - Linux Unified Key Setup v2
*
* Copyright (C) 2015-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2020 Milan Broz
* Copyright (C) 2015-2020 Ondrej Kozina
* Copyright (C) 2015-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2021 Milan Broz
* Copyright (C) 2015-2021 Ondrej Kozina
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -591,12 +591,84 @@ static bool validate_segment_intervals(struct crypt_device *cd,
return true;
}
static int reqs_unknown(uint32_t reqs)
{
return reqs & CRYPT_REQUIREMENT_UNKNOWN;
}
static int reqs_reencrypt(uint32_t reqs)
{
return reqs & CRYPT_REQUIREMENT_OFFLINE_REENCRYPT;
}
static int reqs_reencrypt_online(uint32_t reqs)
{
return reqs & CRYPT_REQUIREMENT_ONLINE_REENCRYPT;
}
/*
* Config section requirements object must be valid.
* Also general segments section must be validated first.
*/
static int validate_reencrypt_segments(struct crypt_device *cd, json_object *hdr_jobj, json_object *jobj_segments, int first_backup, int segments_count)
{
json_object *jobj, *jobj_backup_previous = NULL, *jobj_backup_final = NULL;
uint32_t reqs;
int i, r;
struct luks2_hdr dummy = {
.jobj = hdr_jobj
};
r = LUKS2_config_get_requirements(cd, &dummy, &reqs);
if (r)
return 1;
if (reqs_reencrypt_online(reqs)) {
for (i = first_backup; i < segments_count; i++) {
jobj = json_segments_get_segment(jobj_segments, i);
if (!jobj)
return 1;
if (json_segment_contains_flag(jobj, "backup-final", 0))
jobj_backup_final = jobj;
else if (json_segment_contains_flag(jobj, "backup-previous", 0))
jobj_backup_previous = jobj;
}
if (!jobj_backup_final || !jobj_backup_previous) {
log_dbg(cd, "Backup segment is missing.");
return 1;
}
for (i = 0; i < first_backup; i++) {
jobj = json_segments_get_segment(jobj_segments, i);
if (!jobj)
return 1;
if (json_segment_contains_flag(jobj, "in-reencryption", 0)) {
if (!json_segment_cmp(jobj, jobj_backup_final)) {
log_dbg(cd, "Segment in reencryption does not match backup final segment.");
return 1;
}
continue;
}
if (!json_segment_cmp(jobj, jobj_backup_final) &&
!json_segment_cmp(jobj, jobj_backup_previous)) {
log_dbg(cd, "Segment does not match neither backup final or backup previous segment.");
return 1;
}
}
}
return 0;
}
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;
struct interval *intervals;
uint64_t offset, size;
int i, r, count, first_backup = -1;
struct interval *intervals = NULL;
if (!json_object_object_get_ex(hdr_jobj, "segments", &jobj_segments)) {
log_dbg(cd, "Missing segments section.");
@@ -676,10 +748,18 @@ static int hdr_validate_segments(struct crypt_device *cd, json_object *hdr_jobj)
return 1;
}
/* avoid needlessly large allocation when first backup segment is invalid */
if (first_backup >= count) {
log_dbg(cd, "Gap between last regular segment and backup segment at key %d.", first_backup);
return 1;
}
if (first_backup < 0)
first_backup = count;
intervals = malloc(first_backup * sizeof(*intervals));
if ((size_t)first_backup < SIZE_MAX / sizeof(*intervals))
intervals = malloc(first_backup * sizeof(*intervals));
if (!intervals) {
log_dbg(cd, "Not enough memory.");
return 1;
@@ -709,10 +789,10 @@ static int hdr_validate_segments(struct crypt_device *cd, json_object *hdr_jobj)
}
}
return 0;
return validate_reencrypt_segments(cd, hdr_jobj, jobj_segments, first_backup, count);
}
uint64_t LUKS2_metadata_size(json_object *jobj)
static uint64_t LUKS2_metadata_size_jobj(json_object *jobj)
{
json_object *jobj1, *jobj2;
uint64_t json_size;
@@ -724,6 +804,11 @@ uint64_t LUKS2_metadata_size(json_object *jobj)
return json_size + LUKS2_HDR_BIN_LEN;
}
uint64_t LUKS2_metadata_size(struct luks2_hdr *hdr)
{
return LUKS2_metadata_size_jobj(hdr->jobj);
}
static int hdr_validate_areas(struct crypt_device *cd, json_object *hdr_jobj)
{
struct interval *intervals;
@@ -739,7 +824,7 @@ static int hdr_validate_areas(struct crypt_device *cd, json_object *hdr_jobj)
return 1;
/* config is already validated */
metadata_size = LUKS2_metadata_size(hdr_jobj);
metadata_size = LUKS2_metadata_size_jobj(hdr_jobj);
length = json_object_object_length(jobj_keyslots);
@@ -785,7 +870,7 @@ static int hdr_validate_areas(struct crypt_device *cd, json_object *hdr_jobj)
return 1;
}
ret = validate_intervals(cd, length, intervals, metadata_size, LUKS2_hdr_and_areas_size(hdr_jobj)) ? 0 : 1;
ret = validate_intervals(cd, length, intervals, metadata_size, LUKS2_hdr_and_areas_size_jobj(hdr_jobj)) ? 0 : 1;
free(intervals);
@@ -827,9 +912,10 @@ static int hdr_validate_digests(struct crypt_device *cd, json_object *hdr_jobj)
return 0;
}
/* requirements being validated in stand-alone routine */
static int hdr_validate_config(struct crypt_device *cd, json_object *hdr_jobj)
{
json_object *jobj_config, *jobj, *jobj1;
json_object *jobj_config, *jobj;
int i;
uint64_t keyslots_size, metadata_size, segment_offset;
@@ -884,6 +970,19 @@ static int hdr_validate_config(struct crypt_device *cd, json_object *hdr_jobj)
return 1;
}
return 0;
}
static int hdr_validate_requirements(struct crypt_device *cd, json_object *hdr_jobj)
{
int i;
json_object *jobj_config, *jobj, *jobj1;
if (!json_object_object_get_ex(hdr_jobj, "config", &jobj_config)) {
log_dbg(cd, "Missing config section.");
return 1;
}
/* Requirements object is optional */
if (json_object_object_get_ex(jobj_config, "requirements", &jobj)) {
if (!json_contains(cd, jobj_config, "section", "Config", "requirements", json_type_object))
@@ -909,6 +1008,7 @@ int LUKS2_hdr_validate(struct crypt_device *cd, json_object *hdr_jobj, uint64_t
struct {
int (*validate)(struct crypt_device *, json_object *);
} checks[] = {
{ hdr_validate_requirements },
{ hdr_validate_tokens },
{ hdr_validate_digests },
{ hdr_validate_segments },
@@ -1033,7 +1133,7 @@ void LUKS2_hdr_free(struct crypt_device *cd, struct luks2_hdr *hdr)
log_dbg(cd, "LUKS2 header still in use");
}
uint64_t LUKS2_keyslots_size(json_object *jobj)
static uint64_t LUKS2_keyslots_size_jobj(json_object *jobj)
{
json_object *jobj1, *jobj2;
uint64_t keyslots_size;
@@ -1045,9 +1145,19 @@ uint64_t LUKS2_keyslots_size(json_object *jobj)
return keyslots_size;
}
uint64_t LUKS2_hdr_and_areas_size(json_object *jobj)
uint64_t LUKS2_keyslots_size(struct luks2_hdr *hdr)
{
return 2 * LUKS2_metadata_size(jobj) + LUKS2_keyslots_size(jobj);
return LUKS2_keyslots_size_jobj(hdr->jobj);
}
uint64_t LUKS2_hdr_and_areas_size_jobj(json_object *jobj)
{
return 2 * LUKS2_metadata_size_jobj(jobj) + LUKS2_keyslots_size_jobj(jobj);
}
uint64_t LUKS2_hdr_and_areas_size(struct luks2_hdr *hdr)
{
return LUKS2_hdr_and_areas_size_jobj(hdr->jobj);
}
int LUKS2_hdr_backup(struct crypt_device *cd, struct luks2_hdr *hdr,
@@ -1059,7 +1169,7 @@ int LUKS2_hdr_backup(struct crypt_device *cd, struct luks2_hdr *hdr,
ssize_t ret, buffer_size;
char *buffer = NULL;
hdr_size = LUKS2_hdr_and_areas_size(hdr->jobj);
hdr_size = LUKS2_hdr_and_areas_size(hdr);
buffer_size = size_round_up(hdr_size, crypt_getpagesize());
buffer = crypt_safe_alloc(buffer_size);
@@ -1115,21 +1225,6 @@ int LUKS2_hdr_backup(struct crypt_device *cd, struct luks2_hdr *hdr,
return r;
}
static int reqs_unknown(uint32_t reqs)
{
return reqs & CRYPT_REQUIREMENT_UNKNOWN;
}
static int reqs_reencrypt(uint32_t reqs)
{
return reqs & CRYPT_REQUIREMENT_OFFLINE_REENCRYPT;
}
static int reqs_reencrypt_online(uint32_t reqs)
{
return reqs & CRYPT_REQUIREMENT_ONLINE_REENCRYPT;
}
int LUKS2_hdr_restore(struct crypt_device *cd, struct luks2_hdr *hdr,
const char *backup_file)
{
@@ -1170,7 +1265,7 @@ int LUKS2_hdr_restore(struct crypt_device *cd, struct luks2_hdr *hdr,
goto out;
}
buffer_size = LUKS2_hdr_and_areas_size(hdr_file.jobj);
buffer_size = LUKS2_hdr_and_areas_size(&hdr_file);
buffer = crypt_safe_alloc(buffer_size);
if (!buffer) {
r = -ENOMEM;
@@ -1210,7 +1305,7 @@ int LUKS2_hdr_restore(struct crypt_device *cd, struct luks2_hdr *hdr,
goto out;
}
/* FIXME: what could go wrong? Erase if we're fine with consequences */
if (buffer_size != (ssize_t) LUKS2_hdr_and_areas_size(tmp_hdr.jobj)) {
if (buffer_size != (ssize_t) LUKS2_hdr_and_areas_size(&tmp_hdr)) {
log_err(cd, _("Binary header with keyslot areas size differ on device and backup, restore failed."));
r = -EINVAL;
goto out;
@@ -1289,6 +1384,8 @@ static const struct {
{ CRYPT_ACTIVATE_SAME_CPU_CRYPT, "same-cpu-crypt" },
{ CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS, "submit-from-crypt-cpus" },
{ CRYPT_ACTIVATE_NO_JOURNAL, "no-journal" },
{ CRYPT_ACTIVATE_NO_READ_WORKQUEUE, "no-read-workqueue" },
{ CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE, "no-write-workqueue" },
{ 0, NULL }
};
@@ -1363,24 +1460,106 @@ int LUKS2_config_set_flags(struct crypt_device *cd, struct luks2_hdr *hdr, uint3
*/
/* LUKS2 library requirements */
static const struct {
struct requirement_flag {
uint32_t flag;
uint32_t version;
const char *description;
} requirements_flags[] = {
{ CRYPT_REQUIREMENT_OFFLINE_REENCRYPT, "offline-reencrypt" },
{ CRYPT_REQUIREMENT_ONLINE_REENCRYPT, "online-reencrypt" },
{ 0, NULL }
};
static uint32_t get_requirement_by_name(const char *requirement)
static const struct requirement_flag unknown_requirement_flag = { CRYPT_REQUIREMENT_UNKNOWN, 0, NULL };
static const struct requirement_flag requirements_flags[] = {
{ CRYPT_REQUIREMENT_OFFLINE_REENCRYPT,1, "offline-reencrypt" },
{ CRYPT_REQUIREMENT_ONLINE_REENCRYPT, 2, "online-reencrypt-v2" },
{ CRYPT_REQUIREMENT_ONLINE_REENCRYPT, 1, "online-reencrypt" },
{ 0, 0, NULL }
};
static const struct requirement_flag *get_requirement_by_name(const char *requirement)
{
int i;
for (i = 0; requirements_flags[i].description; i++)
if (!strcmp(requirement, requirements_flags[i].description))
return requirements_flags[i].flag;
return requirements_flags + i;
return CRYPT_REQUIREMENT_UNKNOWN;
return &unknown_requirement_flag;
}
int LUKS2_config_get_reencrypt_version(struct luks2_hdr *hdr, uint32_t *version)
{
json_object *jobj_config, *jobj_requirements, *jobj_mandatory, *jobj;
int i, len;
const struct requirement_flag *req;
assert(hdr && version);
if (!hdr || !version)
return -EINVAL;
if (!json_object_object_get_ex(hdr->jobj, "config", &jobj_config))
return -EINVAL;
if (!json_object_object_get_ex(jobj_config, "requirements", &jobj_requirements))
return -ENOENT;
if (!json_object_object_get_ex(jobj_requirements, "mandatory", &jobj_mandatory))
return -ENOENT;
len = (int) json_object_array_length(jobj_mandatory);
if (len <= 0)
return -ENOENT;
for (i = 0; i < len; i++) {
jobj = json_object_array_get_idx(jobj_mandatory, i);
/* search for requirements prefixed with "online-reencrypt" */
if (strncmp(json_object_get_string(jobj), "online-reencrypt", 16))
continue;
/* check current library is aware of the requirement */
req = get_requirement_by_name(json_object_get_string(jobj));
if (req->flag == (uint32_t)CRYPT_REQUIREMENT_UNKNOWN)
continue;
*version = req->version;
return 0;
}
return -ENOENT;
}
static const struct requirement_flag *stored_requirement_name_by_id(struct crypt_device *cd, struct luks2_hdr *hdr, uint32_t req_id)
{
json_object *jobj_config, *jobj_requirements, *jobj_mandatory, *jobj;
int i, len;
const struct requirement_flag *req;
assert(hdr);
if (!hdr)
return NULL;
if (!json_object_object_get_ex(hdr->jobj, "config", &jobj_config))
return NULL;
if (!json_object_object_get_ex(jobj_config, "requirements", &jobj_requirements))
return NULL;
if (!json_object_object_get_ex(jobj_requirements, "mandatory", &jobj_mandatory))
return NULL;
len = (int) json_object_array_length(jobj_mandatory);
if (len <= 0)
return 0;
for (i = 0; i < len; i++) {
jobj = json_object_array_get_idx(jobj_mandatory, i);
req = get_requirement_by_name(json_object_get_string(jobj));
if (req->flag == req_id)
return req;
}
return NULL;
}
/*
@@ -1390,7 +1569,7 @@ int LUKS2_config_get_requirements(struct crypt_device *cd, struct luks2_hdr *hdr
{
json_object *jobj_config, *jobj_requirements, *jobj_mandatory, *jobj;
int i, len;
uint32_t req;
const struct requirement_flag *req;
assert(hdr);
if (!hdr || !reqs)
@@ -1417,8 +1596,8 @@ int LUKS2_config_get_requirements(struct crypt_device *cd, struct luks2_hdr *hdr
jobj = json_object_array_get_idx(jobj_mandatory, i);
req = get_requirement_by_name(json_object_get_string(jobj));
log_dbg(cd, "%s - %sknown", json_object_get_string(jobj),
reqs_unknown(req) ? "un" : "");
*reqs |= req;
reqs_unknown(req->flag) ? "un" : "");
*reqs |= req->flag;
}
return 0;
@@ -1428,6 +1607,8 @@ int LUKS2_config_set_requirements(struct crypt_device *cd, struct luks2_hdr *hdr
{
json_object *jobj_config, *jobj_requirements, *jobj_mandatory, *jobj;
int i, r = -EINVAL;
const struct requirement_flag *req;
uint32_t req_id;
if (!hdr)
return -EINVAL;
@@ -1437,8 +1618,14 @@ int LUKS2_config_set_requirements(struct crypt_device *cd, struct luks2_hdr *hdr
return -ENOMEM;
for (i = 0; requirements_flags[i].description; i++) {
if (reqs & requirements_flags[i].flag) {
jobj = json_object_new_string(requirements_flags[i].description);
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);
if (req)
jobj = json_object_new_string(req->description);
else
jobj = json_object_new_string(requirements_flags[i].description);
if (!jobj) {
r = -ENOMEM;
goto err;
@@ -1704,8 +1891,8 @@ int LUKS2_hdr_dump(struct crypt_device *cd, struct luks2_hdr *hdr)
log_std(cd, "LUKS header information\n");
log_std(cd, "Version: \t%u\n", hdr->version);
log_std(cd, "Epoch: \t%" PRIu64 "\n", hdr->seqid);
log_std(cd, "Metadata area: \t%" PRIu64 " [bytes]\n", LUKS2_metadata_size(hdr->jobj));
log_std(cd, "Keyslots area: \t%" PRIu64 " [bytes]\n", LUKS2_keyslots_size(hdr->jobj));
log_std(cd, "Metadata area: \t%" PRIu64 " [bytes]\n", LUKS2_metadata_size(hdr));
log_std(cd, "Keyslots area: \t%" PRIu64 " [bytes]\n", LUKS2_keyslots_size(hdr));
log_std(cd, "UUID: \t%s\n", *hdr->uuid ? hdr->uuid : "(no UUID)");
log_std(cd, "Label: \t%s\n", *hdr->label ? hdr->label : "(no label)");
log_std(cd, "Subsystem: \t%s\n", *hdr->subsystem ? hdr->subsystem : "(no subsystem)");
@@ -1764,7 +1951,7 @@ uint64_t LUKS2_get_data_offset(struct luks2_hdr *hdr)
crypt_reencrypt_info ri;
json_object *jobj;
ri = LUKS2_reenc_status(hdr);
ri = LUKS2_reencrypt_status(hdr);
if (ri == CRYPT_REENCRYPT_CLEAN || ri == CRYPT_REENCRYPT_CRASH) {
jobj = LUKS2_get_segment_by_flag(hdr, "backup-final");
if (jobj)
@@ -1792,7 +1979,7 @@ const char *LUKS2_get_cipher(struct luks2_hdr *hdr, int segment)
return json_segment_get_cipher(jobj_segment) ?: "null";
}
crypt_reencrypt_info LUKS2_reenc_status(struct luks2_hdr *hdr)
crypt_reencrypt_info LUKS2_reencrypt_status(struct luks2_hdr *hdr)
{
uint32_t reqs;
@@ -2235,7 +2422,7 @@ int LUKS2_deactivate(struct crypt_device *cd, const char *name, struct luks2_hdr
goto out;
if (contains_reencryption_helper(deps)) {
r = crypt_reencrypt_lock_by_dm_uuid(cd, dmd->uuid, &reencrypt_lock);
r = LUKS2_reencrypt_lock_by_dm_uuid(cd, dmd->uuid, &reencrypt_lock);
if (r) {
if (r == -EBUSY)
log_err(cd, _("Reencryption in-progress. Cannot deactivate device."));
@@ -2314,7 +2501,7 @@ int LUKS2_deactivate(struct crypt_device *cd, const char *name, struct luks2_hdr
}
out:
crypt_reencrypt_unlock(cd, reencrypt_lock);
LUKS2_reencrypt_unlock(cd, reencrypt_lock);
dep = deps;
while (*dep)
free(*dep++);

View File

@@ -1,8 +1,8 @@
/*
* LUKS - Linux Unified Key Setup v2, keyslot handling
*
* Copyright (C) 2015-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2020 Milan Broz
* Copyright (C) 2015-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2021 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -27,7 +27,9 @@ extern const keyslot_handler reenc_keyslot;
static const keyslot_handler *keyslot_handlers[LUKS2_KEYSLOTS_MAX] = {
&luks2_keyslot,
#if USE_LUKS2_REENCRYPTION
&reenc_keyslot,
#endif
NULL
};
@@ -148,7 +150,7 @@ int LUKS2_keyslot_cipher_incompatible(struct crypt_device *cd, const char *ciphe
{
char cipher[MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN];
if (!cipher_spec || !strcmp(cipher_spec, "null") || !strcmp(cipher_spec, "cipher_null"))
if (!cipher_spec || crypt_is_cipher_null(cipher_spec))
return 1;
if (crypt_parse_name_and_mode(cipher_spec, cipher, NULL, cipher_mode) < 0)
@@ -281,19 +283,9 @@ crypt_keyslot_info LUKS2_keyslot_info(struct luks2_hdr *hdr, int keyslot)
return CRYPT_SLOT_ACTIVE;
}
int LUKS2_keyslot_area(struct luks2_hdr *hdr,
int keyslot,
uint64_t *offset,
uint64_t *length)
int LUKS2_keyslot_jobj_area(json_object *jobj_keyslot, uint64_t *offset, uint64_t *length)
{
json_object *jobj_keyslot, *jobj_area, *jobj;
if(LUKS2_keyslot_info(hdr, keyslot) == CRYPT_SLOT_INVALID)
return -EINVAL;
jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot);
if (!jobj_keyslot)
return -ENOENT;
json_object *jobj_area, *jobj;
if (!json_object_object_get_ex(jobj_keyslot, "area", &jobj_area))
return -EINVAL;
@@ -309,6 +301,23 @@ int LUKS2_keyslot_area(struct luks2_hdr *hdr,
return 0;
}
int LUKS2_keyslot_area(struct luks2_hdr *hdr,
int keyslot,
uint64_t *offset,
uint64_t *length)
{
json_object *jobj_keyslot;
if (LUKS2_keyslot_info(hdr, keyslot) == CRYPT_SLOT_INVALID)
return -EINVAL;
jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot);
if (!jobj_keyslot)
return -ENOENT;
return LUKS2_keyslot_jobj_area(jobj_keyslot, offset, length);
}
static int _open_and_verify(struct crypt_device *cd,
struct luks2_hdr *hdr,
const keyslot_handler *h,
@@ -589,7 +598,7 @@ int LUKS2_keyslot_open(struct crypt_device *cd,
return r;
}
int LUKS2_keyslot_reencrypt_create(struct crypt_device *cd,
int LUKS2_keyslot_reencrypt_allocate(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot,
const struct crypt_params_reencrypt *params)
@@ -619,9 +628,6 @@ int LUKS2_keyslot_reencrypt_create(struct crypt_device *cd,
return r;
}
if (LUKS2_hdr_validate(cd, hdr->jobj, hdr->hdr_size - LUKS2_HDR_BIN_LEN))
return -EINVAL;
return 0;
}
@@ -872,10 +878,17 @@ int LUKS2_keyslots_validate(struct crypt_device *cd, json_object *hdr_jobj)
const keyslot_handler *h;
int keyslot;
json_object *jobj_keyslots, *jobj_type;
uint32_t reqs, reencrypt_count = 0;
struct luks2_hdr dummy = {
.jobj = hdr_jobj
};
if (!json_object_object_get_ex(hdr_jobj, "keyslots", &jobj_keyslots))
return -EINVAL;
if (LUKS2_config_get_requirements(cd, &dummy, &reqs))
return -EINVAL;
json_object_object_foreach(jobj_keyslots, slot, val) {
keyslot = atoi(slot);
json_object_object_get_ex(val, "type", &jobj_type);
@@ -891,6 +904,24 @@ int LUKS2_keyslots_validate(struct crypt_device *cd, json_object *hdr_jobj)
log_dbg(cd, "Keyslot %d is not assigned to exactly 1 digest.", keyslot);
return -EINVAL;
}
if (!strcmp(h->name, "reencrypt"))
reencrypt_count++;
}
if ((reqs & CRYPT_REQUIREMENT_ONLINE_REENCRYPT) && reencrypt_count == 0) {
log_dbg(cd, "Missing reencryption keyslot.");
return -EINVAL;
}
if (!(reqs & CRYPT_REQUIREMENT_ONLINE_REENCRYPT) && reencrypt_count) {
log_dbg(cd, "Missing reencryption requirement flag.");
return -EINVAL;
}
if (reencrypt_count > 1) {
log_dbg(cd, "Too many reencryption keyslots.");
return -EINVAL;
}
return 0;

View File

@@ -1,8 +1,8 @@
/*
* LUKS - Linux Unified Key Setup v2, LUKS2 type keyslot handler
*
* Copyright (C) 2015-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2020 Milan Broz
* Copyright (C) 2015-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2021 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -48,7 +48,7 @@ static int luks2_encrypt_to_storage(char *src, size_t srcLength,
return -EINVAL;
/* Encrypt buffer */
r = crypt_storage_init(&s, SECTOR_SIZE, cipher, cipher_mode, vk->key, vk->keylength);
r = crypt_storage_init(&s, SECTOR_SIZE, cipher, cipher_mode, vk->key, vk->keylength, false);
if (r) {
log_err(cd, _("Cannot use %s-%s cipher for keyslot encryption."), cipher, cipher_mode);
return r;
@@ -103,7 +103,7 @@ static int luks2_decrypt_from_storage(char *dst, size_t dstLength,
if (MISALIGNED_512(dstLength))
return -EINVAL;
r = crypt_storage_init(&s, SECTOR_SIZE, cipher, cipher_mode, vk->key, vk->keylength);
r = crypt_storage_init(&s, SECTOR_SIZE, cipher, cipher_mode, vk->key, vk->keylength, false);
if (r) {
log_err(cd, _("Cannot use %s-%s cipher for keyslot encryption."), cipher, cipher_mode);
return r;

View File

@@ -1,8 +1,8 @@
/*
* LUKS - Linux Unified Key Setup v2, reencryption keyslot handler
*
* Copyright (C) 2016-2020, Red Hat, Inc. All rights reserved.
* Copyright (C) 2016-2020, Ondrej Kozina
* Copyright (C) 2016-2021, Red Hat, Inc. All rights reserved.
* Copyright (C) 2016-2021, Ondrej Kozina
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -176,43 +176,17 @@ static int reenc_keyslot_store(struct crypt_device *cd,
return r < 0 ? r : keyslot;
}
int reenc_keyslot_update(struct crypt_device *cd,
const struct luks2_reenc_context *rh)
static int reenc_keyslot_wipe(struct crypt_device *cd,
int keyslot)
{
json_object *jobj_keyslot, *jobj_area, *jobj_area_type;
struct luks2_hdr *hdr;
if (!(hdr = crypt_get_hdr(cd, CRYPT_LUKS2)))
return -EINVAL;
jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, rh->reenc_keyslot);
if (!jobj_keyslot)
return -EINVAL;
/* remove reencryption verification data */
LUKS2_digest_assign(cd, hdr, keyslot, CRYPT_ANY_DIGEST, 0, 0);
json_object_object_get_ex(jobj_keyslot, "area", &jobj_area);
json_object_object_get_ex(jobj_area, "type", &jobj_area_type);
if (rh->rp.type == REENC_PROTECTION_CHECKSUM) {
log_dbg(cd, "Updating reencrypt keyslot for checksum protection.");
json_object_object_add(jobj_area, "type", json_object_new_string("checksum"));
json_object_object_add(jobj_area, "hash", json_object_new_string(rh->rp.p.csum.hash));
json_object_object_add(jobj_area, "sector_size", json_object_new_int64(rh->alignment));
} else if (rh->rp.type == REENC_PROTECTION_NONE) {
log_dbg(cd, "Updating reencrypt keyslot for none protection.");
json_object_object_add(jobj_area, "type", json_object_new_string("none"));
json_object_object_del(jobj_area, "hash");
} else if (rh->rp.type == REENC_PROTECTION_JOURNAL) {
log_dbg(cd, "Updating reencrypt keyslot for journal protection.");
json_object_object_add(jobj_area, "type", json_object_new_string("journal"));
json_object_object_del(jobj_area, "hash");
} else
log_dbg(cd, "No update of reencrypt keyslot needed.");
return 0;
}
static int reenc_keyslot_wipe(struct crypt_device *cd, int keyslot)
{
return 0;
}
@@ -256,7 +230,7 @@ static int reenc_keyslot_dump(struct crypt_device *cd, int keyslot)
static int reenc_keyslot_validate(struct crypt_device *cd, json_object *jobj_keyslot)
{
json_object *jobj_mode, *jobj_area, *jobj_type, *jobj_shift_size, *jobj_hash, *jobj_sector_size, *jobj_direction;
json_object *jobj_mode, *jobj_area, *jobj_type, *jobj_shift_size, *jobj_hash, *jobj_sector_size, *jobj_direction, *jobj_key_size;
const char *mode, *type, *direction;
uint32_t sector_size;
uint64_t shift_size;
@@ -276,12 +250,18 @@ static int reenc_keyslot_validate(struct crypt_device *cd, json_object *jobj_key
!json_object_object_get_ex(jobj_area, "type", &jobj_type))
return -EINVAL;
jobj_key_size = json_contains(cd, jobj_keyslot, "", "reencrypt keyslot", "key_size", json_type_int);
jobj_mode = json_contains(cd, jobj_keyslot, "", "reencrypt keyslot", "mode", json_type_string);
jobj_direction = json_contains(cd, jobj_keyslot, "", "reencrypt keyslot", "direction", json_type_string);
if (!jobj_mode || !jobj_direction)
if (!jobj_mode || !jobj_direction || !jobj_key_size)
return -EINVAL;
if (!validate_json_uint32(jobj_key_size) || crypt_jobj_get_uint32(jobj_key_size) != 1) {
log_dbg(cd, "Illegal reencrypt key size.");
return -EINVAL;
}
mode = json_object_get_string(jobj_mode);
type = json_object_get_string(jobj_type);
direction = json_object_get_string(jobj_direction);

View File

@@ -1,9 +1,9 @@
/*
* LUKS - Linux Unified Key Setup v2, LUKS1 conversion code
*
* Copyright (C) 2015-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2020 Ondrej Kozina
* Copyright (C) 2015-2020 Milan Broz
* Copyright (C) 2015-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2021 Ondrej Kozina
* Copyright (C) 2015-2021 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -573,7 +573,7 @@ int LUKS2_luks1_to_luks2(struct crypt_device *cd, struct luks_phdr *hdr1, struct
* It duplicates check in LUKS2_hdr_write() but we don't want to move
* keyslot areas in case it would fail later
*/
if (max_size < LUKS2_hdr_and_areas_size(hdr2->jobj)) {
if (max_size < LUKS2_hdr_and_areas_size(hdr2)) {
r = -EINVAL;
goto out;
}
@@ -595,7 +595,7 @@ int LUKS2_luks1_to_luks2(struct crypt_device *cd, struct luks_phdr *hdr1, struct
buf_size = luks1_size - LUKS_ALIGN_KEYSLOTS;
/* check future LUKS2 keyslots area is at least as large as LUKS1 keyslots area */
if (buf_size > LUKS2_keyslots_size(hdr2->jobj)) {
if (buf_size > LUKS2_keyslots_size(hdr2)) {
log_err(cd, _("Unable to move keyslot area. LUKS2 keyslots area too small."));
r = -EINVAL;
goto out;
@@ -675,7 +675,7 @@ static int keyslot_LUKS1_compatible(struct crypt_device *cd, struct luks2_hdr *h
int LUKS2_luks2_to_luks1(struct crypt_device *cd, struct luks2_hdr *hdr2, struct luks_phdr *hdr1)
{
size_t buf_size, buf_offset;
char cipher[LUKS_CIPHERNAME_L-1], cipher_mode[LUKS_CIPHERMODE_L-1];
char cipher[LUKS_CIPHERNAME_L], cipher_mode[LUKS_CIPHERMODE_L];
char digest[LUKS_DIGESTSIZE], digest_salt[LUKS_SALTSIZE];
const char *hash;
size_t len;
@@ -824,8 +824,10 @@ int LUKS2_luks2_to_luks1(struct crypt_device *cd, struct luks2_hdr *hdr2, struct
if (r < 0)
return r;
strncpy(hdr1->cipherName, cipher, sizeof(hdr1->cipherName) - 1);
strncpy(hdr1->cipherMode, cipher_mode, sizeof(hdr1->cipherMode) - 1);
strncpy(hdr1->cipherName, cipher, LUKS_CIPHERNAME_L - 1);
hdr1->cipherName[LUKS_CIPHERNAME_L-1] = '\0';
strncpy(hdr1->cipherMode, cipher_mode, LUKS_CIPHERMODE_L - 1);
hdr1->cipherMode[LUKS_CIPHERMODE_L-1] = '\0';
if (!json_object_object_get_ex(jobj_keyslot, "kdf", &jobj_kdf))
return -EINVAL;
@@ -881,7 +883,7 @@ int LUKS2_luks2_to_luks1(struct crypt_device *cd, struct luks2_hdr *hdr2, struct
// move keyslots 32k -> 4k offset
buf_offset = 2 * LUKS2_HDR_16K_LEN;
buf_size = LUKS2_keyslots_size(hdr2->jobj);
buf_size = LUKS2_keyslots_size(hdr2);
r = move_keyslot_areas(cd, buf_offset, 8 * SECTOR_SIZE, buf_size);
if (r < 0) {
log_err(cd, _("Unable to move keyslot area."));

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,381 @@
/*
* 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
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "luks2_internal.h"
#include <assert.h>
#define MAX_STR 64
struct jtype {
enum { JNONE = 0, JSTR, JU64, JX64, JU32 } type;
json_object *jobj;
const char *id;
};
static size_t sr(struct jtype *j, uint8_t *ptr)
{
json_object *jobj;
size_t len = 0;
uint64_t u64;
uint32_t u32;
if (!json_object_is_type(j->jobj, json_type_object))
return 0;
if (!json_object_object_get_ex(j->jobj, j->id, &jobj))
return 0;
switch(j->type) {
case JSTR: /* JSON string */
if (!json_object_is_type(jobj, json_type_string))
return 0;
len = strlen(json_object_get_string(jobj));
if (len > MAX_STR)
return 0;
if (ptr)
memcpy(ptr, json_object_get_string(jobj), len);
break;
case JU64: /* Unsigned 64bit integer stored as string */
if (!json_object_is_type(jobj, json_type_string))
break;
len = sizeof(u64);
if (ptr) {
u64 = cpu_to_be64(crypt_jobj_get_uint64(jobj));
memcpy(ptr, &u64, len);
}
break;
case JX64: /* Unsigned 64bit segment size (allows "dynamic") */
if (!json_object_is_type(jobj, json_type_string))
break;
if (!strcmp(json_object_get_string(jobj), "dynamic")) {
len = strlen("dynamic");
if (ptr)
memcpy(ptr, json_object_get_string(jobj), len);
} else {
len = sizeof(u64);
u64 = cpu_to_be64(crypt_jobj_get_uint64(jobj));
if (ptr)
memcpy(ptr, &u64, len);
}
break;
case JU32: /* Unsigned 32bit integer, stored as JSON int */
if (!json_object_is_type(jobj, json_type_int))
return 0;
len = sizeof(u32);
if (ptr) {
u32 = cpu_to_be32(crypt_jobj_get_uint32(jobj));
memcpy(ptr, &u32, len);
}
break;
case JNONE:
return 0;
};
return len;
}
static size_t srs(struct jtype j[], uint8_t *ptr)
{
size_t l, len = 0;
while(j->jobj) {
l = sr(j, ptr);
if (!l)
return 0;
len += l;
if (ptr)
ptr += l;
j++;
}
return len;
}
static size_t segment_linear_serialize(json_object *jobj_segment, uint8_t *buffer)
{
struct jtype j[] = {
{ JSTR, jobj_segment, "type" },
{ JU64, jobj_segment, "offset" },
{ JX64, jobj_segment, "size" },
{}
};
return srs(j, buffer);
}
static size_t segment_crypt_serialize(json_object *jobj_segment, uint8_t *buffer)
{
struct jtype j[] = {
{ JSTR, jobj_segment, "type" },
{ JU64, jobj_segment, "offset" },
{ JX64, jobj_segment, "size" },
{ JU64, jobj_segment, "iv_tweak" },
{ JSTR, jobj_segment, "encryption" },
{ JU32, jobj_segment, "sector_size" },
{}
};
return srs(j, buffer);
}
static size_t segment_serialize(json_object *jobj_segment, uint8_t *buffer)
{
json_object *jobj_type;
const char *segment_type;
if (!json_object_object_get_ex(jobj_segment, "type", &jobj_type))
return 0;
if (!(segment_type = json_object_get_string(jobj_type)))
return 0;
if (!strcmp(segment_type, "crypt"))
return segment_crypt_serialize(jobj_segment, buffer);
else if (!strcmp(segment_type, "linear"))
return segment_linear_serialize(jobj_segment, buffer);
return 0;
}
static size_t backup_segments_serialize(struct luks2_hdr *hdr, uint8_t *buffer)
{
json_object *jobj_segment;
size_t l, len = 0;
jobj_segment = LUKS2_get_segment_by_flag(hdr, "backup-previous");
if (!jobj_segment || !(l = segment_serialize(jobj_segment, buffer)))
return 0;
len += l;
if (buffer)
buffer += l;
jobj_segment = LUKS2_get_segment_by_flag(hdr, "backup-final");
if (!jobj_segment || !(l = segment_serialize(jobj_segment, buffer)))
return 0;
len += l;
if (buffer)
buffer += l;
jobj_segment = LUKS2_get_segment_by_flag(hdr, "backup-moved-segment");
if (jobj_segment) {
if (!(l = segment_serialize(jobj_segment, buffer)))
return 0;
len += l;
}
return len;
}
static size_t reenc_keyslot_serialize(struct luks2_hdr *hdr, uint8_t *buffer)
{
json_object *jobj_keyslot, *jobj_area, *jobj_type;
const char *area_type;
int keyslot_reencrypt;
keyslot_reencrypt = LUKS2_find_keyslot(hdr, "reencrypt");
if (keyslot_reencrypt < 0)
return 0;
if (!(jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot_reencrypt)))
return 0;
if (!json_object_object_get_ex(jobj_keyslot, "area", &jobj_area))
return 0;
if (!json_object_object_get_ex(jobj_area, "type", &jobj_type))
return 0;
if (!(area_type = json_object_get_string(jobj_type)))
return 0;
struct jtype j[] = {
{ JSTR, jobj_keyslot, "mode" },
{ JSTR, jobj_keyslot, "direction" },
{ JSTR, jobj_area, "type" },
{ JU64, jobj_area, "offset" },
{ JU64, jobj_area, "size" },
{}
};
struct jtype j_datashift[] = {
{ JSTR, jobj_keyslot, "mode" },
{ JSTR, jobj_keyslot, "direction" },
{ JSTR, jobj_area, "type" },
{ JU64, jobj_area, "offset" },
{ JU64, jobj_area, "size" },
{ JU64, jobj_area, "shift_size" },
{}
};
struct jtype j_checksum[] = {
{ JSTR, jobj_keyslot, "mode" },
{ JSTR, jobj_keyslot, "direction" },
{ JSTR, jobj_area, "type" },
{ JU64, jobj_area, "offset" },
{ JU64, jobj_area, "size" },
{ JSTR, jobj_area, "hash" },
{ JU32, jobj_area, "sector_size" },
{}
};
if (!strcmp(area_type, "datashift"))
return srs(j_datashift, buffer);
else if (!strcmp(area_type, "checksum"))
return srs(j_checksum, buffer);
return srs(j, buffer);
}
static size_t blob_serialize(void *blob, size_t length, uint8_t *buffer)
{
if (buffer)
memcpy(buffer, blob, length);
return length;
}
static int reencrypt_assembly_verification_data(struct crypt_device *cd,
struct luks2_hdr *hdr,
struct volume_key *vks,
struct volume_key **verification_data)
{
uint8_t *ptr;
int digest_new, digest_old;
struct volume_key *data = NULL, *vk_old = NULL, *vk_new = NULL;
size_t keyslot_data_len, segments_data_len, data_len = 2;
/* Keys - calculate length */
digest_new = LUKS2_reencrypt_digest_new(hdr);
digest_old = LUKS2_reencrypt_digest_old(hdr);
if (digest_old >= 0) {
vk_old = crypt_volume_key_by_id(vks, digest_old);
if (!vk_old)
return -EINVAL;
data_len += blob_serialize(vk_old->key, vk_old->keylength, NULL);
}
if (digest_new >= 0 && digest_old != digest_new) {
vk_new = crypt_volume_key_by_id(vks, digest_new);
if (!vk_new)
return -EINVAL;
data_len += blob_serialize(vk_new->key, vk_new->keylength, NULL);
}
if (data_len == 2)
return -EINVAL;
/* Metadata - calculate length */
if (!(keyslot_data_len = reenc_keyslot_serialize(hdr, NULL)))
return -EINVAL;
data_len += keyslot_data_len;
if (!(segments_data_len = backup_segments_serialize(hdr, NULL)))
return -EINVAL;
data_len += segments_data_len;
/* Alloc and fill serialization data */
data = crypt_alloc_volume_key(data_len, NULL);
if (!data)
return -ENOMEM;
ptr = (uint8_t*)data->key;
/* v2 */
*ptr++ = 0x76;
*ptr++ = 0x32;
if (vk_old)
ptr += blob_serialize(vk_old->key, vk_old->keylength, ptr);
if (vk_new)
ptr += blob_serialize(vk_new->key, vk_new->keylength, ptr);
if (!reenc_keyslot_serialize(hdr, ptr))
goto bad;
ptr += keyslot_data_len;
if (!backup_segments_serialize(hdr, ptr))
goto bad;
ptr += segments_data_len;
assert((size_t)(ptr - (uint8_t*)data->key) == data_len);
*verification_data = data;
return 0;
bad:
crypt_free_volume_key(data);
return -EINVAL;
}
int LUKS2_keyslot_reencrypt_digest_create(struct crypt_device *cd,
struct luks2_hdr *hdr,
struct volume_key *vks)
{
int digest_reencrypt, keyslot_reencrypt, r;
struct volume_key *data;
keyslot_reencrypt = LUKS2_find_keyslot(hdr, "reencrypt");
if (keyslot_reencrypt < 0)
return keyslot_reencrypt;
r = reencrypt_assembly_verification_data(cd, hdr, vks, &data);
if (r < 0)
return r;
r = LUKS2_digest_create(cd, "pbkdf2", hdr, data);
crypt_free_volume_key(data);
if (r < 0)
return r;
digest_reencrypt = r;
r = LUKS2_digest_assign(cd, hdr, keyslot_reencrypt, CRYPT_ANY_DIGEST, 0, 0);
if (r < 0)
return r;
return LUKS2_digest_assign(cd, hdr, keyslot_reencrypt, digest_reencrypt, 1, 0);
}
int LUKS2_reencrypt_digest_verify(struct crypt_device *cd,
struct luks2_hdr *hdr,
struct volume_key *vks)
{
int r, keyslot_reencrypt;
struct volume_key *data;
keyslot_reencrypt = LUKS2_find_keyslot(hdr, "reencrypt");
if (keyslot_reencrypt < 0)
return keyslot_reencrypt;
r = reencrypt_assembly_verification_data(cd, hdr, vks, &data);
if (r < 0)
return r;
r = LUKS2_digest_verify(cd, hdr, data, keyslot_reencrypt);
crypt_free_volume_key(data);
if (r < 0) {
if (r == -ENOENT)
log_dbg(cd, "Reencryption digest is missing.");
log_err(cd, _("Reencryption metadata is invalid."));
} else
log_dbg(cd, "Reencryption metadata verified.");
return r;
}

View File

@@ -1,8 +1,8 @@
/*
* LUKS - Linux Unified Key Setup v2, internal segment handling
*
* Copyright (C) 2018-2020, Red Hat, Inc. All rights reserved.
* Copyright (C) 2018-2020, Ondrej Kozina
* Copyright (C) 2018-2021, Red Hat, Inc. All rights reserved.
* Copyright (C) 2018-2021, Ondrej Kozina
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -123,7 +123,7 @@ static json_object *json_segment_get_flags(json_object *jobj_segment)
return jobj;
}
static bool json_segment_contains_flag(json_object *jobj_segment, const char *flag_str, size_t len)
bool json_segment_contains_flag(json_object *jobj_segment, const char *flag_str, size_t len)
{
int r, i;
json_object *jobj, *jobj_flags = json_segment_get_flags(jobj_segment);
@@ -410,3 +410,23 @@ json_object *LUKS2_get_segment_by_flag(struct luks2_hdr *hdr, const char *flag)
return jobj_segment;
}
/* compares key characteristics of both segments */
bool json_segment_cmp(json_object *jobj_segment_1, json_object *jobj_segment_2)
{
const char *type = json_segment_type(jobj_segment_1);
const char *type2 = json_segment_type(jobj_segment_2);
if (!type || !type2)
return false;
if (strcmp(type, type2))
return false;
if (!strcmp(type, "crypt"))
return (json_segment_get_sector_size(jobj_segment_1) == json_segment_get_sector_size(jobj_segment_2) &&
!strcmp(json_segment_get_cipher(jobj_segment_1),
json_segment_get_cipher(jobj_segment_2)));
return true;
}

View File

@@ -1,8 +1,8 @@
/*
* LUKS - Linux Unified Key Setup v2, token handling
*
* Copyright (C) 2016-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2016-2020 Milan Broz
* Copyright (C) 2016-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2016-2021 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,7 +147,8 @@ int LUKS2_token_create(struct crypt_device *cd,
if (!json_object_object_get_ex(hdr->jobj, "tokens", &jobj_tokens))
return -EINVAL;
snprintf(num, sizeof(num), "%d", token);
if (snprintf(num, sizeof(num), "%d", token) < 0)
return -EINVAL;
/* Remove token */
if (!json)
@@ -329,7 +330,7 @@ static void LUKS2_token_buffer_free(struct crypt_device *cd,
{
const crypt_token_handler *h = LUKS2_token_handler(cd, token);
if (h->buffer_free)
if (h && h->buffer_free)
h->buffer_free(buffer, buffer_len);
else {
crypt_safe_memzero(buffer, buffer_len);
@@ -383,6 +384,7 @@ int LUKS2_token_open_and_activate(struct crypt_device *cd,
uint32_t flags,
void *usrptr)
{
bool use_keyring;
int keyslot, r;
char *buffer;
size_t buffer_len;
@@ -404,7 +406,13 @@ int LUKS2_token_open_and_activate(struct crypt_device *cd,
keyslot = r;
if ((name || (flags & CRYPT_ACTIVATE_KEYRING_KEY)) && crypt_use_keyring_for_vk(cd)) {
if (!crypt_use_keyring_for_vk(cd))
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)))
flags |= CRYPT_ACTIVATE_KEYRING_KEY;
}
@@ -510,7 +518,9 @@ static int assign_one_keyslot(struct crypt_device *cd, struct luks2_hdr *hdr,
if (!jobj_token_keyslots)
return -EINVAL;
snprintf(num, sizeof(num), "%d", keyslot);
if (snprintf(num, sizeof(num), "%d", keyslot) < 0)
return -EINVAL;
if (assign) {
jobj1 = LUKS2_array_jobj(jobj_token_keyslots, num);
if (!jobj1)
@@ -576,16 +586,12 @@ int LUKS2_token_assign(struct crypt_device *cd, struct luks2_hdr *hdr,
return token;
}
int LUKS2_token_is_assigned(struct crypt_device *cd, struct luks2_hdr *hdr,
int keyslot, int token)
static int token_is_assigned(struct luks2_hdr *hdr, int keyslot, int token)
{
int i;
json_object *jobj_token, *jobj_token_keyslots, *jobj;
json_object *jobj, *jobj_token_keyslots,
*jobj_token = LUKS2_get_token_jobj(hdr, token);
if (keyslot < 0 || keyslot >= LUKS2_KEYSLOTS_MAX || token < 0 || token >= LUKS2_TOKENS_MAX)
return -EINVAL;
jobj_token = LUKS2_get_token_jobj(hdr, token);
if (!jobj_token)
return -ENOENT;
@@ -600,6 +606,15 @@ int LUKS2_token_is_assigned(struct crypt_device *cd, struct luks2_hdr *hdr,
return -ENOENT;
}
int LUKS2_token_is_assigned(struct crypt_device *cd, struct luks2_hdr *hdr,
int keyslot, int token)
{
if (keyslot < 0 || keyslot >= LUKS2_KEYSLOTS_MAX || token < 0 || token >= LUKS2_TOKENS_MAX)
return -EINVAL;
return token_is_assigned(hdr, keyslot, token);
}
int LUKS2_tokens_count(struct luks2_hdr *hdr)
{
json_object *jobj_tokens = LUKS2_get_tokens_jobj(hdr);
@@ -608,3 +623,28 @@ int LUKS2_tokens_count(struct luks2_hdr *hdr)
return json_object_object_length(jobj_tokens);
}
int LUKS2_token_assignment_copy(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot_from,
int keyslot_to,
int commit)
{
int i, r;
if (keyslot_from < 0 || keyslot_from >= LUKS2_KEYSLOTS_MAX || keyslot_to < 0 || keyslot_to >= LUKS2_KEYSLOTS_MAX)
return -EINVAL;
r = LUKS2_tokens_count(hdr);
if (r <= 0)
return r;
for (i = 0; i < LUKS2_TOKENS_MAX; i++) {
if (!token_is_assigned(hdr, keyslot_from, i)) {
if ((r = assign_one_token(cd, hdr, keyslot_to, i, 1)))
return r;
}
}
return commit ? LUKS2_hdr_write(cd, hdr) : 0;
}

View File

@@ -1,8 +1,8 @@
/*
* LUKS - Linux Unified Key Setup v2, kernel keyring token
*
* Copyright (C) 2016-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2016-2020 Ondrej Kozina
* Copyright (C) 2016-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2016-2021 Ondrej Kozina
*
* 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 @@
/*
* cryptsetup kernel RNG access functions
*
* Copyright (C) 2010-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2021 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

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-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2020 Milan Broz
* Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2021 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -78,7 +78,7 @@ struct crypt_device {
char cipher_mode[MAX_CIPHER_LEN]; /* only for compatibility */
char *keyslot_cipher;
unsigned int keyslot_key_size;
struct luks2_reenc_context *rh;
struct luks2_reencrypt *rh;
} luks2;
struct { /* used in CRYPT_PLAIN */
struct crypt_params_plain hdr;
@@ -657,12 +657,12 @@ int crypt_set_data_device(struct crypt_device *cd, const char *device)
log_dbg(cd, "Setting ciphertext data device to %s.", device ?: "(none)");
if (!isLUKS1(cd->type) && !isLUKS2(cd->type) && !isVERITY(cd->type) &&
!isINTEGRITY(cd->type)) {
!isINTEGRITY(cd->type) && !isTCRYPT(cd->type)) {
log_err(cd, _("This operation is not supported for this device type."));
return -EINVAL;
}
if (isLUKS2(cd->type) && crypt_get_reenc_context(cd)) {
if (isLUKS2(cd->type) && crypt_get_luks2_reencrypt(cd)) {
log_err(cd, _("Illegal operation with reencryption in-progress."));
return -EINVAL;
}
@@ -845,11 +845,6 @@ static int _crypt_load_tcrypt(struct crypt_device *cd, struct crypt_params_tcryp
if (!params)
return -EINVAL;
if (cd->metadata_device) {
log_err(cd, _("Detached metadata device is not supported for this crypt type."));
return -EINVAL;
}
r = init_crypto(cd);
if (r < 0)
return r;
@@ -1084,10 +1079,15 @@ static int _init_by_name_crypt_none(struct crypt_device *cd)
_mode);
if (!r) {
snprintf(cd->u.none.cipher_spec, sizeof(cd->u.none.cipher_spec),
r = snprintf(cd->u.none.cipher_spec, sizeof(cd->u.none.cipher_spec),
"%s-%s", cd->u.none.cipher, _mode);
cd->u.none.cipher_mode = cd->u.none.cipher_spec + strlen(cd->u.none.cipher) + 1;
cd->u.none.key_size = tgt->u.crypt.vk->keylength;
if (r < 0 || (size_t)r >= sizeof(cd->u.none.cipher_spec))
r = -EINVAL;
else {
cd->u.none.cipher_mode = cd->u.none.cipher_spec + strlen(cd->u.none.cipher) + 1;
cd->u.none.key_size = tgt->u.crypt.vk->keylength;
r = 0;
}
}
dm_targets_free(cd, &dmd);
@@ -1113,7 +1113,7 @@ static void crypt_free_type(struct crypt_device *cd)
free(cd->u.plain.cipher);
free(cd->u.plain.cipher_spec);
} else if (isLUKS2(cd->type)) {
LUKS2_reenc_context_free(cd, cd->u.luks2.rh);
LUKS2_reencrypt_free(cd, cd->u.luks2.rh);
LUKS2_hdr_free(cd, &cd->u.luks2.hdr);
free(cd->u.luks2.keyslot_cipher);
} else if (isLUKS1(cd->type)) {
@@ -1210,7 +1210,7 @@ static int _init_by_name_crypt(struct crypt_device *cd, const char *name)
}
/* do not try to lookup LUKS2 header in detached header mode */
if (!cd->metadata_device && !found) {
if (dmd.uuid && !cd->metadata_device && !found) {
while (*dep && !found) {
r = dm_query_device(cd, *dep, DM_ACTIVE_DEVICE, &dmdep);
if (r < 0)
@@ -1850,13 +1850,13 @@ static int _crypt_format_luks2(struct crypt_device *cd,
if (dev_size < (crypt_get_data_offset(cd) * SECTOR_SIZE))
log_std(cd, _("WARNING: Data offset is outside of currently available data device.\n"));
if (cd->metadata_size && (cd->metadata_size != LUKS2_metadata_size(cd->u.luks2.hdr.jobj)))
if (cd->metadata_size && (cd->metadata_size != LUKS2_metadata_size(&cd->u.luks2.hdr)))
log_std(cd, _("WARNING: LUKS2 metadata size changed to %" PRIu64 " bytes.\n"),
LUKS2_metadata_size(cd->u.luks2.hdr.jobj));
LUKS2_metadata_size(&cd->u.luks2.hdr));
if (cd->keyslots_size && (cd->keyslots_size != LUKS2_keyslots_size(cd->u.luks2.hdr.jobj)))
if (cd->keyslots_size && (cd->keyslots_size != LUKS2_keyslots_size(&cd->u.luks2.hdr)))
log_std(cd, _("WARNING: LUKS2 keyslots area size changed to %" PRIu64 " bytes.\n"),
LUKS2_keyslots_size(cd->u.luks2.hdr.jobj));
LUKS2_keyslots_size(&cd->u.luks2.hdr));
if (!integrity && sector_size > SECTOR_SIZE) {
dev_size -= (crypt_get_data_offset(cd) * SECTOR_SIZE);
@@ -1874,11 +1874,11 @@ static int _crypt_format_luks2(struct crypt_device *cd,
goto out;
}
r = LUKS2_wipe_header_areas(cd, &cd->u.luks2.hdr);
r = LUKS2_wipe_header_areas(cd, &cd->u.luks2.hdr, cd->metadata_device != NULL);
if (r < 0) {
log_err(cd, _("Cannot wipe header on device %s."),
mdata_device_path(cd));
if (dev_size < LUKS2_hdr_and_areas_size(cd->u.luks2.hdr.jobj))
if (dev_size < LUKS2_hdr_and_areas_size(&cd->u.luks2.hdr))
log_err(cd, _("Device %s is too small."), device_path(crypt_metadata_device(cd)));
goto out;
}
@@ -2035,7 +2035,7 @@ static int _crypt_format_verity(struct crypt_device *cd,
} else
cd->u.verity.hdr.data_size = params->data_size;
if (device_is_identical(crypt_metadata_device(cd), crypt_data_device(cd)) &&
if (device_is_identical(crypt_metadata_device(cd), crypt_data_device(cd)) > 0 &&
(cd->u.verity.hdr.data_size * params->data_block_size) > params->hash_area_offset) {
log_err(cd, _("Data area overlaps with hash area."));
return -EINVAL;
@@ -2060,14 +2060,14 @@ static int _crypt_format_verity(struct crypt_device *cd,
}
hash_blocks_size = VERITY_hash_blocks(cd, params) * params->hash_block_size;
if (device_is_identical(crypt_metadata_device(cd), fec_device) &&
if (device_is_identical(crypt_metadata_device(cd), fec_device) > 0 &&
(params->hash_area_offset + hash_blocks_size) > params->fec_area_offset) {
log_err(cd, _("Hash area overlaps with FEC area."));
r = -EINVAL;
goto err;
}
if (device_is_identical(crypt_data_device(cd), fec_device) &&
if (device_is_identical(crypt_data_device(cd), fec_device) > 0 &&
(cd->u.verity.hdr.data_size * params->data_block_size) > params->fec_area_offset) {
log_err(cd, _("Data area overlaps with FEC area."));
r = -EINVAL;
@@ -2388,11 +2388,6 @@ static int _compare_crypt_devices(struct crypt_device *cd,
if (!src->u.crypt.vk || !tgt->u.crypt.vk)
return -EINVAL;
if (_compare_volume_keys(src->u.crypt.vk, 0, tgt->u.crypt.vk, tgt->u.crypt.vk->key_description != NULL)) {
log_dbg(cd, "Keys in context and target device do not match.");
return -EINVAL;
}
/* CIPHER checks */
if (!src->u.crypt.cipher || !tgt->u.crypt.cipher)
return -EINVAL;
@@ -2400,6 +2395,14 @@ static int _compare_crypt_devices(struct crypt_device *cd,
log_dbg(cd, "Cipher specs do not match.");
return -EINVAL;
}
if (tgt->u.crypt.vk->keylength == 0 && crypt_is_cipher_null(tgt->u.crypt.cipher))
log_dbg(cd, "Existing device uses cipher null. Skipping key comparison.");
else if (_compare_volume_keys(src->u.crypt.vk, 0, tgt->u.crypt.vk, tgt->u.crypt.vk->key_description != NULL)) {
log_dbg(cd, "Keys in context and target device do not match.");
return -EINVAL;
}
if (crypt_strcmp(src->u.crypt.integrity, tgt->u.crypt.integrity)) {
log_dbg(cd, "Integrity parameters do not match.");
return -EINVAL;
@@ -2413,7 +2416,7 @@ static int _compare_crypt_devices(struct crypt_device *cd,
return -EINVAL;
}
if (!device_is_identical(src->data_device, tgt->data_device)) {
if (device_is_identical(src->data_device, tgt->data_device) <= 0) {
log_dbg(cd, "Data devices do not match.");
return -EINVAL;
}
@@ -2467,7 +2470,7 @@ static int _compare_integrity_devices(struct crypt_device *cd,
return -EINVAL;
}
if (!device_is_identical(src->data_device, tgt->data_device)) {
if (device_is_identical(src->data_device, tgt->data_device) <= 0) {
log_dbg(cd, "Data devices do not match.");
return -EINVAL;
}
@@ -2770,6 +2773,11 @@ int crypt_resize(struct crypt_device *cd, const char *name, uint64_t new_size)
if (!cd || !cd->type || !name)
return -EINVAL;
if (isTCRYPT(cd->type) || isBITLK(cd->type)) {
log_err(cd, _("This operation is not supported for this device type."));
return -ENOTSUP;
}
log_dbg(cd, "Resizing device %s to %" PRIu64 " sectors.", name, new_size);
r = dm_query_device(cd, name, DM_ACTIVE_CRYPT_KEYSIZE | DM_ACTIVE_CRYPT_KEY, &dmdq);
@@ -3090,6 +3098,45 @@ out:
return r;
}
/* key must be properly verified */
static int resume_by_volume_key(struct crypt_device *cd,
struct volume_key *vk,
const char *name)
{
int digest, r;
struct volume_key *zerokey = NULL;
if (crypt_is_cipher_null(crypt_get_cipher_spec(cd))) {
zerokey = crypt_alloc_volume_key(0, NULL);
if (!zerokey)
return -ENOMEM;
vk = zerokey;
} else if (crypt_use_keyring_for_vk(cd)) {
/* LUKS2 path only */
digest = LUKS2_digest_by_segment(&cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT);
if (digest < 0)
return -EINVAL;
r = LUKS2_volume_key_load_in_keyring_by_digest(cd,
&cd->u.luks2.hdr, vk, digest);
if (r < 0)
return r;
}
r = dm_resume_and_reinstate_key(cd, name, vk);
if (r == -ENOTSUP)
log_err(cd, _("Resume is not supported for device %s."), name);
else if (r)
log_err(cd, _("Error during resuming device %s."), name);
if (r < 0)
crypt_drop_keyring_key(cd, vk);
crypt_free_volume_key(zerokey);
return r;
}
int crypt_resume_by_passphrase(struct crypt_device *cd,
const char *name,
int keyslot,
@@ -3125,32 +3172,13 @@ int crypt_resume_by_passphrase(struct crypt_device *cd,
r = LUKS2_keyslot_open(cd, keyslot, CRYPT_DEFAULT_SEGMENT, passphrase, passphrase_size, &vk);
if (r < 0)
goto out;
return r;
keyslot = r;
if (crypt_use_keyring_for_vk(cd)) {
if (!isLUKS2(cd->type)) {
r = -EINVAL;
goto out;
}
r = LUKS2_volume_key_load_in_keyring_by_keyslot(cd,
&cd->u.luks2.hdr, vk, keyslot);
if (r < 0)
goto out;
}
r = resume_by_volume_key(cd, vk, name);
r = dm_resume_and_reinstate_key(cd, name, vk);
if (r == -ENOTSUP)
log_err(cd, _("Resume is not supported for device %s."), name);
else if (r)
log_err(cd, _("Error during resuming device %s."), name);
out:
if (r < 0)
crypt_drop_keyring_key(cd, vk);
crypt_free_volume_key(vk);
return r < 0 ? r : keyslot;
}
@@ -3189,35 +3217,22 @@ int crypt_resume_by_keyfile_device_offset(struct crypt_device *cd,
&passphrase_read, &passphrase_size_read,
keyfile_offset, keyfile_size, 0);
if (r < 0)
goto out;
return r;
if (isLUKS1(cd->type))
r = LUKS_open_key_with_hdr(keyslot, passphrase_read, passphrase_size_read,
&cd->u.luks1.hdr, &vk, cd);
else
r = LUKS2_keyslot_open(cd, keyslot, CRYPT_DEFAULT_SEGMENT, passphrase_read, passphrase_size_read, &vk);
if (r < 0)
goto out;
keyslot = r;
if (crypt_use_keyring_for_vk(cd)) {
if (!isLUKS2(cd->type)) {
r = -EINVAL;
goto out;
}
r = LUKS2_volume_key_load_in_keyring_by_keyslot(cd,
&cd->u.luks2.hdr, vk, keyslot);
if (r < 0)
goto out;
}
r = dm_resume_and_reinstate_key(cd, name, vk);
if (r < 0)
log_err(cd, _("Error during resuming device %s."), name);
out:
crypt_safe_free(passphrase_read);
if (r < 0)
crypt_drop_keyring_key(cd, vk);
return r;
keyslot = r;
r = resume_by_volume_key(cd, vk, name);
crypt_free_volume_key(vk);
return r < 0 ? r : keyslot;
}
@@ -3280,24 +3295,10 @@ int crypt_resume_by_volume_key(struct crypt_device *cd,
r = -EINVAL;
if (r == -EPERM || r == -ENOENT)
log_err(cd, _("Volume key does not match the volume."));
if (r < 0)
goto out;
r = 0;
if (crypt_use_keyring_for_vk(cd)) {
r = LUKS2_key_description_by_segment(cd, &cd->u.luks2.hdr, vk, CRYPT_DEFAULT_SEGMENT);
if (!r)
r = crypt_volume_key_load_in_keyring(cd, vk);
}
if (r < 0)
goto out;
if (r >= 0)
r = resume_by_volume_key(cd, vk, name);
r = dm_resume_and_reinstate_key(cd, name, vk);
if (r < 0)
log_err(cd, _("Error during resuming device %s."), name);
out:
if (r < 0)
crypt_drop_keyring_key(cd, vk);
crypt_free_volume_key(vk);
return r;
}
@@ -3459,6 +3460,9 @@ int crypt_keyslot_change_by_passphrase(struct crypt_device *cd,
r = LUKS2_digest_assign(cd, &cd->u.luks2.hdr, keyslot_new, digest, 1, 0);
if (r < 0)
goto out;
r = LUKS2_token_assignment_copy(cd, &cd->u.luks2.hdr, keyslot_old, keyslot_new, 0);
if (r < 0)
goto out;
} else {
log_dbg(cd, "Key slot %d is going to be overwritten.", keyslot_old);
/* FIXME: improve return code so that we can detect area is damaged */
@@ -3686,7 +3690,7 @@ static int _check_header_data_overlap(struct crypt_device *cd, const char *name)
if (!name || !isLUKS(cd->type))
return 0;
if (!device_is_identical(crypt_data_device(cd), crypt_metadata_device(cd)))
if (device_is_identical(crypt_data_device(cd), crypt_metadata_device(cd)) <= 0)
return 0;
/* FIXME: check real header size */
@@ -3853,21 +3857,6 @@ out:
return r;
}
static int load_all_keys(struct crypt_device *cd, struct luks2_hdr *hdr, struct volume_key *vks)
{
int r;
struct volume_key *vk = vks;
while (vk) {
r = LUKS2_volume_key_load_in_keyring_by_digest(cd, hdr, vk, crypt_volume_key_get_id(vk));
if (r < 0)
return r;
vk = crypt_volume_key_next(vk);
}
return 0;
}
/* See fixmes in _open_and_activate_luks2 */
int update_reencryption_flag(struct crypt_device *cd, int enable, bool commit);
@@ -3879,6 +3868,7 @@ static int _open_and_activate(struct crypt_device *cd,
size_t passphrase_size,
uint32_t flags)
{
bool use_keyring;
int r;
struct volume_key *vk = NULL;
@@ -3890,8 +3880,13 @@ static int _open_and_activate(struct crypt_device *cd,
return r;
keyslot = r;
if ((name || (flags & CRYPT_ACTIVATE_KEYRING_KEY)) &&
crypt_use_keyring_for_vk(cd)) {
if (!crypt_use_keyring_for_vk(cd))
use_keyring = false;
else
use_keyring = ((name && !crypt_is_cipher_null(crypt_get_cipher(cd))) ||
(flags & CRYPT_ACTIVATE_KEYRING_KEY));
if (use_keyring) {
r = LUKS2_volume_key_load_in_keyring_by_keyslot(cd,
&cd->u.luks2.hdr, vk, keyslot);
if (r < 0)
@@ -3909,6 +3904,22 @@ out:
return r < 0 ? r : keyslot;
}
#if USE_LUKS2_REENCRYPTION
static int load_all_keys(struct crypt_device *cd, struct luks2_hdr *hdr, struct volume_key *vks)
{
int r;
struct volume_key *vk = vks;
while (vk) {
r = LUKS2_volume_key_load_in_keyring_by_digest(cd, hdr, vk, crypt_volume_key_get_id(vk));
if (r < 0)
return r;
vk = crypt_volume_key_next(vk);
}
return 0;
}
static int _open_all_keys(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot,
@@ -3919,7 +3930,7 @@ static int _open_all_keys(struct crypt_device *cd,
{
int r, segment;
struct volume_key *_vks = NULL;
crypt_reencrypt_info ri = LUKS2_reenc_status(hdr);
crypt_reencrypt_info ri = LUKS2_reencrypt_status(hdr);
segment = (flags & CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY) ? CRYPT_ANY_SEGMENT : CRYPT_DEFAULT_SEGMENT;
@@ -3975,7 +3986,7 @@ static int _open_and_activate_reencrypt_device(struct crypt_device *cd,
if (crypt_use_keyring_for_vk(cd))
flags |= CRYPT_ACTIVATE_KEYRING_KEY;
r = crypt_reencrypt_lock(cd, &reencrypt_lock);
r = LUKS2_reencrypt_lock(cd, &reencrypt_lock);
if (r) {
if (r == -EBUSY)
log_err(cd, _("Reencryption in-progress. Cannot activate device."));
@@ -3987,7 +3998,7 @@ static int _open_and_activate_reencrypt_device(struct crypt_device *cd,
if ((r = crypt_load(cd, CRYPT_LUKS2, NULL)))
goto err;
ri = LUKS2_reenc_status(hdr);
ri = LUKS2_reencrypt_status(hdr);
if (ri == CRYPT_REENCRYPT_CRASH) {
r = LUKS2_reencrypt_locked_recovery_by_passphrase(cd, keyslot,
@@ -3998,14 +4009,14 @@ static int _open_and_activate_reencrypt_device(struct crypt_device *cd,
}
keyslot = r;
ri = LUKS2_reenc_status(hdr);
ri = LUKS2_reencrypt_status(hdr);
}
/* recovery finished reencryption or it's already finished */
if (ri == CRYPT_REENCRYPT_NONE) {
crypt_drop_keyring_key(cd, vks);
crypt_free_volume_key(vks);
crypt_reencrypt_unlock(cd, reencrypt_lock);
LUKS2_reencrypt_unlock(cd, reencrypt_lock);
return _open_and_activate(cd, keyslot, name, passphrase, passphrase_size, flags);
}
@@ -4023,15 +4034,21 @@ static int _open_and_activate_reencrypt_device(struct crypt_device *cd,
keyslot = r;
}
if (r >= 0) {
r = LUKS2_reencrypt_digest_verify(cd, hdr, vks);
if (r < 0)
goto err;
}
log_dbg(cd, "Entering clean reencryption state mode.");
if (r >= 0)
r = luks2_check_device_size(cd, hdr, minimal_size, &device_size, true, dynamic_size);
r = LUKS2_reencrypt_check_device_size(cd, hdr, minimal_size, &device_size, true, dynamic_size);
if (r >= 0)
r = LUKS2_activate_multi(cd, name, vks, device_size >> SECTOR_SHIFT, flags);
err:
crypt_reencrypt_unlock(cd, reencrypt_lock);
LUKS2_reencrypt_unlock(cd, reencrypt_lock);
if (r < 0)
crypt_drop_keyring_key(cd, vks);
crypt_free_volume_key(vks);
@@ -4050,10 +4067,11 @@ static int _open_and_activate_luks2(struct crypt_device *cd,
uint32_t flags)
{
crypt_reencrypt_info ri;
int r;
int r, rv;
struct luks2_hdr *hdr = &cd->u.luks2.hdr;
struct volume_key *vks = NULL;
ri = LUKS2_reenc_status(hdr);
ri = LUKS2_reencrypt_status(hdr);
if (ri == CRYPT_REENCRYPT_INVALID)
return -EINVAL;
@@ -4061,15 +4079,45 @@ static int _open_and_activate_luks2(struct crypt_device *cd,
if (name)
r = _open_and_activate_reencrypt_device(cd, hdr, keyslot, name, passphrase,
passphrase_size, flags);
else
else {
r = _open_all_keys(cd, hdr, keyslot, passphrase,
passphrase_size, flags, NULL);
passphrase_size, flags, &vks);
if (r < 0)
return r;
rv = LUKS2_reencrypt_digest_verify(cd, hdr, vks);
crypt_free_volume_key(vks);
if (rv < 0)
return rv;
}
} else
r = _open_and_activate(cd, keyslot, name, passphrase,
passphrase_size, flags);
return r;
}
#else
static int _open_and_activate_luks2(struct crypt_device *cd,
int keyslot,
const char *name,
const char *passphrase,
size_t passphrase_size,
uint32_t flags)
{
crypt_reencrypt_info ri;
ri = LUKS2_reencrypt_status(&cd->u.luks2.hdr);
if (ri == CRYPT_REENCRYPT_INVALID)
return -EINVAL;
if (ri > CRYPT_REENCRYPT_NONE) {
log_err(cd, _("This operation is not supported for this device type."));
return -ENOTSUP;
}
return _open_and_activate(cd, keyslot, name, passphrase, passphrase_size, flags);
}
#endif
static int _activate_by_passphrase(struct crypt_device *cd,
const char *name,
@@ -4161,21 +4209,26 @@ static int _activate_loopaes(struct crypt_device *cd,
static int _activate_check_status(struct crypt_device *cd, const char *name, unsigned reload)
{
crypt_status_info ci;
int r;
if (!name)
return 0;
ci = crypt_status(cd, name);
if (ci == CRYPT_INVALID) {
log_err(cd, _("Cannot use device %s, name is invalid or still in use."), name);
return -EINVAL;
} else if (ci >= CRYPT_ACTIVE && !reload) {
r = dm_status_device(cd, name);
if (r >= 0 && reload)
return 0;
if (r >= 0 || r == -EEXIST) {
log_err(cd, _("Device %s already exists."), name);
return -EEXIST;
}
return 0;
if (r == -ENODEV)
return 0;
log_err(cd, _("Cannot use device %s, name is invalid or still in use."), name);
return r;
}
// activation/deactivation of device mapping
@@ -4269,6 +4322,7 @@ int crypt_activate_by_volume_key(struct crypt_device *cd,
size_t volume_key_size,
uint32_t flags)
{
bool use_keyring;
struct volume_key *vk = NULL;
int r;
@@ -4344,8 +4398,12 @@ int crypt_activate_by_volume_key(struct crypt_device *cd,
if (r > 0)
r = 0;
if (!r && (name || (flags & CRYPT_ACTIVATE_KEYRING_KEY)) &&
crypt_use_keyring_for_vk(cd)) {
if (!crypt_use_keyring_for_vk(cd))
use_keyring = false;
else
use_keyring = (name && !crypt_is_cipher_null(crypt_get_cipher(cd))) || (flags & CRYPT_ACTIVATE_KEYRING_KEY);
if (!r && use_keyring) {
r = LUKS2_key_description_by_segment(cd,
&cd->u.luks2.hdr, vk, CRYPT_DEFAULT_SEGMENT);
if (!r)
@@ -4406,7 +4464,7 @@ int crypt_activate_by_signed_key(struct crypt_device *cd,
return -EINVAL;
}
log_dbg(cd, "%s volume %s by signed key.", name ? "Activating" : "Checking", name ?: "");
log_dbg(cd, "%s volume %s by %skey.", name ? "Activating" : "Checking", name ?: "", signature ? "signed " : "");
if (cd->u.verity.hdr.flags & CRYPT_VERITY_ROOT_HASH_SIGNATURE && !signature) {
log_err(cd, _("Root hash signature required."));
@@ -4956,6 +5014,9 @@ const char *crypt_get_cipher_mode(struct crypt_device *cd)
/* INTERNAL only */
const char *crypt_get_integrity(struct crypt_device *cd)
{
if (!cd)
return NULL;
if (isINTEGRITY(cd->type))
return cd->u.integrity.params.integrity;
@@ -5235,8 +5296,8 @@ int crypt_get_metadata_size(struct crypt_device *cd,
msize = LUKS_ALIGN_KEYSLOTS;
ksize = LUKS_device_sectors(&cd->u.luks1.hdr) * SECTOR_SIZE - msize;
} else if (isLUKS2(cd->type)) {
msize = LUKS2_metadata_size(cd->u.luks2.hdr.jobj);
ksize = LUKS2_keyslots_size(cd->u.luks2.hdr.jobj);
msize = LUKS2_metadata_size(&cd->u.luks2.hdr);
ksize = LUKS2_keyslots_size(&cd->u.luks2.hdr);
} else
return -EINVAL;
@@ -5510,13 +5571,13 @@ void *crypt_get_hdr(struct crypt_device *cd, const char *type)
}
/* internal only */
struct luks2_reenc_context *crypt_get_reenc_context(struct crypt_device *cd)
struct luks2_reencrypt *crypt_get_luks2_reencrypt(struct crypt_device *cd)
{
return cd->u.luks2.rh;
}
/* internal only */
void crypt_set_reenc_context(struct crypt_device *cd, struct luks2_reenc_context *rh)
void crypt_set_luks2_reencrypt(struct crypt_device *cd, struct luks2_reencrypt *rh)
{
cd->u.luks2.rh = rh;
}
@@ -6039,7 +6100,7 @@ crypt_reencrypt_info crypt_reencrypt_status(struct crypt_device *cd,
if (_onlyLUKS2(cd, CRYPT_CD_QUIET, CRYPT_REQUIREMENT_ONLINE_REENCRYPT))
return CRYPT_REENCRYPT_INVALID;
return LUKS2_reencrypt_status(cd, params);
return LUKS2_reencrypt_get_params(&cd->u.luks2.hdr, params);
}
static void __attribute__((destructor)) libcryptsetup_exit(void)

View File

@@ -1,8 +1,8 @@
/*
* TCRYPT (TrueCrypt-compatible) and VeraCrypt volume handling
*
* Copyright (C) 2012-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2020 Milan Broz
* Copyright (C) 2012-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2021 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -749,7 +749,7 @@ int TCRYPT_activate(struct crypt_device *cd,
return -ENOTSUP;
}
if (hdr->d.sector_size && hdr->d.sector_size != SECTOR_SIZE) {
if (hdr->d.sector_size % SECTOR_SIZE) {
log_err(cd, _("Activation is not supported for %d sector size."),
hdr->d.sector_size);
return -ENOTSUP;
@@ -769,15 +769,12 @@ int TCRYPT_activate(struct crypt_device *cd,
if (!algs)
return -EINVAL;
if (hdr->d.sector_size == 0)
return -EINVAL;
if (params->flags & CRYPT_TCRYPT_SYSTEM_HEADER)
dmd.size = 0;
else if (params->flags & CRYPT_TCRYPT_HIDDEN_HEADER)
dmd.size = hdr->d.hidden_volume_size / hdr->d.sector_size;
dmd.size = hdr->d.hidden_volume_size / SECTOR_SIZE;
else
dmd.size = hdr->d.volume_size / hdr->d.sector_size;
dmd.size = hdr->d.volume_size / SECTOR_SIZE;
if (dmd.flags & CRYPT_ACTIVATE_SHARED)
device_check = DEV_OK;
@@ -1031,7 +1028,7 @@ uint64_t TCRYPT_get_data_offset(struct crypt_device *cd,
/* Mapping through whole device, not partition! */
if (params->flags & CRYPT_TCRYPT_SYSTEM_HEADER) {
if (crypt_dev_is_partition(device_path(crypt_metadata_device(cd))))
if (crypt_dev_is_partition(device_path(crypt_data_device(cd))))
return 0;
goto hdr_offset;
}
@@ -1042,11 +1039,11 @@ uint64_t TCRYPT_get_data_offset(struct crypt_device *cd,
if (params->flags & CRYPT_TCRYPT_HIDDEN_HEADER) {
if (hdr->d.version > 3)
return (hdr->d.mk_offset / hdr->d.sector_size);
return (hdr->d.mk_offset / SECTOR_SIZE);
if (device_size(crypt_metadata_device(cd), &size) < 0)
return 0;
return (size - hdr->d.hidden_volume_size +
(TCRYPT_HDR_HIDDEN_OFFSET_OLD)) / hdr->d.sector_size;
(TCRYPT_HDR_HIDDEN_OFFSET_OLD)) / SECTOR_SIZE;
}
goto hdr_offset;
}
@@ -1055,11 +1052,11 @@ uint64_t TCRYPT_get_data_offset(struct crypt_device *cd,
if (device_size(crypt_metadata_device(cd), &size) < 0)
return 0;
return (size - hdr->d.hidden_volume_size +
(TCRYPT_HDR_HIDDEN_OFFSET_OLD)) / hdr->d.sector_size;
(TCRYPT_HDR_HIDDEN_OFFSET_OLD)) / SECTOR_SIZE;
}
hdr_offset:
return hdr->d.mk_offset / hdr->d.sector_size;
return hdr->d.mk_offset / SECTOR_SIZE;
}
uint64_t TCRYPT_get_iv_offset(struct crypt_device *cd,
@@ -1073,10 +1070,10 @@ uint64_t TCRYPT_get_iv_offset(struct crypt_device *cd,
else if (params->mode && !strncmp(params->mode, "lrw", 3))
iv_offset = 0;
else
iv_offset = hdr->d.mk_offset / hdr->d.sector_size;
iv_offset = hdr->d.mk_offset / SECTOR_SIZE;
if (params->flags & CRYPT_TCRYPT_SYSTEM_HEADER)
iv_offset += crypt_dev_partition_offset(device_path(crypt_metadata_device(cd)));
iv_offset += crypt_dev_partition_offset(device_path(crypt_data_device(cd)));
return iv_offset;
}

View File

@@ -1,8 +1,8 @@
/*
* TCRYPT (TrueCrypt-compatible) header definition
*
* Copyright (C) 2012-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2020 Milan Broz
* Copyright (C) 2012-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2021 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

@@ -3,8 +3,8 @@
*
* Copyright (C) 2004 Jana Saout <jana@saout.de>
* Copyright (C) 2004-2007 Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2009-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2020 Milan Broz
* Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2021 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,8 +1,8 @@
/*
* libcryptsetup - cryptsetup library, cipher benchmark
*
* Copyright (C) 2012-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2020 Milan Broz
* Copyright (C) 2012-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2021 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 @@
/*
* blkid probe utilities
*
* Copyright (C) 2018-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2018-2021 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

View File

@@ -1,7 +1,7 @@
/*
* blkid probe utilities
*
* Copyright (C) 2018-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2018-2021 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
@@ -21,6 +21,8 @@
#ifndef _UTILS_BLKID_H
#define _UTILS_BLKID_H
#include <sys/types.h>
struct blkid_handle;
typedef enum { PRB_OK = 0, PRB_EMPTY, PRB_AMBIGUOUS, PRB_FAIL } blk_probe_status;

View File

@@ -2,8 +2,8 @@
* utils_crypt - cipher utilities for cryptsetup
*
* Copyright (C) 2004-2007 Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2009-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2020 Milan Broz
* Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2021 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -23,6 +23,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include "libcryptsetup.h"
@@ -76,14 +77,16 @@ int crypt_parse_hash_integrity_mode(const char *s, char *integrity)
return -EINVAL;
r = sscanf(s, "%" MAX_CIPHER_LEN_STR "[^-]-%" MAX_CIPHER_LEN_STR "s", mode, hash);
if (r == 2)
if (r == 2 && !isdigit(hash[0]))
r = snprintf(integrity, MAX_CIPHER_LEN, "%s(%s)", mode, hash);
else if (r == 2)
r = snprintf(integrity, MAX_CIPHER_LEN, "%s-%s", mode, hash);
else if (r == 1)
r = snprintf(integrity, MAX_CIPHER_LEN, "%s", mode);
else
return -EINVAL;
if (r < 0 || r == MAX_CIPHER_LEN)
if (r < 0 || r >= MAX_CIPHER_LEN)
return -EINVAL;
return 0;
@@ -174,3 +177,10 @@ ssize_t crypt_hex_to_bytes(const char *hex, char **result, int safe_alloc)
*result = bytes;
return i;
}
bool crypt_is_cipher_null(const char *cipher_spec)
{
if (!cipher_spec)
return false;
return (strstr(cipher_spec, "cipher_null") || !strcmp(cipher_spec, "null"));
}

View File

@@ -2,8 +2,8 @@
* utils_crypt - cipher utilities for cryptsetup
*
* Copyright (C) 2004-2007 Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2009-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2020 Milan Broz
* Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2021 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -23,6 +23,7 @@
#ifndef _UTILS_CRYPT_H
#define _UTILS_CRYPT_H
#include <stdbool.h>
#include <unistd.h>
#define MAX_CIPHER_LEN 32
@@ -38,4 +39,6 @@ int crypt_parse_pbkdf(const char *s, const char **pbkdf);
ssize_t crypt_hex_to_bytes(const char *hex, char **result, int safe_alloc);
bool crypt_is_cipher_null(const char *cipher_spec);
#endif /* _UTILS_CRYPT_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-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2020 Milan Broz
* Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2021 Milan Broz
*
* 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,9 @@ static int device_ready(struct crypt_device *cd, struct device *device)
struct stat st;
size_t tmp_size;
if (!device)
return -EINVAL;
if (device->o_direct) {
log_dbg(cd, "Trying to open and read device %s with direct-io.",
device_path(device));
@@ -217,6 +220,9 @@ static int _open_locked(struct crypt_device *cd, struct device *device, int flag
{
int fd;
if (!device)
return -EINVAL;
log_dbg(cd, "Opening locked device %s", device_path(device));
if ((flags & O_ACCMODE) != O_RDONLY && device_locked_readonly(device->lh)) {
@@ -300,6 +306,9 @@ static int device_open_internal(struct crypt_device *cd, struct device *device,
int device_open(struct crypt_device *cd, struct device *device, int flags)
{
if (!device)
return -EINVAL;
assert(!device_locked(device->lh));
return device_open_internal(cd, device, flags);
}
@@ -354,6 +363,9 @@ void device_release_excl(struct crypt_device *cd, struct device *device)
int device_open_locked(struct crypt_device *cd, struct device *device, int flags)
{
if (!device)
return -EINVAL;
assert(!crypt_metadata_locking_enabled() || device_locked(device->lh));
return device_open_internal(cd, device, flags);
}
@@ -520,10 +532,16 @@ void device_topology_alignment(struct crypt_device *cd,
temp_alignment = (unsigned long)min_io_size;
/* Ignore bogus opt-io that could break alignment */
/*
* Ignore bogus opt-io that could break alignment.
* Also real opt_io_size should be aligned to minimal page size (4k).
* Some bogus USB enclosures reports wrong data here.
*/
if ((temp_alignment < (unsigned long)opt_io_size) &&
!((unsigned long)opt_io_size % temp_alignment))
!((unsigned long)opt_io_size % temp_alignment) && !MISALIGNED_4K(opt_io_size))
temp_alignment = (unsigned long)opt_io_size;
else if (opt_io_size && (opt_io_size != min_io_size))
log_err(cd, _("Ignoring bogus optimal-io size for data device (%u bytes)."), opt_io_size);
/* If calculated alignment is multiple of default, keep default */
if (temp_alignment && (default_alignment % temp_alignment))
@@ -583,8 +601,11 @@ int device_size(struct device *device, uint64_t *size)
struct stat st;
int devfd, r = -EINVAL;
if (!device)
return -EINVAL;
devfd = open(device->path, O_RDONLY);
if(devfd == -1)
if (devfd == -1)
return -EINVAL;
if (fstat(devfd, &st) < 0)
@@ -606,6 +627,9 @@ int device_fallocate(struct device *device, uint64_t size)
struct stat st;
int devfd, r = -EINVAL;
if (!device)
return -EINVAL;
devfd = open(device_path(device), O_RDWR);
if (devfd == -1)
return -EINVAL;
@@ -846,22 +870,30 @@ size_t size_round_up(size_t size, size_t block)
void device_disable_direct_io(struct device *device)
{
device->o_direct = 0;
if (device)
device->o_direct = 0;
}
int device_direct_io(const struct device *device)
{
return device->o_direct;
return device ? device->o_direct : 0;
}
static dev_t device_devno(const struct device *device)
static int device_compare_path(const char *path1, const char *path2)
{
struct stat st;
struct stat st_path1, st_path2;
if (stat(device->path, &st) || !S_ISBLK(st.st_mode))
return 0;
if (stat(path1, &st_path1 ) < 0 || stat(path2, &st_path2 ) < 0)
return -EINVAL;
return st.st_rdev;
if (S_ISBLK(st_path1.st_mode) && S_ISBLK(st_path2.st_mode))
return (st_path1.st_rdev == st_path2.st_rdev) ? 1 : 0;
if (S_ISREG(st_path1.st_mode) && S_ISREG(st_path2.st_mode))
return (st_path1.st_ino == st_path2.st_ino &&
st_path1.st_dev == st_path2.st_dev) ? 1 : 0;
return 0;
}
int device_is_identical(struct device *device1, struct device *device2)
@@ -872,21 +904,19 @@ int device_is_identical(struct device *device1, struct device *device2)
if (device1 == device2)
return 1;
if (device1->init_done && device2->init_done)
return (device_devno(device1) == device_devno(device2));
else if (device1->init_done || device2->init_done)
return 0;
if (!strcmp(device_path(device1), device_path(device2)))
return 1;
return 0;
return device_compare_path(device_path(device1), device_path(device2));
}
int device_is_rotational(struct device *device)
{
struct stat st;
if (!device)
return -EINVAL;
if (stat(device_path(device), &st) < 0)
return -EINVAL;
@@ -900,6 +930,9 @@ size_t device_alignment(struct device *device)
{
int devfd;
if (!device)
return -EINVAL;
if (!device->alignment) {
devfd = open(device_path(device), O_RDONLY);
if (devfd != -1) {
@@ -913,17 +946,18 @@ size_t device_alignment(struct device *device)
void device_set_lock_handle(struct device *device, struct crypt_lock_handle *h)
{
device->lh = h;
if (device)
device->lh = h;
}
struct crypt_lock_handle *device_get_lock_handle(struct device *device)
{
return device->lh;
return device ? device->lh : NULL;
}
int device_read_lock(struct crypt_device *cd, struct device *device)
{
if (!crypt_metadata_locking_enabled())
if (!device || !crypt_metadata_locking_enabled())
return 0;
if (device_read_lock_internal(cd, device))
@@ -934,7 +968,7 @@ int device_read_lock(struct crypt_device *cd, struct device *device)
int device_write_lock(struct crypt_device *cd, struct device *device)
{
if (!crypt_metadata_locking_enabled())
if (!device || !crypt_metadata_locking_enabled())
return 0;
assert(!device_locked(device->lh) || !device_locked_readonly(device->lh));
@@ -944,7 +978,7 @@ int device_write_lock(struct crypt_device *cd, struct device *device)
void device_read_unlock(struct crypt_device *cd, struct device *device)
{
if (!crypt_metadata_locking_enabled())
if (!device || !crypt_metadata_locking_enabled())
return;
assert(device_locked(device->lh));
@@ -954,7 +988,7 @@ void device_read_unlock(struct crypt_device *cd, struct device *device)
void device_write_unlock(struct crypt_device *cd, struct device *device)
{
if (!crypt_metadata_locking_enabled())
if (!device || !crypt_metadata_locking_enabled())
return;
assert(device_locked(device->lh) && !device_locked_readonly(device->lh));

View File

@@ -1,8 +1,8 @@
/*
* Metadata on-disk locking for processes serialization
*
* Copyright (C) 2016-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2016-2020 Ondrej Kozina
* Copyright (C) 2016-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2016-2021 Ondrej Kozina
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -106,7 +106,7 @@ static int open_lock_dir(struct crypt_device *cd, const char *dir, const char *b
lockdfd = openat(dirfd, base, O_RDONLY | O_NOFOLLOW | O_DIRECTORY | O_CLOEXEC);
if (lockdfd < 0) {
if (errno == ENOENT) {
log_std(cd, _("WARNING: Locking directory %s/%s is missing!\n"), dir, base);
log_dbg(cd, _("Locking directory %s/%s will be created with default compiled-in permissions."), dir, base);
/* success or failure w/ errno == EEXIST either way just try to open the 'base' directory again */
if (mkdirat(dirfd, base, DEFAULT_LUKS2_LOCK_DIR_PERMS) && errno != EEXIST)

View File

@@ -1,8 +1,8 @@
/*
* Metadata on-disk locking for processes serialization
*
* Copyright (C) 2016-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2016-2020 Ondrej Kozina
* Copyright (C) 2016-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2016-2021 Ondrej Kozina
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -22,6 +22,8 @@
#ifndef _CRYPTSETUP_UTILS_LOCKING_H
#define _CRYPTSETUP_UTILS_LOCKING_H
#include <stdbool.h>
struct crypt_device;
struct crypt_lock_handle;
struct device;

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-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2020 Milan Broz
* Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2021 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -367,7 +367,9 @@ char *crypt_get_base_device(const char *dev_path)
if (dm_is_dm_kernel_name(devname))
return NULL;
snprintf(part_path, sizeof(part_path), "/dev/%s", devname);
if (snprintf(part_path, sizeof(part_path), "/dev/%s", devname) < 0)
return NULL;
return strdup(part_path);
}

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-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2020 Milan Broz
* Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2021 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,8 @@
#define _UTILS_DM_H
/* device-mapper library helpers */
#include <inttypes.h>
#include <stddef.h>
#include <stdint.h>
struct crypt_device;
struct volume_key;
@@ -69,6 +70,9 @@ static inline uint32_t act2dmflags(uint32_t act_flags)
#define DM_BITLK_ELEPHANT_SUPPORTED (1 << 21) /* Elephant diffuser for BITLK supported */
#define DM_VERITY_SIGNATURE_SUPPORTED (1 << 22) /* Verity option root_hash_sig_key_desc supported */
#define DM_INTEGRITY_DISCARDS_SUPPORTED (1 << 23) /* dm-integrity discards/TRIM option is supported */
#define DM_VERITY_PANIC_CORRUPTION_SUPPORTED (1 << 24) /* dm-verity panic on corruption */
#define DM_CRYPT_NO_WORKQUEUE_SUPPORTED (1 << 25) /* dm-crypt suppot for bypassing workqueues */
#define DM_INTEGRITY_FIX_HMAC_SUPPORTED (1 << 26) /* hmac covers also superblock */
typedef enum { DM_CRYPT = 0, DM_VERITY, DM_INTEGRITY, DM_LINEAR, DM_ERROR, DM_ZERO, DM_UNKNOWN } dm_target_type;
enum tdirection { TARGET_SET = 1, TARGET_QUERY };
@@ -118,9 +122,8 @@ struct dm_target {
const char *root_hash_sig_key_desc;
uint64_t hash_offset; /* hash offset in blocks (not header) */
uint64_t hash_blocks; /* size of hash device (in hash blocks) */
uint64_t fec_offset; /* FEC offset in blocks (not header) */
uint64_t fec_blocks; /* size of FEC device (in hash blocks) */
uint64_t fec_blocks; /* FEC blocks covering data + hash + padding (foreign metadata)*/
struct crypt_params_verity *vp;
} verity;
struct {
@@ -146,6 +149,8 @@ struct dm_target {
struct device *meta_device;
bool fix_padding;
bool fix_hmac;
bool legacy_recalc;
} integrity;
struct {
uint64_t offset;
@@ -185,8 +190,8 @@ int dm_crypt_target_set(struct dm_target *tgt, uint64_t seg_offset, uint64_t seg
uint32_t tag_size, uint32_t sector_size);
int dm_verity_target_set(struct dm_target *tgt, uint64_t seg_offset, uint64_t seg_size,
struct device *data_device, struct device *hash_device, struct device *fec_device,
const char *root_hash, uint32_t root_hash_size, const char *root_hash_sig_key_desc,
uint64_t hash_offset_block, uint64_t hash_blocks, struct crypt_params_verity *vp);
const char *root_hash, uint32_t root_hash_size, const char* root_hash_sig_key_desc,
uint64_t hash_offset_block, uint64_t fec_blocks, struct crypt_params_verity *vp);
int dm_integrity_target_set(struct crypt_device *cd,
struct dm_target *tgt, uint64_t seg_offset, uint64_t seg_size,
struct device *meta_device,

View File

@@ -1,7 +1,7 @@
/*
* FIPS mode utilities
*
* Copyright (C) 2011-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2011-2021 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

View File

@@ -1,7 +1,7 @@
/*
* FIPS mode utilities
*
* Copyright (C) 2011-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2011-2021 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

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-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2020 Milan Broz
* Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2021 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

@@ -3,8 +3,8 @@
*
* Copyright (C) 2004 Jana Saout <jana@saout.de>
* Copyright (C) 2004-2007 Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2009-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2020 Milan Broz
* Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2021 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,8 +1,8 @@
/*
* kernel keyring utilities
*
* Copyright (C) 2016-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2016-2020 Ondrej Kozina
* Copyright (C) 2016-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2016-2021 Ondrej Kozina
*
* 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,8 +1,8 @@
/*
* kernel keyring syscall wrappers
*
* Copyright (C) 2016-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2016-2020 Ondrej Kozina
* Copyright (C) 2016-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2016-2021 Ondrej Kozina
*
* 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,8 +1,8 @@
/*
* loopback block device utilities
*
* Copyright (C) 2009-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2020 Milan Broz
* Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2021 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -234,8 +234,9 @@ static char *_sysfs_backing_file(const char *loop)
if (stat(loop, &st) || !S_ISBLK(st.st_mode))
return NULL;
snprintf(buf, sizeof(buf), "/sys/dev/block/%d:%d/loop/backing_file",
major(st.st_rdev), minor(st.st_rdev));
if (snprintf(buf, sizeof(buf), "/sys/dev/block/%d:%d/loop/backing_file",
major(st.st_rdev), minor(st.st_rdev)) < 0)
return NULL;
fd = open(buf, O_RDONLY);
if (fd < 0)

View File

@@ -1,8 +1,8 @@
/*
* loopback block device utilities
*
* Copyright (C) 2009-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2020 Milan Broz
* Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2021 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,8 +1,8 @@
/*
* utils_pbkdf - PBKDF settings for libcryptsetup
*
* Copyright (C) 2009-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2020 Milan Broz
* Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2021 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,8 +1,8 @@
/*
* utils_safe_memory - safe memory helpers
*
* Copyright (C) 2009-2020 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2020 Milan Broz
* Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2021 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -66,6 +66,7 @@ void *crypt_safe_alloc(size_t size)
void crypt_safe_free(void *data)
{
struct safe_allocation *alloc;
volatile size_t *s;
if (!data)
return;
@@ -75,7 +76,8 @@ void crypt_safe_free(void *data)
crypt_safe_memzero(data, alloc->size);
alloc->size = 0x55aa55aa;
s = (volatile size_t *)&alloc->size;
*s = 0x55aa55aa;
free(alloc);
}

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