Compare commits

...

297 Commits

Author SHA1 Message Date
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
Milan Broz
74e94e7bdd Prepare version 2.3.3. 2020-05-28 11:26:27 +02:00
Milan Broz
72cd628357 Update cryptsetup.pot. 2020-05-24 23:37:31 +02:00
Yuri Chornoivan
45367e4a34 po: update uk.po (from translationproject.org) 2020-05-24 23:22:15 +02:00
Yuri Kozlov
7d76831250 po: update ru.po (from translationproject.org) 2020-05-24 23:22:15 +02:00
Jakub Bogusz
d2ff3fc2ee po: update pl.po (from translationproject.org) 2020-05-24 23:22:15 +02:00
Hiroshi Takekawa
537b8454a4 po: update ja.po (from translationproject.org) 2020-05-24 23:22:15 +02:00
Frédéric Marchal
a7c71b90b1 po: update fr.po (from translationproject.org) 2020-05-24 23:22:15 +02:00
Antonio Ceballos
e0be3deb3a po: update es.po (from translationproject.org) 2020-05-24 23:22:15 +02:00
Roland Illig
5490476d84 po: update de.po (from translationproject.org) 2020-05-24 23:22:15 +02:00
Petr Pisar
90865eb887 po: update cs.po (from translationproject.org) 2020-05-24 23:22:15 +02:00
Milan Broz
157f71d78e Add IV vector tests.
This test checks IV wrapper implemented in userspace.
2020-05-24 23:19:46 +02:00
Milan Broz
176fee54e4 Require both keyslot cipher ane key size options.
If not specified together, cryptsetup silently fail.
2020-05-15 22:07:52 +02:00
Milan Broz
61f4363ed7 Implement EBOIV in userspace storage wrapper.
The EBOIV initialization vector is intended to be used
internally with BitLocker devices (for CBC mode).
It can be used in some specific cases for other devices.

This patch adds userspace implementation duplicating
the same EBOIV as the dm-crypt kernel.

Fixes: #562
2020-05-15 17:33:06 +02:00
Vojtech Trefny
86cc67e081 bitlk: Fix memory leak when freeing bitlk_fvek structure 2020-05-15 17:15:07 +02:00
Milan Broz
dcc9888350 Update pot file. 2020-05-15 10:56:36 +02:00
Мирослав Николић
6af6a424b4 po: update sr.po (from translationproject.org) 2020-05-15 10:44:11 +02:00
Milan Broz
e1ceb63023 Set devel version. 2020-05-15 10:43:52 +02:00
Milan Broz
4eb7193a27 Support large IV count option for plain device
The iv_large_sector option is supported in dm-crypt since introduction
of larger sectors encryption.
It counts Initialization Vector (IV) in larger sector size (if set) instead
of 512 bytes sectors.

This option does not have any performance or security impact, but it can be
used for accessing incompatible existing disk images from other systems.
(It is used internally in BitLocker compatibily code).

This patch allows it to be used for plain type device, so users
can manually map foreign disk images.
Only open action with plain device and sector size > 512 bytes is supported.
2020-05-15 10:37:33 +02:00
Arno Wagner
e6ff3b37a4 sync with wiki 2020-05-12 17:21:49 +02:00
Milan Broz
c3e095969f Skip 4k Bitlk images (some older systems cannot activate them). 2020-05-07 09:15:45 +02:00
Vojtěch Trefný
2e345a1059 bitlk: Fix working with 4k sector devices
We need to use the iv_large_sectors flag and correct sector size
for the crypt segments for these devices. Used sector size is
read from the device header. This commit also adds two new test
images with 4k sectors.

Fixes: #557
2020-05-06 21:20:26 +02:00
Milan Broz
e759ebe0bd Better explain --persistent option for flag removals.
Also fix a error message that was not displayed
properly for the persistent discard flag incompatibility.

Fixes: #558.
2020-05-02 17:09:59 +02:00
Milan Broz
533b874590 Update Readme.md. 2020-04-30 17:12:37 +02:00
Milan Broz
780ebb4680 Version 2.3.2. 2020-04-30 16:56:53 +02:00
Yuri Chornoivan
02a579af59 po: update uk.po (from translationproject.org) 2020-04-29 08:49:39 +02:00
Yuri Kozlov
9bcf1c4b8d po: update ru.po (from translationproject.org) 2020-04-29 08:49:39 +02:00
Jakub Bogusz
dec9b4f7c7 po: update pl.po (from translationproject.org) 2020-04-29 08:49:39 +02:00
Hiroshi Takekawa
4701842829 po: update ja.po (from translationproject.org) 2020-04-29 08:49:39 +02:00
Frédéric Marchal
488b4bdbe8 po: update fr.po (from translationproject.org) 2020-04-29 08:49:39 +02:00
Antonio Ceballos
c8d886b422 po: update es.po (from translationproject.org) 2020-04-29 08:49:39 +02:00
Roland Illig
a83bbd2e92 po: update de.po (from translationproject.org) 2020-04-29 08:49:39 +02:00
Petr Pisar
c3a47cb72f po: update cs.po (from translationproject.org) 2020-04-29 08:49:39 +02:00
Ondrej Kozina
0971e55d4d Fix gcc warning in unbound key dump. 2020-04-29 08:49:25 +02:00
Ondrej Kozina
6f45c7a8ac Drop duplicit check on --refresh option. 2020-04-29 08:49:04 +02:00
Arno Wagner
c567d852a5 Sync to wiki (added 10.9) 2020-04-28 15:28:49 +02:00
Arno Wagner
0b38128e21 sync to Wiki 2020-04-27 16:27:50 +02:00
Arno Wagner
b9daa8b2ee Fixes to 6.10, should state situation with LUKS2
accurately now.
2020-04-26 18:56:28 +02:00
Arno Wagner
878c7173c3 typo 2020-04-26 18:34:59 +02:00
Arno Wagner
f69b980dcf Sync to Wiki Version.
Rework to differentiate LUKS1 from LUKS2 and
info for LUKS2 added.
2020-04-26 18:22:25 +02:00
Milan Broz
33378792ca Prepare rc0 for version 2.3.2. 2020-04-17 10:48:04 +02:00
Milan Broz
c7a2b4d5e3 Fix a line break in veritysetup man page. 2020-04-16 15:33:25 +02:00
Milan Broz
4a077fc2c9 Rephrase warning a little bit. 2020-04-16 15:30:35 +02:00
Ondrej Kozina
f309ec21d7 Allow dump of LUKS2 unbound keyslot.
Adds option to dump content of LUKS2 unbound keyslot
in to a file:

'cryptsetup luksDump --unbound --master-key-file /file -S 12 /dev/luks2'

or to terminal:

'cryptsetup luksDump --unbound -S 12 /dev/luks2'

Parameters -S (specific keyslot) is mandatory with --unbound.

Fixes: #549
2020-04-16 15:29:24 +02:00
Milan Broz
e261cf7481 Add issue templates.
(Note: default is in project setting as a copy of Bug.md)
2020-04-15 18:06:07 +02:00
Milan Broz
fa8390b23e Remove redundant EOL in some usage messages.
With recent changes in log wrapper these messages were forgotten to fix.
2020-04-15 13:14:13 +02:00
Milan Broz
af89858d47 Use fsync explicitly for the device check in cryptsetup-reencrypt.
With direct-io removal in previous patch we should ensure the header
change hits the real device immediatelly.
2020-04-15 13:10:36 +02:00
Ondrej Kozina
e6a3569743 Avoid name clash with newer json-c library.
This is partial revert of previous commit and also
fixes wrong decision to name our internal helpers with
json_object prefix.
2020-04-14 17:24:57 +02:00
Björn Esser
604abec333 Add support for upcoming json-c 0.14.0.
* TRUE/FALSE are not defined anymore.  1 and 0 are used instead.
  * json_object_get_uint64() and json_object_new_uint64() are part
    of the upstream API now.
2020-04-13 14:25:18 +02:00
Milan Broz
790666ffb0 Add support for allow_discrads for dm-integrity.
Kernel 5.7 adds support for optional discard/TRIM operation
for dm-integrity (available only for internal hash, not for LUKS2
with integrity).

This patch adds support for the new option.
2020-04-09 00:03:42 +02:00
Milan Broz
c9f6ccff9f Ignore not relevant TOCTOU warning in previous commit. 2020-04-03 13:30:54 +02:00
Milan Broz
02b3f42500 Fix open flags in cryptsetup-reencrypt header access check.
We should not use O_DIRECT, it does not work tin in-memory fs.

Also never use O_EXCL on regular files, it is undedfined according
to open() documentation.

Fixes: #529.
2020-04-03 12:59:50 +02:00
Vojtěch Trefný
e10724accb bitlk: Correctly free memory in passphrase_to_utf16
Fixes: #547
2020-04-01 08:02:09 +02:00
Milan Broz
5b68dec43a Adjust IV size in cipher benchmark.
The IV size for benchmark can be autodetected (for known ciphers).
For other algorithms user still can specify own values.
2020-03-23 18:46:59 +01:00
Milan Broz
9d13da0050 Set devel version. 2020-03-23 18:46:28 +01:00
Ondrej Kozina
1e94425279 Remove unused parameter from crypto_backend_init. 2020-03-20 11:32:57 +01:00
Milan Broz
fc48f9bc08 Workaround for verity FEC test.
Threre asre some situatiuoins when randomized image is nor repairable
by FEC data. Let's use completely deterministic image creation (fixed salt and uuid).

FIXME: The FEC Reed-Solomon code is doing something strange here, this
kind of erasure should be always repairable.
2020-03-19 10:14:45 +01:00
Milan Broz
2eb25910a1 Fix Veracrypt compatible support for longer passphrases.
Previous fix for longer passhphrases increased maximal
passphrase length even if it was not needed, for example
if used with SHA256 hash in combination with keyfiles.

This patch tries to fix the problem, so some older volumes
can be opened again.

Also some test images are added for regression testing.

Fixes: #542.
2020-03-16 17:09:41 +01:00
Milan Broz
1dab341b33 Update Readme.md. 2020-03-12 09:59:00 +01:00
Milan Broz
1f7ed87e6c Prepare version 2.3.1. 2020-03-12 09:39:20 +01:00
Milan Broz
c59ea422cc Add 2.3.1 release notes. 2020-03-10 16:03:53 +01:00
Ondrej Kozina
0bcb71f742 Add experimental warning in bitlk man section. 2020-03-10 12:26:26 +01:00
Yuri Chornoivan
7e38a3386e po: update uk.po (from translationproject.org) 2020-03-09 08:18:30 +01:00
Jakub Bogusz
c25b5ef215 po: update pl.po (from translationproject.org) 2020-03-09 08:18:30 +01:00
Hiroshi Takekawa
72fb507de2 po: update ja.po (from translationproject.org) 2020-03-09 08:18:30 +01:00
Frédéric Marchal
45c4c95b98 po: update fr.po (from translationproject.org) 2020-03-09 08:18:30 +01:00
Antonio Ceballos
e8861d1043 po: update es.po (from translationproject.org) 2020-03-09 08:18:30 +01:00
Roland Illig
c48fcb743b po: update de.po (from translationproject.org) 2020-03-09 08:18:30 +01:00
Joe Hansen
d5d732ddf4 po: update da.po (from translationproject.org) 2020-03-09 08:18:29 +01:00
Petr Pisar
f83bd5cdf6 po: update cs.po (from translationproject.org) 2020-03-09 08:18:29 +01:00
Milan Broz
76c87c628f Update cryptsetup.pot. 2020-03-09 08:18:16 +01:00
Milan Broz
fa125a354d Set version to 2.3.1-rc0. 2020-03-08 10:56:09 +01:00
Aaron Rogers
f184b54796 Improve hexdigest printing for large key-size 2020-03-01 16:17:27 +01:00
Vojtěch Trefný
75925fb2f7 bitlk: Strip extra newline from potential recovery keys
There might be a trailing newline added by the text editor when
the recovery passphrase was passed using the '--key-file' option
so we'll remove it before trying to use the passphrase.
2020-03-01 16:11:42 +01:00
Antonio Ceballos
b780228ade po: update es.po (from translationproject.org) 2020-03-01 16:07:42 +01:00
Ondrej Kozina
91c012eff0 Do not wipe device with no integrity profile.
With '--integrity none' we performed useless full
device wipe.

Fixes: #539.
2020-02-27 16:23:06 +01:00
Milan Broz
05d45c6948 Check for dm_device_get_name.
And fail dependency scan if not available.

Currently this call uses syfs DM extensions, these are
usually not available anyway on such old systems.
2020-02-21 12:13:04 +01:00
Milan Broz
a2c13fbc48 Used CLOCK_MONOTONIC in benchmark on ancient systems. 2020-02-21 10:42:47 +01:00
Milan Broz
16c7aab99b Fix some (ancient) compiler warnings. 2020-02-21 10:30:39 +01:00
Milan Broz
0cf5e309a0 Print warning if running without O_CLOEXEC. 2020-02-21 10:23:07 +01:00
Milan Broz
b5fbd682f2 Move fcntl.h to internal defines and check for O_CLOEXEC. 2020-02-21 10:10:11 +01:00
Milan Broz
90e04b0046 Remove O_CLOEXEC from block utils.
It is not needed here, used only in utilities.
2020-02-21 10:09:09 +01:00
Milan Broz
329f6562c2 Add autoconf check for O_CLOEXEC. 2020-02-21 10:08:17 +01:00
Milan Broz
852bad1ef4 Fix acompiler warning with --disable-blkid. 2020-02-21 08:28:55 +01:00
Henrik Grimler
aa44a61ab2 lib/Makemodule.am: convert some spaces to tabs 2020-02-21 08:25:41 +01:00
Milan Broz
3e237cb490 Detect separate libiconv library.
This patch should fix compilation issues on distributions with
iconv implemented in a separate library (instead libc internally).
2020-02-21 08:20:14 +01:00
Milan Broz
7b206fb13d Workaround for dm-integrity kernel table bug.
Some kernels show invalid dm-integrity table if suberblock
contains "recalculate" bit.

We can workaround that by setting recalculate option in table
(kernel uses bits from superblock anyway), so the table displayed
is always correct.

Fixes: #538
2020-02-20 14:19:57 +01:00
Milan Broz
8f7e898341 Print error message if LUKS1 keyslot cannot be processed.
If crypto backend is missing support for hash algorithms used
in PBKDF2 during slot derivatiom the fail was not visible.

Print at least error message to user in this case.

Fixes: #536
2020-02-20 14:19:53 +01:00
Ondrej Kozina
7499d9f245 Return -EINVAL when validation fails.
LUKS2_hdr_validate() returns positive integer on error. Replace returned
value with negative errno instead so that failed upconversion stops
sooner. It failed anyway but debug messages were misleading.
2020-02-19 11:18:46 +01:00
Ondrej Kozina
ba6e6f051a Properly align LUKS2 keyslots area on conversion.
If LUKS1 payload offset (data offset) is not aligned to
4KiB we create unaligned keyslots area in LUKS2 metadata
during upconversion. Unaligned keyslots area is not valid
from LUKS2 perspective. Fix it by properly aligning future
keyslots area and also check if LUKS1 keyslots area fit
in the new one.

Fixes: #534.
2020-02-17 22:19:39 +01:00
Ondrej Kozina
d4f4dfb54f Validate LUKS2 in-before moving keyslots on conversion.
During LUKS2 upconversion we moved binary keyslots area before
validating future LUKS2 header. If later LUKS2 validation failed
for some reason keyslots were already moved to new offsets and
LUKS1 offsets were therefore invalid. Following effort to unlock
such device failed because keyslots were efectively corrupted.

See issue #534.
2020-02-17 22:18:58 +01:00
Ondrej Kozina
3e7dedaf99 Minor code cleanup. 2020-02-17 22:18:36 +01:00
Milan Broz
f18cd7ae81 tcrypt: Suport VeraCrypt 128 bytes passwords
VeraCrypt now allows passwords of maximal length 128 bytes
(compared to legacy TrueCrypt where it was limited by 64 bytes).

This patch implements support for such a passphrases for TCRYPT format.

The whole extension seems to be quite dubious, the original TCRYPT
passphrase limit was IMO because of internal block length in PBKDF2
(SHA1/SH256 block size is 64 bytes), this patch make sense for SHA512
where the block size is 128 bytes.

Another strange thing is enlarging keyfile pool according to real
entered password size.

Fixes: #532.
2020-02-17 22:08:47 +01:00
Milan Broz
0ae4fcf8eb Update Readme.md. 2020-02-02 17:37:24 +01:00
169 changed files with 22519 additions and 14691 deletions

View File

@@ -0,0 +1,15 @@
### Issue description
<!-- Please, shortly describe the issue here. -->
### Steps for reproducing the issue
<!-- How it can be reproduced? Include all important steps. -->
### Additional info
<!-- Please mention what distribution you are using. -->
### Debug log
<!-- Paste a debug log of the failing command (add --debug option) between the markers below (to keep raw debug format).-->
```
Output with --debug option:
```

View File

@@ -0,0 +1,5 @@
### Documentation issue
<!-- Please, shortly describe the issue in documentation here. -->
### Additional info
<!-- Please mention what cryptsetup version you are using. -->

View File

@@ -0,0 +1,5 @@
### New feature description
<!-- Please, shortly describe the requested feature here. -->
### Additional info
<!-- Please mention what distribution and cryptsetup version you are using. -->

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

3102
FAQ

File diff suppressed because it is too large Load Diff

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

@@ -6,7 +6,7 @@ What the ...?
on the [DMCrypt](https://gitlab.com/cryptsetup/cryptsetup/wikis/DMCrypt) kernel module.
These include **plain** **dm-crypt** volumes, **LUKS** volumes, **loop-AES**,
**TrueCrypt** (including **VeraCrypt** extension) and BitLocker formats.
**TrueCrypt** (including **VeraCrypt** extension) and **BitLocker** formats.
The project also includes a **veritysetup** utility used to conveniently setup
[DMVerity](https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity) block integrity checking kernel module
@@ -44,22 +44,13 @@ Download
--------
All release tarballs and release notes are hosted on [kernel.org](https://www.kernel.org/pub/linux/utils/cryptsetup/).
**The latest testing cryptsetup version is 2.3.0-rc0**
* [cryptsetup-2.3.0-rc0.tar.xz](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.3/cryptsetup-2.3.0-rc0.tar.xz)
* Signature [cryptsetup-2.3.0-rc0.tar.sign](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.3/cryptsetup-2.3.0-rc0.tar.sign)
**The latest stable cryptsetup version is 2.3.5**
* [cryptsetup-2.3.5.tar.xz](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.3/cryptsetup-2.3.5.tar.xz)
* Signature [cryptsetup-2.3.5.tar.sign](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.3/cryptsetup-2.3.5.tar.sign)
_(You need to decompress file first to check signature.)_
* [Cryptsetup 2.3.0-rc0 Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.3/v2.3.0-rc0-ReleaseNotes).
**The latest stable cryptsetup version is 2.2.2**
* [cryptsetup-2.2.2.tar.xz](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.2/cryptsetup-2.2.2.tar.xz)
* Signature [cryptsetup-2.2.2.tar.sign](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.2/cryptsetup-2.2.2.tar.sign)
_(You need to decompress file first to check signature.)_
* [Cryptsetup 2.2.2 Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.2/v2.2.2-ReleaseNotes).
* [Cryptsetup 2.3.5 Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.3/v2.3.5-ReleaseNotes).
Previous versions
* [Version 2.2.1](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.2/cryptsetup-2.2.1.tar.xz) -
[Signature](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.2/cryptsetup-2.2.1.tar.sign) -
[Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.2/v2.2.0-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).
@@ -76,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!
-----
@@ -85,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.0])
AC_INIT([cryptsetup],[2.3.6])
dnl library version from <major>.<minor>.<release>[-<suffix>]
LIBCRYPTSETUP_VERSION=$(echo $PACKAGE_VERSION | cut -f1 -d-)
@@ -33,6 +33,7 @@ AC_PROG_MAKE_SET
AC_ENABLE_STATIC(no)
LT_INIT
PKG_PROG_PKG_CONFIG
AM_ICONV
dnl ==========================================================================
dnl define PKG_CHECK_VAR for old pkg-config <= 0.28
@@ -59,6 +60,12 @@ 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])],
[[
#ifdef HAVE_FCNTL_H
# include <fcntl.h>
#endif
]])
AC_CHECK_HEADERS(uuid/uuid.h,,[AC_MSG_ERROR([You need the uuid library.])])
AC_CHECK_HEADER(libdevmapper.h,,[AC_MSG_ERROR([You need the device-mapper library.])])
@@ -169,7 +176,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
@@ -348,6 +363,7 @@ AC_CHECK_DECLS([dm_task_retry_remove], [], [], [#include <libdevmapper.h>])
AC_CHECK_DECLS([dm_task_deferred_remove], [], [], [#include <libdevmapper.h>])
AC_CHECK_DECLS([dm_device_has_mounted_fs], [], [], [#include <libdevmapper.h>])
AC_CHECK_DECLS([dm_device_has_holders], [], [], [#include <libdevmapper.h>])
AC_CHECK_DECLS([dm_device_get_name], [], [], [#include <libdevmapper.h>])
AC_CHECK_DECLS([DM_DEVICE_GET_TARGET_VERSION], [], [], [#include <libdevmapper.h>])
AC_CHECK_DECLS([DM_UDEV_DISABLE_DISK_RULES_FLAG], [have_cookie=yes], [have_cookie=no], [#include <libdevmapper.h>])
if test "x$enable_udev" = xyes; then
@@ -588,7 +604,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

45
docs/v2.3.1-ReleaseNotes Normal file
View File

@@ -0,0 +1,45 @@
Cryptsetup 2.3.1 Release Notes
==============================
Stable bug-fix release.
All users of cryptsetup 2.x should upgrade to this version.
Changes since version 2.3.0
~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Support VeraCrypt 128 bytes passwords.
VeraCrypt now allows passwords of maximal length 128 bytes
(compared to legacy TrueCrypt where it was limited by 64 bytes).
* Strip extra newline from BitLocker recovery keys
There might be a trailing newline added by the text editor when
the recovery passphrase was passed using the --key-file option.
* Detect separate libiconv library.
It should fix compilation issues on distributions with iconv
implemented in a separate library.
* Various fixes and workarounds to build on old Linux distributions.
* Split lines with hexadecimal digest printing for large key-sizes.
* Do not wipe the device with no integrity profile.
With --integrity none we performed useless full device wipe.
* Workaround for dm-integrity kernel table bug.
Some kernels show an invalid dm-integrity mapping table
if superblock contains the "recalculate" bit. This causes
integritysetup to not recognize the dm-integrity device.
Integritysetup now specifies kernel options such a way that
even on unpatched kernels mapping table is correct.
* Print error message if LUKS1 keyslot cannot be processed.
If the crypto backend is missing support for hash algorithms
used in PBKDF2, the error message was not visible.
* Properly align LUKS2 keyslots area on conversion.
If the LUKS1 payload offset (data offset) is not aligned
to 4 KiB boundary, new LUKS2 keyslots area in now aligned properly.
* Validate LUKS2 earlier on conversion to not corrupt the device
if binary keyslots areas metadata are not correct.

42
docs/v2.3.2-ReleaseNotes Normal file
View File

@@ -0,0 +1,42 @@
Cryptsetup 2.3.2 Release Notes
==============================
Stable bug-fix release.
All users of cryptsetup 2.x should upgrade to this version.
Changes since version 2.3.1
~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Support compilation with json-c library version 0.14.
* Update FAQ document for some LUKS2 specific information.
* Add option to dump content of LUKS2 unbound keyslot:
cryptsetup luksDump --unbound -S <slot> <device>
or optionally with --master-key-file option.
The slot number --key-slot (-S) option is mandatory here.
An unbound keyslot store a key is that is not assigned to data
area on disk (LUKS2 allows to store arbitrary keys).
* Rephrase some error messages and remove redundant end-of-lines.
* Add support for discards (TRIM) for standalone dm-integrity devices.
Linux kernel 5.7 adds support for optional discard/TRIM operation
over dm-integrity devices.
It is now supported through --allow-discards integritysetup option.
Note you need to add this flag in all activation calls.
Note that this option cannot be used for LUKS2 authenticated encryption
(that uses dm-integrity for storing additional per-sector metadata).
* Fix cryptsetup-reencrypt to work on devices that do not allow
direct-io device access.
* Fix a crash in the BitLocker-compatible code error path.
* Fix Veracrypt compatible support for longer (>64 bytes) passphrases.
It allows some older images to be correctly opened again.
The issue was introduced in version 2.3.1.

42
docs/v2.3.3-ReleaseNotes Normal file
View File

@@ -0,0 +1,42 @@
Cryptsetup 2.3.3 Release Notes
==============================
Stable bug-fix release.
All users of cryptsetup 2.x should upgrade to this version.
Changes since version 2.3.2
~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Fix BitLocker compatible device access that uses native 4kB sectors.
Devices formatted with storage that natively support 4096-bytes
sectors can also use this sector size for encryption units.
* Support large IV count (--iv-large-sectors) cryptsetup option
for plain device mapping.
The large IV count is supported in dm-crypt together with larger
sector encryption. It counts the Initialization Vector (IV) in
a larger sector size instead of 512-bytes sectors.
This option does not have any performance or security impact,
but it can be used for accessing incompatible existing disk images
from other systems.
Only open action with plain device type and sector size > 512 bytes
are supported.
* Fix a memory leak in BitLocker compatible handling.
* Allow EBOIV (Initialization Vector algorithm) use.
The EBOIV initialization vector is intended to be used internally
with BitLocker devices (for CBC mode). It can now be used also
outside of the BitLocker compatible code.
* Require both keyslot cipher and key size options.
If these LUKS2 keyslot parameters were not specified together,
cryptsetup silently failed.
* Update to man pages and FAQ.

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".

View File

@@ -40,6 +40,7 @@ libcryptsetup_la_LIBADD = \
@LIBARGON2_LIBS@ \
@JSON_C_LIBS@ \
@BLKID_LIBS@ \
$(LTLIBICONV) \
libcrypto_backend.la \
libutils_io.la
@@ -76,7 +77,7 @@ libcryptsetup_la_SOURCES = \
lib/base64.h \
lib/base64.c \
lib/integrity/integrity.h \
lib/integrity/integrity.c \
lib/integrity/integrity.c \
lib/loopaes/loopaes.h \
lib/loopaes/loopaes.c \
lib/tcrypt/tcrypt.h \
@@ -92,7 +93,7 @@ libcryptsetup_la_SOURCES = \
lib/verity/verity.h \
lib/verity/rs_encode_char.c \
lib/verity/rs_decode_char.c \
lib/verity/rs.h \
lib/verity/rs.h \
lib/luks2/luks2_disk_metadata.c \
lib/luks2/luks2_json_format.c \
lib/luks2/luks2_json_metadata.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
@@ -22,7 +22,6 @@
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <uuid/uuid.h>
#include <time.h>
#include <iconv.h>
@@ -55,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
@@ -112,6 +114,7 @@ struct segment {
struct bitlk_signature {
uint8_t boot_code[3];
uint8_t signature[8];
uint16_t sector_size;
} __attribute__ ((packed));
struct bitlk_superblock {
@@ -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) {
@@ -291,7 +306,7 @@ static int passphrase_to_utf16(struct crypt_device *cd, char *input, size_t inle
*out = outbuf;
} else {
*out = NULL;
free(outbuf);
crypt_safe_free(outbuf);
log_dbg(cd, "Failed to convert passphrase: %s", strerror(errno));
r = -errno;
}
@@ -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);
@@ -415,6 +435,7 @@ void BITLK_bitlk_fvek_free(struct bitlk_fvek *fvek)
return;
crypt_free_volume_key(fvek->vk);
free(fvek);
}
void BITLK_bitlk_vmk_free(struct bitlk_vmk *vmk)
@@ -435,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);
@@ -480,6 +504,18 @@ int BITLK_read_sb(struct crypt_device *cd, struct bitlk_metadata *params)
goto out;
}
if (memcmp(sig.signature, BITLK_SIGNATURE, sizeof(sig.signature)) == 0) {
params->togo = false;
fve_offset = BITLK_HEADER_METADATA_OFFSET;
} else if (memcmp(sig.signature, BITLK_SIGNATURE_TOGO, sizeof(sig.signature)) == 0) {
params->togo = true;
fve_offset = BITLK_HEADER_METADATA_OFFSET_TOGO;
} else {
log_err(cd, _("Invalid or unknown signature for BITLK device."));
r = -EINVAL;
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;
@@ -492,14 +528,14 @@ int BITLK_read_sb(struct crypt_device *cd, struct bitlk_metadata *params)
goto out;
}
if (memcmp(sig.signature, BITLK_SIGNATURE, sizeof(sig.signature)) == 0) {
params->togo = false;
fve_offset = BITLK_HEADER_METADATA_OFFSET;
} else if (memcmp(sig.signature, BITLK_SIGNATURE_TOGO, sizeof(sig.signature)) == 0) {
params->togo = true;
fve_offset = BITLK_HEADER_METADATA_OFFSET_TOGO;
} else {
log_err(cd, _("Invalid or unknown signature for BITLK device."));
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;
goto out;
}
@@ -551,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;
@@ -573,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;
@@ -615,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;
@@ -641,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);
@@ -669,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));
@@ -722,6 +766,7 @@ int BITLK_dump(struct crypt_device *cd, struct device *device, struct bitlk_meta
log_std(cd, "Info for BITLK%s device %s.\n", params->togo ? " To Go" : "", device_path(device));
log_std(cd, "Version: \t%u\n", params->metadata_version);
log_std(cd, "GUID: \t%s\n", params->guid);
log_std(cd, "Sector size: \t%u [bytes]\n", params->sector_size);
log_std(cd, "Created: \t%s", ctime((time_t *)&(params->creation_time)));
log_std(cd, "Description: \t%s\n", params->description);
log_std(cd, "Cipher name: \t%s\n", params->cipher);
@@ -789,8 +834,14 @@ static int get_recovery_key(struct crypt_device *cd,
- 8 groups of 6 divided by '-'
- each part is a number dividable by 11
*/
if (passwordLen != BITLK_RECOVERY_KEY_LEN)
return 0;
if (passwordLen != BITLK_RECOVERY_KEY_LEN) {
if (passwordLen == BITLK_RECOVERY_KEY_LEN + 1 && password[passwordLen - 1] == '\n') {
/* looks like a recovery key with an extra newline, possibly from a key file */
passwordLen--;
log_dbg(cd, "Possible extra EOL stripped from the recovery key.");
} else
return 0;
}
for (i = BITLK_RECOVERY_PART_LEN; i < passwordLen; i += BITLK_RECOVERY_PART_LEN + 1) {
if (password[i] != '-')
@@ -818,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,
@@ -893,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)
@@ -908,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,
@@ -978,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;
@@ -996,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)
@@ -1150,6 +1330,9 @@ int BITLK_activate(struct crypt_device *cd,
}
}
if (params->sector_size != SECTOR_SIZE)
dmd.flags |= CRYPT_ACTIVATE_IV_LARGE_SECTORS;
r = dm_targets_allocate(&dmd.segment, num_segments);
if (r)
goto out;
@@ -1170,7 +1353,7 @@ int BITLK_activate(struct crypt_device *cd,
segments[i].iv_offset,
segments[i].iv_offset,
NULL, 0,
SECTOR_SIZE);
params->sector_size);
if (r)
goto out;

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
@@ -95,6 +95,7 @@ struct bitlk_fvek {
};
struct bitlk_metadata {
uint16_t sector_size;
bool togo;
bool state;
BITLKEncryptionType type;

View File

@@ -2,8 +2,8 @@
* cryptsetup plain device helper functions
*
* Copyright (C) 2004 Jana Saout <jana@saout.de>
* Copyright (C) 2010-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
@@ -23,6 +23,10 @@
#include <time.h>
#include "crypto_backend_internal.h"
#ifndef CLOCK_MONOTONIC_RAW
#define CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC
#endif
/*
* This is not simulating storage, so using disk block causes extreme overhead.
* Let's use some fixed block size where results are more reliable...

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
@@ -51,6 +51,7 @@ static const struct cipher_alg cipher_algs[] = {
{ "paes", NULL, 16, true }, /* protected AES, s390 wrapped key scheme */
{ "xchacha12,aes", "adiantum", 32, false },
{ "xchacha20,aes", "adiantum", 32, false },
{ "sm4", NULL, 16, false },
{ NULL, NULL, 0, false }
};
@@ -72,7 +73,13 @@ int crypt_cipher_ivsize(const char *name, const char *mode)
{
const struct cipher_alg *ca = _get_alg(name, mode);
return ca ? ca->blocksize : -EINVAL;
if (!ca)
return -EINVAL;
if (mode && !strcasecmp(mode, "ecb"))
return 0;
return ca->blocksize;
}
int crypt_cipher_wrapped_key(const char *name, const char *mode)

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
@@ -26,13 +26,12 @@
#include <stddef.h>
#include <string.h>
struct crypt_device;
struct crypt_hash;
struct crypt_hmac;
struct crypt_cipher;
struct crypt_storage;
int crypt_backend_init(struct crypt_device *ctx);
int crypt_backend_init(void);
void crypt_backend_destroy(void);
#define CRYPT_BACKEND_KERNEL (1 << 0) /* Crypto uses kernel part, for benchmark */
@@ -110,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)
{
@@ -89,8 +94,10 @@ static void crypt_hash_test_whirlpool_bug(void)
crypto_backend_whirlpool_bug = 1;
}
int crypt_backend_init(struct crypt_device *ctx)
int crypt_backend_init(void)
{
int r;
if (crypto_backend_initialised)
return 0;
@@ -120,11 +127,12 @@ int crypt_backend_init(struct crypt_device *ctx)
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 }
};
@@ -110,7 +118,7 @@ static int crypt_kernel_socket_init(struct sockaddr_alg *sa, int *tfmfd, int *op
return 0;
}
int crypt_backend_init(struct crypt_device *ctx)
int crypt_backend_init(void)
{
struct utsname uts;
struct sockaddr_alg sa = {
@@ -118,7 +126,7 @@ int crypt_backend_init(struct crypt_device *ctx)
.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(struct crypt_device *ctx)
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
@@ -213,7 +213,7 @@ static struct hash_alg *_get_alg(const char *name)
return NULL;
}
int crypt_backend_init(struct crypt_device *ctx)
int crypt_backend_init(void)
{
return 0;
}

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
@@ -75,8 +75,10 @@ static struct hash_alg *_get_alg(const char *name)
return NULL;
}
int crypt_backend_init(struct crypt_device *ctx)
int crypt_backend_init(void)
{
int r;
if (crypto_backend_initialised)
return 0;
@@ -84,10 +86,13 @@ int crypt_backend_init(struct crypt_device *ctx)
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
*/
@@ -121,7 +126,7 @@ static const char *openssl_backend_version(void)
}
#endif
int crypt_backend_init(struct crypt_device *ctx)
int crypt_backend_init(void)
{
if (crypto_backend_initialised)
return 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
@@ -31,16 +31,16 @@
* IV documentation: https://gitlab.com/cryptsetup/cryptsetup/wikis/DMCrypt
*/
struct crypt_sector_iv {
enum { IV_NONE, IV_NULL, IV_PLAIN, IV_PLAIN64, IV_ESSIV, IV_BENBI, IV_PLAIN64BE } type;
enum { IV_NONE, IV_NULL, IV_PLAIN, IV_PLAIN64, IV_ESSIV, IV_BENBI, IV_PLAIN64BE, IV_EBOIV } type;
int iv_size;
char *iv;
struct crypt_cipher *essiv_cipher;
int benbi_shift;
struct crypt_cipher *cipher;
int shift;
};
/* 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,12 +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)
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") ||
@@ -86,7 +89,6 @@ static int crypt_sector_iv_init(struct crypt_sector_iv *ctx,
char *hash_name = strchr(iv_name, ':');
int hash_size;
char tmp[256];
int r;
if (!hash_name)
return -EINVAL;
@@ -114,7 +116,7 @@ static int crypt_sector_iv_init(struct crypt_sector_iv *ctx,
return r;
}
r = crypt_cipher_init(&ctx->essiv_cipher, cipher_name, "ecb",
r = crypt_cipher_init(&ctx->cipher, cipher_name, "ecb",
tmp, hash_size);
crypt_backend_memzero(tmp, sizeof(tmp));
if (r)
@@ -127,7 +129,15 @@ static int crypt_sector_iv_init(struct crypt_sector_iv *ctx,
return -EINVAL;
ctx->type = IV_BENBI;
ctx->benbi_shift = SECTOR_SHIFT - log;
ctx->shift = SECTOR_SHIFT - log;
} else if (!strncasecmp(iv_name, "eboiv", 5)) {
r = crypt_cipher_init(&ctx->cipher, cipher_name, "ecb",
key, key_length);
if (r)
return r;
ctx->type = IV_EBOIV;
ctx->shift = int_log2(sector_size);
} else
return -ENOENT;
@@ -163,14 +173,20 @@ static int crypt_sector_iv_generate(struct crypt_sector_iv *ctx, uint64_t sector
case IV_ESSIV:
memset(ctx->iv, 0, ctx->iv_size);
*(uint64_t *)ctx->iv = cpu_to_le64(sector);
return crypt_cipher_encrypt(ctx->essiv_cipher,
return crypt_cipher_encrypt(ctx->cipher,
ctx->iv, ctx->iv, ctx->iv_size, NULL, 0);
break;
case IV_BENBI:
memset(ctx->iv, 0, ctx->iv_size);
val = cpu_to_be64((sector << ctx->benbi_shift) + 1);
val = cpu_to_be64((sector << ctx->shift) + 1);
memcpy(ctx->iv + ctx->iv_size - sizeof(val), &val, sizeof(val));
break;
case IV_EBOIV:
memset(ctx->iv, 0, ctx->iv_size);
*(uint64_t *)ctx->iv = cpu_to_le64(sector << ctx->shift);
return crypt_cipher_encrypt(ctx->cipher,
ctx->iv, ctx->iv, ctx->iv_size, NULL, 0);
break;
default:
return -EINVAL;
}
@@ -180,8 +196,8 @@ static int crypt_sector_iv_generate(struct crypt_sector_iv *ctx, uint64_t sector
static void crypt_sector_iv_destroy(struct crypt_sector_iv *ctx)
{
if (ctx->type == IV_ESSIV)
crypt_cipher_destroy(ctx->essiv_cipher);
if (ctx->type == IV_ESSIV || ctx->type == IV_EBOIV)
crypt_cipher_destroy(ctx->cipher);
if (ctx->iv) {
memset(ctx->iv, 0, ctx->iv_size);
@@ -197,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];
@@ -229,14 +246,14 @@ int crypt_storage_init(struct crypt_storage **ctx,
return r;
}
r = crypt_sector_iv_init(&s->cipher_iv, cipher, mode_name, cipher_iv, key, key_length);
r = crypt_sector_iv_init(&s->cipher_iv, cipher, mode_name, cipher_iv, key, key_length, sector_size);
if (r) {
crypt_storage_destroy(s);
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;
@@ -249,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)
@@ -278,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
@@ -27,6 +27,10 @@
#include <sys/resource.h>
#include "crypto_backend.h"
#ifndef CLOCK_MONOTONIC_RAW
#define CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC
#endif
#define BENCH_MIN_MS 250
#define BENCH_MIN_MS_FAST 10
#define BENCH_PERCENT_ATLEAST 95
@@ -357,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
@@ -22,7 +22,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <uuid/uuid.h>
#include "integrity.h"
@@ -41,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;
@@ -93,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;
}
@@ -213,7 +213,7 @@ int INTEGRITY_create_dmd_device(struct crypt_device *cd,
struct volume_key *journal_crypt_key,
struct volume_key *journal_mac_key,
struct crypt_dm_active_device *dmd,
uint32_t flags)
uint32_t flags, uint32_t sb_flags)
{
int r;
@@ -224,6 +224,10 @@ int INTEGRITY_create_dmd_device(struct crypt_device *cd,
.flags = flags,
};
/* Workaround for kernel dm-integrity table bug */
if (sb_flags & SB_FLAG_RECALCULATING)
dmd->flags |= CRYPT_ACTIVATE_RECALCULATE;
r = INTEGRITY_data_sectors(cd, crypt_metadata_device(cd),
crypt_get_data_offset(cd) * SECTOR_SIZE, &dmd->size);
if (r < 0)
@@ -275,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;
}
@@ -287,7 +300,8 @@ int INTEGRITY_activate(struct crypt_device *cd,
uint32_t flags, uint32_t sb_flags)
{
struct crypt_dm_active_device dmd = {};
int r = INTEGRITY_create_dmd_device(cd, params, vk, journal_crypt_key, journal_mac_key, &dmd, flags);
int r = INTEGRITY_create_dmd_device(cd, params, vk, journal_crypt_key,
journal_mac_key, &dmd, flags, sb_flags);
if (r < 0)
return r;
@@ -316,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];
@@ -91,7 +93,7 @@ int INTEGRITY_create_dmd_device(struct crypt_device *cd,
struct volume_key *journal_crypt_key,
struct volume_key *journal_mac_key,
struct crypt_dm_active_device *dmd,
uint32_t flags);
uint32_t flags, uint32_t sb_flags);
int INTEGRITY_activate_dmd_device(struct crypt_device *cd,
const char *name,

View File

@@ -3,8 +3,8 @@
*
* Copyright (C) 2004 Jana Saout <jana@saout.de>
* Copyright (C) 2004-2007 Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2009-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
@@ -30,6 +30,7 @@
#include <stdlib.h>
#include <unistd.h>
#include <inttypes.h>
#include <fcntl.h>
#include "nls.h"
#include "bitops.h"
@@ -77,6 +78,10 @@
*_py = NULL; \
} while (0)
#ifndef O_CLOEXEC
#define O_CLOEXEC 0
#endif
struct crypt_device;
struct luks2_reenc_context;
@@ -261,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.
@@ -1101,6 +1105,14 @@ int crypt_keyslot_destroy(struct crypt_device *cd, int keyslot);
#define CRYPT_ACTIVATE_NO_JOURNAL_BITMAP (1 << 20)
/** device is suspended (key should be wiped from memory), output only */
#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
@@ -1477,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);
@@ -1491,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);
@@ -2287,7 +2299,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.
@@ -2328,17 +2340,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);
@@ -2348,17 +2358,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
@@ -27,14 +27,13 @@
#include <dirent.h>
#include <errno.h>
#include <libdevmapper.h>
#include <fcntl.h>
#include <linux/fs.h>
#include <uuid/uuid.h>
#include <sys/stat.h>
#ifdef HAVE_SYS_SYSMACROS_H
# include <sys/sysmacros.h> /* for major, minor */
#endif
#include <assert.h>
#include "internal.h"
#define DM_UUID_LEN 129
@@ -175,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;
}
@@ -206,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;
}
@@ -231,6 +236,12 @@ static void _dm_set_integrity_compat(struct crypt_device *cd,
if (_dm_satisfies_version(1, 4, 0, integrity_maj, integrity_min, integrity_patch))
_dm_flags |= DM_INTEGRITY_FIX_PADDING_SUPPORTED;
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;
}
@@ -579,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);
@@ -592,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)
@@ -613,44 +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", 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" : "",
sector_feature, integrity_dm);
(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" : "",
(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);
@@ -677,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;
@@ -688,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);
@@ -757,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;
@@ -770,143 +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 (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';
@@ -917,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)
@@ -1161,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) {
@@ -1181,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;
@@ -1294,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)
{
@@ -1343,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;
@@ -1581,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;
}
@@ -1603,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|
@@ -1618,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."));
@@ -1633,6 +1731,10 @@ int dm_create_device(struct crypt_device *cd, const char *name,
!(dmt_flags & DM_INTEGRITY_RECALC_SUPPORTED))
log_err(cd, _("Requested automatic recalculation of integrity tags is not supported."));
if (r == -EINVAL && dmd->segment.type == DM_INTEGRITY && (dmd->flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) &&
!(dmt_flags & DM_INTEGRITY_DISCARDS_SUPPORTED))
log_err(cd, _("Discard/TRIM is not supported."));
if (r == -EINVAL && dmd->segment.type == DM_INTEGRITY && (dmd->flags & CRYPT_ACTIVATE_NO_JOURNAL_BITMAP) &&
!(dmt_flags & DM_INTEGRITY_BITMAP_SUPPORTED))
log_err(cd, _("Requested dm-integrity bitmap mode is not supported."));
@@ -1660,11 +1762,17 @@ 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))
log_err(cd, _("Discard/TRIM is not supported."));
if ((dmd->flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) &&
!dm_flags(cd, DM_INTEGRITY, &dmt_flags) && !(dmt_flags & DM_INTEGRITY_DISCARDS_SUPPORTED))
log_err(cd, _("Discard/TRIM is not supported."));
}
if (!r && resume)
@@ -1702,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);
@@ -1900,6 +2009,12 @@ 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) {
tgt->u.crypt.tag_size = val;
rintegrity = strchr(arg + strlen("integrity:"), ':');
@@ -2148,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"))
@@ -2193,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;
@@ -2398,6 +2520,12 @@ 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 */
goto err;
}
@@ -2643,6 +2771,7 @@ int dm_query_device(struct crypt_device *cd, const char *name,
static int _process_deps(struct crypt_device *cd, const char *prefix, struct dm_deps *deps, char **names, size_t names_offset, size_t names_length)
{
#if HAVE_DECL_DM_DEVICE_GET_NAME
struct crypt_dm_active_device dmd;
char dmname[PATH_MAX];
unsigned i;
@@ -2681,6 +2810,9 @@ static int _process_deps(struct crypt_device *cd, const char *prefix, struct dm_
}
return count;
#else
return -EINVAL;
#endif
}
int dm_device_deps(struct crypt_device *cd, const char *name, const char *prefix, char **names, size_t names_length)
@@ -2831,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>
@@ -2843,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);
@@ -2918,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;
@@ -2937,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;
@@ -2978,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
@@ -81,7 +81,7 @@ static int hash_keys(struct crypt_device *cd,
const char *hash_name;
char tweak, *key_ptr;
unsigned int i;
int r;
int r = 0;
hash_name = hash_override ?: get_hash(key_len_output);
tweak = get_tweak(keys_count);

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
@@ -22,7 +22,6 @@
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/stat.h>
#include "luks.h"
@@ -154,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).",
@@ -219,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
@@ -23,7 +23,6 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
@@ -376,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;
}
@@ -387,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."));
@@ -956,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;
@@ -975,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;
@@ -987,8 +998,10 @@ static int LUKS_open_key(unsigned int keyIndex,
hdr->keyblock[keyIndex].passwordSalt, LUKS_SALTSIZE,
derived_key->key, hdr->keyBytes,
hdr->keyblock[keyIndex].passwordIterations, 0, 0);
if (r < 0)
if (r < 0) {
log_err(ctx, _("Cannot open keyslot (using hash %s)."), hdr->hashSpec);
goto out;
}
log_dbg(ctx, "Reading key slot %d area.", keyIndex);
r = LUKS_decrypt_from_storage(AfKey,
@@ -1000,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;
@@ -1025,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"
@@ -330,6 +332,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,
@@ -523,7 +531,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);

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);

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,7 +23,6 @@
#define _CRYPTSETUP_LUKS2_INTERNAL_H
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <json-c/json.h>
@@ -59,9 +58,9 @@ json_object *LUKS2_get_segments_jobj(struct luks2_hdr *hdr);
void hexprint_base64(struct crypt_device *cd, json_object *jobj,
const char *sep, const char *line_sep);
uint64_t json_object_get_uint64(json_object *jobj);
uint32_t json_object_get_uint32(json_object *jobj);
json_object *json_object_new_uint64(uint64_t value);
uint64_t crypt_jobj_get_uint64(json_object *jobj);
uint32_t crypt_jobj_get_uint32(json_object *jobj);
json_object *crypt_jobj_new_uint64(uint64_t value);
int json_object_object_add_by_uint(json_object *jobj, unsigned key, json_object *jobj_val);
void json_object_object_del_by_uint(json_object *jobj, unsigned key);

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
@@ -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();
@@ -325,8 +328,8 @@ int LUKS2_generate_hdr(
json_object_object_add_by_uint(jobj_segments, 0, jobj_segment);
json_object_object_add(jobj_config, "json_size", json_object_new_uint64(metadata_size - LUKS2_HDR_BIN_LEN));
json_object_object_add(jobj_config, "keyslots_size", json_object_new_uint64(keyslots_size));
json_object_object_add(jobj_config, "json_size", crypt_jobj_new_uint64(metadata_size - LUKS2_HDR_BIN_LEN));
json_object_object_add(jobj_config, "keyslots_size", crypt_jobj_new_uint64(keyslots_size));
JSON_DBG(cd, hdr->jobj, "Header JSON:");
return 0;
@@ -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;
}
@@ -400,6 +403,6 @@ int LUKS2_set_keyslots_size(struct crypt_device *cd,
if (!json_object_object_get_ex(hdr->jobj, "config", &jobj_config))
return 1;
json_object_object_add(jobj_config, "keyslots_size", json_object_new_uint64(keyslots_size));
json_object_object_add(jobj_config, "keyslots_size", crypt_jobj_new_uint64(keyslots_size));
return 0;
}

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
@@ -45,11 +45,11 @@ void hexprint_base64(struct crypt_device *cd, json_object *jobj,
&buf, &buf_len))
return;
for (i = 0; i < buf_len / 2; i++)
log_std(cd, "%02hhx%s", buf[i], sep);
log_std(cd, "\n\t%s", line_sep);
for (i = buf_len / 2; i < buf_len; i++)
for (i = 0; i < buf_len; i++) {
if (i && !(i % 16))
log_std(cd, "\n\t%s", line_sep);
log_std(cd, "%02hhx%s", buf[i], sep);
}
log_std(cd, "\n");
free(buf);
}
@@ -219,7 +219,7 @@ int LUKS2_get_default_segment(struct luks2_hdr *hdr)
* json_type_int needs to be validated first.
* See validate_json_uint32()
*/
uint32_t json_object_get_uint32(json_object *jobj)
uint32_t crypt_jobj_get_uint32(json_object *jobj)
{
return json_object_get_int64(jobj);
}
@@ -234,21 +234,21 @@ static json_bool json_str_to_uint64(json_object *jobj, uint64_t *value)
tmp = strtoull(json_object_get_string(jobj), &endptr, 10);
if (*endptr || errno) {
*value = 0;
return FALSE;
return 0;
}
*value = tmp;
return TRUE;
return 1;
}
uint64_t json_object_get_uint64(json_object *jobj)
uint64_t crypt_jobj_get_uint64(json_object *jobj)
{
uint64_t r;
json_str_to_uint64(jobj, &r);
return r;
}
json_object *json_object_new_uint64(uint64_t value)
json_object *crypt_jobj_new_uint64(uint64_t value)
{
/* 18446744073709551615 */
char num[21];
@@ -273,9 +273,9 @@ static json_bool numbered(struct crypt_device *cd, const char *name, const char
for (i = 0; key[i]; i++)
if (!isdigit(key[i])) {
log_dbg(cd, "%s \"%s\" is not in numbered form.", name, key);
return FALSE;
return 0;
}
return TRUE;
return 1;
}
json_object *json_contains(struct crypt_device *cd, json_object *jobj, const char *name,
@@ -300,7 +300,7 @@ json_bool validate_json_uint32(json_object *jobj)
errno = 0;
tmp = json_object_get_int64(jobj);
return (errno || tmp < 0 || tmp > UINT32_MAX) ? FALSE : TRUE;
return (errno || tmp < 0 || tmp > UINT32_MAX) ? 0 : 1;
}
static json_bool validate_keyslots_array(struct crypt_device *cd,
@@ -313,17 +313,17 @@ static json_bool validate_keyslots_array(struct crypt_device *cd,
jobj = json_object_array_get_idx(jarr, i);
if (!json_object_is_type(jobj, json_type_string)) {
log_dbg(cd, "Illegal value type in keyslots array at index %d.", i);
return FALSE;
return 0;
}
if (!json_contains(cd, jobj_keys, "", "Keyslots section",
json_object_get_string(jobj), json_type_object))
return FALSE;
return 0;
i++;
}
return TRUE;
return 1;
}
static json_bool validate_segments_array(struct crypt_device *cd,
@@ -336,17 +336,17 @@ static json_bool validate_segments_array(struct crypt_device *cd,
jobj = json_object_array_get_idx(jarr, i);
if (!json_object_is_type(jobj, json_type_string)) {
log_dbg(cd, "Illegal value type in segments array at index %d.", i);
return FALSE;
return 0;
}
if (!json_contains(cd, jobj_segments, "", "Segments section",
json_object_get_string(jobj), json_type_object))
return FALSE;
return 0;
i++;
}
return TRUE;
return 1;
}
static json_bool segment_has_digest(const char *segment_name, json_object *jobj_digests)
@@ -357,10 +357,10 @@ static json_bool segment_has_digest(const char *segment_name, json_object *jobj_
UNUSED(key);
json_object_object_get_ex(val, "segments", &jobj_segments);
if (LUKS2_array_jobj(jobj_segments, segment_name))
return TRUE;
return 1;
}
return FALSE;
return 0;
}
static json_bool validate_intervals(struct crypt_device *cd,
@@ -372,18 +372,18 @@ static json_bool validate_intervals(struct crypt_device *cd,
while (i < length) {
if (ix[i].offset < 2 * metadata_size) {
log_dbg(cd, "Illegal area offset: %" PRIu64 ".", ix[i].offset);
return FALSE;
return 0;
}
if (!ix[i].length) {
log_dbg(cd, "Area length must be greater than zero.");
return FALSE;
return 0;
}
if ((ix[i].offset + ix[i].length) > keyslots_area_end) {
log_dbg(cd, "Area [%" PRIu64 ", %" PRIu64 "] overflows binary keyslots area (ends at offset: %" PRIu64 ").",
ix[i].offset, ix[i].offset + ix[i].length, keyslots_area_end);
return FALSE;
return 0;
}
for (j = 0; j < length; j++) {
@@ -393,14 +393,14 @@ static json_bool validate_intervals(struct crypt_device *cd,
log_dbg(cd, "Overlapping areas [%" PRIu64 ",%" PRIu64 "] and [%" PRIu64 ",%" PRIu64 "].",
ix[i].offset, ix[i].offset + ix[i].length,
ix[j].offset, ix[j].offset + ix[j].length);
return FALSE;
return 0;
}
}
i++;
}
return TRUE;
return 1;
}
static int LUKS2_keyslot_validate(struct crypt_device *cd, json_object *hdr_jobj, json_object *hdr_keyslot, const char *key)
@@ -455,7 +455,7 @@ static int hdr_validate_json_size(struct crypt_device *cd, json_object *hdr_jobj
json = json_object_to_json_string_ext(hdr_jobj,
JSON_C_TO_STRING_PLAIN | JSON_C_TO_STRING_NOSLASHESCAPE);
json_area_size = json_object_get_uint64(jobj1);
json_area_size = crypt_jobj_get_uint64(jobj1);
json_size = (uint64_t)strlen(json);
if (hdr_json_size != json_area_size) {
@@ -543,7 +543,7 @@ static int hdr_validate_crypt_segment(struct crypt_device *cd,
return 1;
}
sector_size = json_object_get_uint32(jobj_sector_size);
sector_size = crypt_jobj_get_uint32(jobj_sector_size);
if (!sector_size || MISALIGNED_512(sector_size)) {
log_dbg(cd, "Illegal sector size: %" PRIu32, sector_size);
return 1;
@@ -594,9 +594,9 @@ static bool validate_segment_intervals(struct crypt_device *cd,
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 +676,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;
@@ -970,13 +978,16 @@ int LUKS2_hdr_read(struct crypt_device *cd, struct luks2_hdr *hdr, int repair)
return r;
}
int LUKS2_hdr_write_force(struct crypt_device *cd, struct luks2_hdr *hdr)
static int hdr_cleanup_and_validate(struct crypt_device *cd, struct luks2_hdr *hdr)
{
/* NOTE: is called before LUKS2 validation routines */
/* erase unused digests (no assigned keyslot or segment) */
LUKS2_digests_erase_unused(cd, hdr);
if (LUKS2_hdr_validate(cd, hdr->jobj, hdr->hdr_size - LUKS2_HDR_BIN_LEN))
return LUKS2_hdr_validate(cd, hdr->jobj, hdr->hdr_size - LUKS2_HDR_BIN_LEN);
}
int LUKS2_hdr_write_force(struct crypt_device *cd, struct luks2_hdr *hdr)
{
if (hdr_cleanup_and_validate(cd, hdr))
return -EINVAL;
return LUKS2_disk_hdr_write(cd, hdr, crypt_metadata_device(cd), false);
@@ -984,11 +995,7 @@ int LUKS2_hdr_write_force(struct crypt_device *cd, struct luks2_hdr *hdr)
int LUKS2_hdr_write(struct crypt_device *cd, struct luks2_hdr *hdr)
{
/* NOTE: is called before LUKS2 validation routines */
/* erase unused digests (no assigned keyslot or segment) */
LUKS2_digests_erase_unused(cd, hdr);
if (LUKS2_hdr_validate(cd, hdr->jobj, hdr->hdr_size - LUKS2_HDR_BIN_LEN))
if (hdr_cleanup_and_validate(cd, hdr))
return -EINVAL;
return LUKS2_disk_hdr_write(cd, hdr, crypt_metadata_device(cd), true);
@@ -1290,6 +1297,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 }
};
@@ -1567,7 +1576,7 @@ static void hdr_dump_keyslots(struct crypt_device *cd, json_object *hdr_jobj)
log_std(cd, " %s: %s%s\n", slot, tmps, r == -ENOENT ? " (unbound)" : "");
if (json_object_object_get_ex(val, "key_size", &jobj2))
log_std(cd, "\tKey: %u bits\n", json_object_get_uint32(jobj2) * 8);
log_std(cd, "\tKey: %u bits\n", crypt_jobj_get_uint32(jobj2) * 8);
log_std(cd, "\tPriority: %s\n", get_priority_desc(val));
@@ -1650,7 +1659,7 @@ static void hdr_dump_segments(struct crypt_device *cd, json_object *hdr_jobj)
log_std(cd, "\tcipher: %s\n", json_object_get_string(jobj1));
if (json_object_object_get_ex(jobj_segment, "sector_size", &jobj1))
log_std(cd, "\tsector: %" PRIu32 " [bytes]\n", json_object_get_uint32(jobj1));
log_std(cd, "\tsector: %" PRIu32 " [bytes]\n", crypt_jobj_get_uint32(jobj1));
if (json_object_object_get_ex(jobj_segment, "integrity", &jobj1) &&
json_object_object_get_ex(jobj1, "type", &jobj2))
@@ -1747,7 +1756,7 @@ int LUKS2_get_data_size(struct luks2_hdr *hdr, uint64_t *size, bool *dynamic)
return 0;
}
tmp += json_object_get_uint64(jobj_size);
tmp += crypt_jobj_get_uint64(jobj_size);
}
/* impossible, real device size must not be zero */
@@ -2157,7 +2166,12 @@ int LUKS2_activate(struct crypt_device *cd,
return -EINVAL;
}
r = INTEGRITY_create_dmd_device(cd, NULL, NULL, NULL, NULL, &dmdi, dmd.flags);
if (dmd.flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) {
log_err(cd, _("Discard/TRIM is not supported."));
return -EINVAL;
}
r = INTEGRITY_create_dmd_device(cd, NULL, NULL, NULL, NULL, &dmdi, dmd.flags, 0);
if (r)
return r;

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
@@ -148,7 +148,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)
@@ -300,11 +300,11 @@ int LUKS2_keyslot_area(struct luks2_hdr *hdr,
if (!json_object_object_get_ex(jobj_area, "offset", &jobj))
return -EINVAL;
*offset = json_object_get_uint64(jobj);
*offset = crypt_jobj_get_uint64(jobj);
if (!json_object_object_get_ex(jobj_area, "size", &jobj))
return -EINVAL;
*length = json_object_get_uint64(jobj);
*length = crypt_jobj_get_uint64(jobj);
return 0;
}
@@ -835,8 +835,8 @@ int placeholder_keyslot_alloc(struct crypt_device *cd,
/* Area object */
jobj_area = json_object_new_object();
json_object_object_add(jobj_area, "offset", json_object_new_uint64(area_offset));
json_object_object_add(jobj_area, "size", json_object_new_uint64(area_length));
json_object_object_add(jobj_area, "offset", crypt_jobj_new_uint64(area_offset));
json_object_object_add(jobj_area, "size", crypt_jobj_new_uint64(area_length));
json_object_object_add(jobj_keyslot, "area", jobj_area);
json_object_object_add_by_uint(jobj_keyslots, keyslot, jobj_keyslot);

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;
@@ -220,7 +220,7 @@ static int luks2_keyslot_set_key(struct crypt_device *cd,
if (!json_object_object_get_ex(jobj_area, "offset", &jobj2))
return -EINVAL;
area_offset = json_object_get_uint64(jobj2);
area_offset = crypt_jobj_get_uint64(jobj2);
if (!json_object_object_get_ex(jobj_area, "encryption", &jobj2))
return -EINVAL;
@@ -313,7 +313,7 @@ static int luks2_keyslot_get_key(struct crypt_device *cd,
if (!json_object_object_get_ex(jobj_area, "offset", &jobj2))
return -EINVAL;
area_offset = json_object_get_uint64(jobj2);
area_offset = crypt_jobj_get_uint64(jobj2);
if (!json_object_object_get_ex(jobj_area, "encryption", &jobj2))
return -EINVAL;
@@ -494,8 +494,8 @@ static int luks2_keyslot_alloc(struct crypt_device *cd,
/* Area object */
jobj_area = json_object_new_object();
json_object_object_add(jobj_area, "type", json_object_new_string("raw"));
json_object_object_add(jobj_area, "offset", json_object_new_uint64(area_offset));
json_object_object_add(jobj_area, "size", json_object_new_uint64(area_length));
json_object_object_add(jobj_area, "offset", crypt_jobj_new_uint64(area_offset));
json_object_object_add(jobj_area, "size", crypt_jobj_new_uint64(area_length));
json_object_object_add(jobj_keyslot, "area", jobj_area);
json_object_object_add_by_uint(jobj_keyslots, keyslot, jobj_keyslot);
@@ -607,7 +607,7 @@ static int luks2_keyslot_dump(struct crypt_device *cd, int keyslot)
log_std(cd, "\tCipher: %s\n", json_object_get_string(jobj1));
json_object_object_get_ex(jobj_area, "key_size", &jobj1);
log_std(cd, "\tCipher key: %u bits\n", json_object_get_uint32(jobj1) * 8);
log_std(cd, "\tCipher key: %u bits\n", crypt_jobj_get_uint32(jobj1) * 8);
json_object_object_get_ex(jobj_kdf, "type", &jobj1);
log_std(cd, "\tPBKDF: %s\n", json_object_get_string(jobj1));
@@ -617,7 +617,7 @@ static int luks2_keyslot_dump(struct crypt_device *cd, int keyslot)
log_std(cd, "\tHash: %s\n", json_object_get_string(jobj1));
json_object_object_get_ex(jobj_kdf, "iterations", &jobj1);
log_std(cd, "\tIterations: %" PRIu64 "\n", json_object_get_uint64(jobj1));
log_std(cd, "\tIterations: %" PRIu64 "\n", crypt_jobj_get_uint64(jobj1));
} else {
json_object_object_get_ex(jobj_kdf, "time", &jobj1);
log_std(cd, "\tTime cost: %" PRIu64 "\n", json_object_get_int64(jobj1));
@@ -640,10 +640,10 @@ static int luks2_keyslot_dump(struct crypt_device *cd, int keyslot)
log_std(cd, "\tAF hash: %s\n", json_object_get_string(jobj1));
json_object_object_get_ex(jobj_area, "offset", &jobj1);
log_std(cd, "\tArea offset:%" PRIu64 " [bytes]\n", json_object_get_uint64(jobj1));
log_std(cd, "\tArea offset:%" PRIu64 " [bytes]\n", crypt_jobj_get_uint64(jobj1));
json_object_object_get_ex(jobj_area, "size", &jobj1);
log_std(cd, "\tArea length:%" PRIu64 " [bytes]\n", json_object_get_uint64(jobj1));
log_std(cd, "\tArea length:%" PRIu64 " [bytes]\n", crypt_jobj_get_uint64(jobj1));
return 0;
}

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
@@ -67,13 +67,13 @@ int reenc_keyslot_alloc(struct crypt_device *cd,
if (params->data_shift) {
json_object_object_add(jobj_area, "type", json_object_new_string("datashift"));
json_object_object_add(jobj_area, "shift_size", json_object_new_uint64(params->data_shift << SECTOR_SHIFT));
json_object_object_add(jobj_area, "shift_size", crypt_jobj_new_uint64(params->data_shift << SECTOR_SHIFT));
} else
/* except data shift protection, initial setting is irrelevant. Type can be changed during reencryption */
json_object_object_add(jobj_area, "type", json_object_new_string("none"));
json_object_object_add(jobj_area, "offset", json_object_new_uint64(area_offset));
json_object_object_add(jobj_area, "size", json_object_new_uint64(area_length));
json_object_object_add(jobj_area, "offset", crypt_jobj_new_uint64(area_offset));
json_object_object_add(jobj_area, "size", crypt_jobj_new_uint64(area_length));
json_object_object_add(jobj_keyslot, "type", json_object_new_string("reencrypt"));
json_object_object_add(jobj_keyslot, "key_size", json_object_new_int(1)); /* useless but mandatory */
@@ -113,8 +113,8 @@ static int reenc_keyslot_store_data(struct crypt_device *cd,
!json_object_object_get_ex(jobj_area, "size", &jobj_length))
return -EINVAL;
area_offset = json_object_get_uint64(jobj_offset);
area_length = json_object_get_uint64(jobj_length);
area_offset = crypt_jobj_get_uint64(jobj_offset);
area_length = crypt_jobj_get_uint64(jobj_length);
if (!area_offset || !area_length || ((uint64_t)buffer_len > area_length))
return -EINVAL;
@@ -242,14 +242,14 @@ static int reenc_keyslot_dump(struct crypt_device *cd, int keyslot)
log_std(cd, "\t%-12s%d [bytes]\n", "Hash data:", json_object_get_int(jobj1));
} else if (!strcmp(json_object_get_string(jobj_resilience), "datashift")) {
json_object_object_get_ex(jobj_area, "shift_size", &jobj1);
log_std(cd, "\t%-12s%" PRIu64 "[bytes]\n", "Shift size:", json_object_get_uint64(jobj1));
log_std(cd, "\t%-12s%" PRIu64 "[bytes]\n", "Shift size:", crypt_jobj_get_uint64(jobj1));
}
json_object_object_get_ex(jobj_area, "offset", &jobj1);
log_std(cd, "\tArea offset:%" PRIu64 " [bytes]\n", json_object_get_uint64(jobj1));
log_std(cd, "\tArea offset:%" PRIu64 " [bytes]\n", crypt_jobj_get_uint64(jobj1));
json_object_object_get_ex(jobj_area, "size", &jobj1);
log_std(cd, "\tArea length:%" PRIu64 " [bytes]\n", json_object_get_uint64(jobj1));
log_std(cd, "\tArea length:%" PRIu64 " [bytes]\n", crypt_jobj_get_uint64(jobj1));
return 0;
}
@@ -304,7 +304,7 @@ static int reenc_keyslot_validate(struct crypt_device *cd, json_object *jobj_key
return -EINVAL;
if (!validate_json_uint32(jobj_sector_size))
return -EINVAL;
sector_size = json_object_get_uint32(jobj_sector_size);
sector_size = crypt_jobj_get_uint32(jobj_sector_size);
if (sector_size < SECTOR_SIZE || NOTPOW2(sector_size)) {
log_dbg(cd, "Invalid sector_size (%" PRIu32 ") for checksum resilience mode.", sector_size);
return -EINVAL;
@@ -313,7 +313,7 @@ static int reenc_keyslot_validate(struct crypt_device *cd, json_object *jobj_key
if (!(jobj_shift_size = json_contains(cd, jobj_area, "type:datashift", "Keyslot area", "shift_size", json_type_string)))
return -EINVAL;
shift_size = json_object_get_uint64(jobj_shift_size);
shift_size = crypt_jobj_get_uint64(jobj_shift_size);
if (!shift_size)
return -EINVAL;

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
@@ -91,8 +91,8 @@ static int json_luks1_keyslot(const struct luks_phdr *hdr_v1, int keyslot, struc
}
area_size = offs_b - offs_a;
json_object_object_add(jobj_area, "key_size", json_object_new_int(hdr_v1->keyBytes));
json_object_object_add(jobj_area, "offset", json_object_new_uint64(offset));
json_object_object_add(jobj_area, "size", json_object_new_uint64(area_size));
json_object_object_add(jobj_area, "offset", crypt_jobj_new_uint64(offset));
json_object_object_add(jobj_area, "size", crypt_jobj_new_uint64(area_size));
json_object_object_add(keyslot_obj, "area", jobj_area);
*keyslot_object = keyslot_obj;
@@ -145,7 +145,7 @@ static int json_luks1_segment(const struct luks_phdr *hdr_v1, struct json_object
/* offset field */
number = (uint64_t)hdr_v1->payloadOffset * SECTOR_SIZE;
field = json_object_new_uint64(number);
field = crypt_jobj_new_uint64(number);
if (!field) {
json_object_put(segment_obj);
return -ENOMEM;
@@ -401,8 +401,9 @@ static int json_luks1_object(struct luks_phdr *hdr_v1, struct json_object **luks
json_object_object_add(luks1_obj, "config", field);
json_size = LUKS2_HDR_16K_LEN - LUKS2_HDR_BIN_LEN;
json_object_object_add(field, "json_size", json_object_new_uint64(json_size));
json_object_object_add(field, "keyslots_size", json_object_new_uint64(keyslots_size));
json_object_object_add(field, "json_size", crypt_jobj_new_uint64(json_size));
keyslots_size -= (keyslots_size % 4096);
json_object_object_add(field, "keyslots_size", crypt_jobj_new_uint64(keyslots_size));
*luks1_object = luks1_obj;
return 0;
@@ -418,8 +419,8 @@ static void move_keyslot_offset(json_object *jobj, int offset_add)
UNUSED(key);
json_object_object_get_ex(val, "area", &jobj_area);
json_object_object_get_ex(jobj_area, "offset", &jobj2);
offset = json_object_get_uint64(jobj2) + offset_add;
json_object_object_add(jobj_area, "offset", json_object_new_uint64(offset));
offset = crypt_jobj_get_uint64(jobj2) + offset_add;
json_object_object_add(jobj_area, "offset", crypt_jobj_new_uint64(offset));
}
}
@@ -577,6 +578,12 @@ int LUKS2_luks1_to_luks2(struct crypt_device *cd, struct luks_phdr *hdr1, struct
goto out;
}
/* check future LUKS2 metadata before moving keyslots area */
if (LUKS2_hdr_validate(cd, hdr2->jobj, hdr2->hdr_size - LUKS2_HDR_BIN_LEN)) {
r = -EINVAL;
goto out;
}
if ((r = luks_header_in_use(cd))) {
if (r > 0)
r = -EBUSY;
@@ -586,6 +593,14 @@ int LUKS2_luks1_to_luks2(struct crypt_device *cd, struct luks_phdr *hdr1, struct
// move keyslots 4k -> 32k offset
buf_offset = 2 * LUKS2_HDR_16K_LEN;
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)) {
log_err(cd, _("Unable to move keyslot area. LUKS2 keyslots area too small."));
r = -EINVAL;
goto out;
}
if ((r = move_keyslot_areas(cd, 8 * SECTOR_SIZE, buf_offset, buf_size)) < 0) {
log_err(cd, _("Unable to move keyslot area."));
goto out;
@@ -660,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;
@@ -749,7 +764,7 @@ int LUKS2_luks2_to_luks1(struct crypt_device *cd, struct luks2_hdr *hdr2, struct
return -EINVAL;
if (!json_object_object_get_ex(jobj_area, "offset", &jobj1))
return -EINVAL;
offset = json_object_get_uint64(jobj1);
offset = crypt_jobj_get_uint64(jobj1);
} else {
if (LUKS2_find_area_gap(cd, hdr2, key_size, &offset, &area_length))
return -EINVAL;
@@ -781,7 +796,7 @@ int LUKS2_luks2_to_luks1(struct crypt_device *cd, struct luks2_hdr *hdr2, struct
if (!json_object_object_get_ex(jobj_kdf, "iterations", &jobj1))
continue;
hdr1->keyblock[i].passwordIterations = json_object_get_uint32(jobj1);
hdr1->keyblock[i].passwordIterations = crypt_jobj_get_uint32(jobj1);
if (!json_object_object_get_ex(jobj_kdf, "salt", &jobj1))
continue;
@@ -809,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;
@@ -822,7 +839,7 @@ int LUKS2_luks2_to_luks1(struct crypt_device *cd, struct luks2_hdr *hdr2, struct
if (!json_object_object_get_ex(jobj_digest, "iterations", &jobj1))
return -EINVAL;
hdr1->mkDigestIterations = json_object_get_uint32(jobj1);
hdr1->mkDigestIterations = crypt_jobj_get_uint32(jobj1);
if (!json_object_object_get_ex(jobj_digest, "digest", &jobj1))
return -EINVAL;
@@ -847,7 +864,7 @@ int LUKS2_luks2_to_luks1(struct crypt_device *cd, struct luks2_hdr *hdr2, struct
if (!json_object_object_get_ex(jobj_segment, "offset", &jobj1))
return -EINVAL;
offset = json_object_get_uint64(jobj1) / SECTOR_SIZE;
offset = crypt_jobj_get_uint64(jobj1) / SECTOR_SIZE;
if (offset > UINT32_MAX)
return -EINVAL;
/* FIXME: LUKS1 requires offset == 0 || offset >= luks1_hdr_size */

View File

@@ -1,8 +1,8 @@
/*
* LUKS - Linux Unified Key Setup v2, reencryption helpers
*
* Copyright (C) 2015-2020, Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2020, Ondrej Kozina
* Copyright (C) 2015-2021, Red Hat, Inc. All rights reserved.
* 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
@@ -165,7 +165,7 @@ static uint32_t reencrypt_alignment(struct luks2_hdr *hdr)
if (!json_object_object_get_ex(jobj_area, "sector_size", &jobj_sector_size))
return 0;
return json_object_get_uint32(jobj_sector_size);
return crypt_jobj_get_uint32(jobj_sector_size);
}
static json_object *_enc_create_segments_shift_after(struct crypt_device *cd,
@@ -200,13 +200,13 @@ static json_object *_enc_create_segments_shift_after(struct crypt_device *cd,
json_segment_remove_flag(jobj_seg_new, "in-reencryption");
tmp = rh->length;
} else {
json_object_object_add(jobj_seg_new, "offset", json_object_new_uint64(rh->offset + data_offset));
json_object_object_add(jobj_seg_new, "iv_tweak", json_object_new_uint64(rh->offset >> SECTOR_SHIFT));
json_object_object_add(jobj_seg_new, "offset", crypt_jobj_new_uint64(rh->offset + data_offset));
json_object_object_add(jobj_seg_new, "iv_tweak", crypt_jobj_new_uint64(rh->offset >> SECTOR_SHIFT));
tmp = json_segment_get_size(jobj_seg_new, 0) + rh->length;
}
/* alter size of new segment, reenc_seg == 0 we're finished */
json_object_object_add(jobj_seg_new, "size", reenc_seg > 0 ? json_object_new_uint64(tmp) : json_object_new_string("dynamic"));
json_object_object_add(jobj_seg_new, "size", reenc_seg > 0 ? crypt_jobj_new_uint64(tmp) : json_object_new_string("dynamic"));
json_object_object_add_by_uint(jobj_segs_post, reenc_seg, jobj_seg_new);
return jobj_segs_post;
@@ -256,7 +256,7 @@ static json_object *reencrypt_make_hot_segments_encrypt_shift(struct crypt_devic
jobj_seg_shrunk = NULL;
if (json_object_copy(LUKS2_get_segment_jobj(hdr, sg), &jobj_seg_shrunk))
goto err;
json_object_object_add(jobj_seg_shrunk, "size", json_object_new_uint64(segment_size - rh->length));
json_object_object_add(jobj_seg_shrunk, "size", crypt_jobj_new_uint64(segment_size - rh->length));
json_object_object_add_by_uint(jobj_segs_hot, sg++, jobj_seg_shrunk);
}
@@ -336,7 +336,7 @@ static json_object *reencrypt_make_post_segments_forward(struct crypt_device *cd
goto err;
jobj_old_seg = jobj_old_seg_copy;
fixed_length = rh->device_size - fixed_length;
json_object_object_add(jobj_old_seg, "size", json_object_new_uint64(fixed_length));
json_object_object_add(jobj_old_seg, "size", crypt_jobj_new_uint64(fixed_length));
} else
json_object_get(jobj_old_seg);
json_object_object_add_by_uint(jobj_segs_post, 1, jobj_old_seg);
@@ -491,7 +491,7 @@ static json_object *reencrypt_make_hot_segments_backward(struct crypt_device *cd
if (rh->offset) {
if (json_object_copy(LUKS2_get_segment_jobj(hdr, 0), &jobj_old_seg))
goto err;
json_object_object_add(jobj_old_seg, "size", json_object_new_uint64(rh->offset));
json_object_object_add(jobj_old_seg, "size", crypt_jobj_new_uint64(rh->offset));
json_object_object_add_by_uint(jobj_segs_hot, sg++, jobj_old_seg);
}
@@ -575,7 +575,7 @@ static uint64_t reencrypt_data_shift(struct luks2_hdr *hdr)
if (!json_object_object_get_ex(jobj_area, "shift_size", &jobj_data_shift))
return 0;
return json_object_get_uint64(jobj_data_shift);
return crypt_jobj_get_uint64(jobj_data_shift);
}
static crypt_reencrypt_mode_info reencrypt_mode(struct luks2_hdr *hdr)
@@ -2238,7 +2238,7 @@ static int reencrypt_verify_and_upload_keys(struct crypt_device *cd, struct luks
if (LUKS2_digest_verify_by_digest(cd, hdr, digest_new, vk) != digest_new)
return -EINVAL;
if (crypt_use_keyring_for_vk(cd) &&
if (crypt_use_keyring_for_vk(cd) && !crypt_is_cipher_null(reencrypt_segment_cipher_new(hdr)) &&
(r = LUKS2_volume_key_load_in_keyring_by_digest(cd, hdr, vk, crypt_volume_key_get_id(vk))))
return r;
}
@@ -2254,7 +2254,7 @@ static int reencrypt_verify_and_upload_keys(struct crypt_device *cd, struct luks
r = -EINVAL;
goto err;
}
if (crypt_use_keyring_for_vk(cd) &&
if (crypt_use_keyring_for_vk(cd) && !crypt_is_cipher_null(reencrypt_segment_cipher_old(hdr)) &&
(r = LUKS2_volume_key_load_in_keyring_by_digest(cd, hdr, vk, crypt_volume_key_get_id(vk))))
goto err;
}
@@ -2310,9 +2310,11 @@ static int reencrypt_init(struct crypt_device *cd,
}
if (!cipher_mode || *cipher_mode == '\0')
snprintf(_cipher, sizeof(_cipher), "%s", cipher);
r = snprintf(_cipher, sizeof(_cipher), "%s", cipher);
else
snprintf(_cipher, sizeof(_cipher), "%s-%s", cipher, cipher_mode);
r = snprintf(_cipher, sizeof(_cipher), "%s-%s", cipher, cipher_mode);
if (r < 0 || (size_t)r >= sizeof(_cipher))
return -EINVAL;
if (MISALIGNED(params->data_shift, sector_size >> SECTOR_SHIFT)) {
log_err(cd, _("Data shift is not aligned to requested encryption sector size (%" PRIu32 " bytes)."), sector_size);
@@ -2664,6 +2666,7 @@ static int reencrypt_load_by_passphrase(struct crypt_device *cd,
struct luks2_hdr *hdr;
struct crypt_lock_handle *reencrypt_lock;
struct luks2_reenc_context *rh;
const struct volume_key *vk;
struct crypt_dm_active_device dmd_target, dmd_source = {
.uuid = crypt_get_uuid(cd),
.flags = CRYPT_ACTIVATE_SHARED /* turn off exclusive open checks */
@@ -2730,6 +2733,19 @@ static int reencrypt_load_by_passphrase(struct crypt_device *cd,
goto err;
flags = dmd_target.flags;
/*
* By default reencryption code aims to retain flags from existing dm device.
* The keyring activation flag can not be inherited if original cipher is null.
*
* In this case override the flag based on decision made in reencrypt_verify_and_upload_keys
* above. The code checks if new VK is eligible for keyring.
*/
vk = crypt_volume_key_by_id(*vks, LUKS2_reencrypt_digest_new(hdr));
if (vk && vk->key_description && crypt_is_cipher_null(reencrypt_segment_cipher_old(hdr))) {
flags |= CRYPT_ACTIVATE_KEYRING_KEY;
dmd_source.flags |= CRYPT_ACTIVATE_KEYRING_KEY;
}
r = LUKS2_assembly_multisegment_dmd(cd, hdr, *vks, LUKS2_get_segments_jobj(hdr), &dmd_source);
if (!r) {
r = crypt_compare_dm_devices(cd, &dmd_source, &dmd_target);
@@ -2882,7 +2898,7 @@ static int reencrypt_init_by_passphrase(struct crypt_device *cd,
if (flags & CRYPT_REENCRYPT_RECOVERY)
return reencrypt_recovery_by_passphrase(cd, hdr, keyslot_old, keyslot_new, passphrase, passphrase_size);
if (cipher) {
if (cipher && !crypt_cipher_wrapped_key(cipher, cipher_mode)) {
r = crypt_keyslot_get_key_size(cd, keyslot_new);
if (r < 0)
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
@@ -55,7 +55,7 @@ uint64_t json_segment_get_offset(json_object *jobj_segment, unsigned blockwise)
!json_object_object_get_ex(jobj_segment, "offset", &jobj))
return 0;
return blockwise ? json_object_get_uint64(jobj) >> SECTOR_SHIFT : json_object_get_uint64(jobj);
return blockwise ? crypt_jobj_get_uint64(jobj) >> SECTOR_SHIFT : crypt_jobj_get_uint64(jobj);
}
const char *json_segment_type(json_object *jobj_segment)
@@ -77,7 +77,7 @@ uint64_t json_segment_get_iv_offset(json_object *jobj_segment)
!json_object_object_get_ex(jobj_segment, "iv_tweak", &jobj))
return 0;
return json_object_get_uint64(jobj);
return crypt_jobj_get_uint64(jobj);
}
uint64_t json_segment_get_size(json_object *jobj_segment, unsigned blockwise)
@@ -88,7 +88,7 @@ uint64_t json_segment_get_size(json_object *jobj_segment, unsigned blockwise)
!json_object_object_get_ex(jobj_segment, "size", &jobj))
return 0;
return blockwise ? json_object_get_uint64(jobj) >> SECTOR_SHIFT : json_object_get_uint64(jobj);
return blockwise ? crypt_jobj_get_uint64(jobj) >> SECTOR_SHIFT : crypt_jobj_get_uint64(jobj);
}
const char *json_segment_get_cipher(json_object *jobj_segment)
@@ -229,8 +229,8 @@ static json_object *_segment_create_generic(const char *type, uint64_t offset, c
return NULL;
json_object_object_add(jobj, "type", json_object_new_string(type));
json_object_object_add(jobj, "offset", json_object_new_uint64(offset));
json_object_object_add(jobj, "size", length ? json_object_new_uint64(*length) : json_object_new_string("dynamic"));
json_object_object_add(jobj, "offset", crypt_jobj_new_uint64(offset));
json_object_object_add(jobj, "size", length ? crypt_jobj_new_uint64(*length) : json_object_new_string("dynamic"));
return jobj;
}
@@ -252,7 +252,7 @@ json_object *json_segment_create_crypt(uint64_t offset,
if (!jobj)
return NULL;
json_object_object_add(jobj, "iv_tweak", json_object_new_uint64(iv_offset));
json_object_object_add(jobj, "iv_tweak", crypt_jobj_new_uint64(iv_offset));
json_object_object_add(jobj, "encryption", json_object_new_string(cipher));
json_object_object_add(jobj, "sector_size", json_object_new_int(sector_size));
if (reencryption)

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
@@ -20,7 +20,6 @@
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <assert.h>
#include <sys/select.h>
@@ -28,10 +27,6 @@
#include "libcryptsetup.h"
#include "internal.h"
#ifndef O_CLOEXEC
#define O_CLOEXEC 0
#endif
static int random_initialised = 0;
#define URANDOM_DEVICE "/dev/urandom"

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
@@ -26,7 +26,6 @@
#include <stdlib.h>
#include <stdarg.h>
#include <sys/utsname.h>
#include <fcntl.h>
#include <errno.h>
#include "libcryptsetup.h"
@@ -231,7 +230,7 @@ int init_crypto(struct crypt_device *ctx)
return r;
}
r = crypt_backend_init(ctx);
r = crypt_backend_init();
if (r < 0)
log_err(ctx, _("Cannot initialize crypto backend."));
@@ -584,6 +583,9 @@ int crypt_init(struct crypt_device **cd, const char *device)
return -EINVAL;
log_dbg(NULL, "Allocating context for crypt device %s.", device ?: "(none)");
#if !HAVE_DECL_O_CLOEXEC
log_dbg(NULL, "Running without O_CLOEXEC.");
#endif
if (!(h = malloc(sizeof(struct crypt_device))))
return -ENOMEM;
@@ -655,7 +657,7 @@ 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;
}
@@ -843,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;
@@ -1082,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);
@@ -1208,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)
@@ -1872,7 +1874,7 @@ 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));
@@ -2033,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;
@@ -2058,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;
@@ -2386,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;
@@ -2398,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;
@@ -2411,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;
}
@@ -2465,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;
}
@@ -2768,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);
@@ -3088,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,
@@ -3123,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;
}
@@ -3187,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;
}
@@ -3278,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;
}
@@ -3457,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 */
@@ -3684,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 */
@@ -3877,6 +3883,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;
@@ -3888,8 +3895,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)
@@ -4159,21 +4171,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
@@ -4267,6 +4284,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;
@@ -4342,8 +4360,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)
@@ -4404,7 +4426,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."));
@@ -4954,6 +4976,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;

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
@@ -23,7 +23,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <assert.h>
#include "libcryptsetup.h"
@@ -479,8 +478,8 @@ static int TCRYPT_decrypt_hdr(struct crypt_device *cd, struct tcrypt_phdr *hdr,
}
static int TCRYPT_pool_keyfile(struct crypt_device *cd,
unsigned char pool[TCRYPT_KEY_POOL_LEN],
const char *keyfile)
unsigned char pool[VCRYPT_KEY_POOL_LEN],
const char *keyfile, int keyfiles_pool_length)
{
unsigned char *data;
int i, j, fd, data_size, r = -EIO;
@@ -512,7 +511,7 @@ static int TCRYPT_pool_keyfile(struct crypt_device *cd,
pool[j++] += (unsigned char)(crc >> 16);
pool[j++] += (unsigned char)(crc >> 8);
pool[j++] += (unsigned char)(crc);
j %= TCRYPT_KEY_POOL_LEN;
j %= keyfiles_pool_length;
}
r = 0;
out:
@@ -527,29 +526,39 @@ static int TCRYPT_init_hdr(struct crypt_device *cd,
struct tcrypt_phdr *hdr,
struct crypt_params_tcrypt *params)
{
unsigned char pwd[TCRYPT_KEY_POOL_LEN] = {};
size_t passphrase_size;
unsigned char pwd[VCRYPT_KEY_POOL_LEN] = {};
size_t passphrase_size, max_passphrase_size;
char *key;
unsigned int i, skipped = 0, iterations;
int r = -EPERM;
int r = -EPERM, keyfiles_pool_length;
if (posix_memalign((void*)&key, crypt_getpagesize(), TCRYPT_HDR_KEY_LEN))
return -ENOMEM;
if (params->flags & CRYPT_TCRYPT_VERA_MODES &&
params->passphrase_size > TCRYPT_KEY_POOL_LEN) {
/* Really. Keyfile pool length depends on passphrase size in Veracrypt. */
max_passphrase_size = VCRYPT_KEY_POOL_LEN;
keyfiles_pool_length = VCRYPT_KEY_POOL_LEN;
} else {
max_passphrase_size = TCRYPT_KEY_POOL_LEN;
keyfiles_pool_length = TCRYPT_KEY_POOL_LEN;
}
if (params->keyfiles_count)
passphrase_size = TCRYPT_KEY_POOL_LEN;
passphrase_size = max_passphrase_size;
else
passphrase_size = params->passphrase_size;
if (params->passphrase_size > TCRYPT_KEY_POOL_LEN) {
log_err(cd, _("Maximum TCRYPT passphrase length (%d) exceeded."),
TCRYPT_KEY_POOL_LEN);
if (params->passphrase_size > max_passphrase_size) {
log_err(cd, _("Maximum TCRYPT passphrase length (%zu) exceeded."),
max_passphrase_size);
goto out;
}
/* Calculate pool content from keyfiles */
for (i = 0; i < params->keyfiles_count; i++) {
r = TCRYPT_pool_keyfile(cd, pwd, params->keyfiles[i]);
r = TCRYPT_pool_keyfile(cd, pwd, params->keyfiles[i], keyfiles_pool_length);
if (r < 0)
goto out;
}
@@ -740,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;
@@ -760,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;
@@ -1022,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;
}
@@ -1033,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;
}
@@ -1046,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,
@@ -1064,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
@@ -42,6 +42,7 @@
#define TCRYPT_LRW_IKEY_LEN 16
#define TCRYPT_KEY_POOL_LEN 64
#define VCRYPT_KEY_POOL_LEN 128
#define TCRYPT_KEYFILE_LEN 1048576
#define TCRYPT_HDR_FLAG_SYSTEM (1 << 0)

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
@@ -23,7 +23,6 @@
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/resource.h>
#include <sys/stat.h>

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
@@ -48,6 +48,12 @@ int crypt_benchmark(struct crypt_device *cd,
if (posix_memalign(&buffer, crypt_getpagesize(), buffer_size))
goto out;
r = crypt_cipher_ivsize(cipher, cipher_mode);
if (r >= 0 && iv_size != (size_t)r) {
log_dbg(cd, "IV length for benchmark adjusted to %i bytes (requested %zu).", r, iv_size);
iv_size = r;
}
if (iv_size) {
iv = malloc(iv_size);
if (!iv)
@@ -71,9 +77,9 @@ int crypt_benchmark(struct crypt_device *cd,
if (r == -ERANGE)
log_dbg(cd, "Measured cipher runtime is too low.");
else if (r == -ENOTSUP || r == -ENOENT)
log_dbg(cd, "Cannot initialize cipher %s, mode %s.", cipher, cipher_mode);
else if (r)
log_dbg(cd, "Cannot initialize cipher %s, mode %s, key size %zu, IV size %zu.",
cipher, cipher_mode, volume_key_size, iv_size);
out:
free(buffer);
free(key);

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
@@ -310,9 +310,9 @@ int blk_supported(void)
off_t blk_get_offset(struct blkid_handle *h)
{
const char *offset;
off_t offset_value = -1;
#ifdef HAVE_BLKID
const char *offset;
if (blk_is_superblock(h)) {
if (!blkid_probe_lookup_value(h->pr, "SBMAGIC_OFFSET", &offset, NULL))
offset_value = strtoll(offset, NULL, 10);

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
@@ -24,7 +24,6 @@
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -163,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));
@@ -218,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)) {
@@ -301,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);
}
@@ -355,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);
}
@@ -521,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))
@@ -584,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)
@@ -607,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;
@@ -847,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)
@@ -873,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;
@@ -901,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) {
@@ -914,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))
@@ -935,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));
@@ -945,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));
@@ -955,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
@@ -20,7 +20,6 @@
*/
#include <errno.h>
#include <fcntl.h>
#include <linux/limits.h>
#include <stdio.h>
#include <stdlib.h>
@@ -107,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
@@ -26,7 +26,6 @@
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include <fcntl.h>
#include <errno.h>
#include <limits.h>
#include <sys/stat.h>
@@ -368,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;
@@ -68,6 +69,10 @@ static inline uint32_t act2dmflags(uint32_t act_flags)
#define DM_BITLK_EBOIV_SUPPORTED (1 << 20) /* EBOIV for BITLK supported */
#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 };
@@ -117,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 {
@@ -145,6 +149,8 @@ struct dm_target {
struct device *meta_device;
bool fix_padding;
bool fix_hmac;
bool legacy_recalc;
} integrity;
struct {
uint64_t offset;
@@ -184,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)

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