Compare commits

..

212 Commits

Author SHA1 Message Date
Milan Broz
3d403a7bd0 Bump libcryptsetup version. 2015-03-23 18:22:16 +01:00
Milan Broz
91f6296699 Prepare version 1.6.7. 2015-03-23 17:49:06 +01:00
Milan Broz
bd94eb36b3 Update po files. 2015-03-20 13:32:42 +01:00
Milan Broz
1a19329b18 Use silent rules in autoconf. 2015-03-20 13:32:13 +01:00
Milan Broz
78a43c053a Update po files. 2015-03-19 12:35:09 +01:00
Milan Broz
d7d76e72f7 Update URLs (->gitlab.com).
The code.google is going to be abandoned.
Thank you you for all the fish.
2015-03-19 11:23:16 +01:00
Milan Broz
dd0dcc05df Fix typo in URL. 2015-03-19 11:05:28 +01:00
Milan Broz
3be8731fef Add notes about releases. 2015-03-19 11:03:14 +01:00
Milan Broz
86d0ff1a2b Add README.md for project page info. 2015-03-19 10:43:40 +01:00
Milan Broz
3adfe80601 Test device read only once for O_DIRECT.
Also do not report error for disappeared device (it is reported later on real access).
2015-03-19 09:39:36 +01:00
Milan Broz
0bc437d92c Detect if O_DIRECT is usable on device allocation.
Try to read the first sector of a device when allocating
device context.

Should fix issue#247.
2015-03-18 15:01:53 +01:00
Milan Broz
6b10f30eb9 Reorder algorithms for VeraCrypt modes. 2015-02-27 10:12:54 +01:00
Milan Broz
fedd5bc969 Update de.po. 2015-02-26 08:08:16 +01:00
Milan Broz
8aee4f95fb Clarify using of VeraCrypt modes in libcryptsetup.h. 2015-02-25 10:55:24 +01:00
Milan Broz
1f2d8de95f Support VeraCrypt devices (TrueCrypt extension).
Add CRYPT_TCRYPT_VERA_MODES libcryptswtup flag and
--veracrypt option.

Fixes issue#245.
2015-02-24 22:04:15 +01:00
Milan Broz
dced269426 Update kernel version in man page. 2015-02-23 10:19:02 +01:00
Milan Broz
b834a59eaf Fix typo in man page.
Fixes issue#244.
2015-02-20 16:57:20 +01:00
Milan Broz
4f7b413638 Add low-level performance options for dmcrypt tuning.
The patch adds the two options
  --perf-same_cpu_crypt
  --perf-submit_from_crypt_cpus
that set the same named options inside dmcrypt
(available in Linux kernel 3.20 and later).
2015-02-20 16:46:34 +01:00
Milan Broz
e4355c2973 Wait for udev scan before removing device in reencrypt test. 2015-02-20 13:02:27 +01:00
Milan Broz
31a4d552a2 Support keyfile offset and keyfile size option even for plain volumes.
For historic reasons, in the plain mode the hashing is not used
if keyfile is used (with exception of --key-file=-).

Print warning if the parameters are ignored.

For other cases, uses keyfile offset, keyfile size and hash
as psecified on commandline.

Partially fixes issue#243
2015-02-20 12:55:21 +01:00
Milan Broz
6d51e8ab69 Support permanent device decryption using cryptsetup-reencrypt --decrypt. 2015-01-27 14:20:34 +01:00
Milan Broz
8157e47ad4 Support keyfile for luksAddKey if the master key is specified.
If AddKey was called with master key argument, the code always asked
for a passphrase ignoring the keyfile argument.

Now it is properly processed as the same as if no master key is specified.
2015-01-26 14:42:46 +01:00
Milan Broz
62b0138dad Allow to use --header option in all LUKS commands.
The --header always takes precedence over positional device argument.

Also allow specify UUID= for luksSuspend and luksResume if used with
detached header.
2015-01-26 13:31:37 +01:00
Milan Broz
c13a8003fa Mention that loop-AES extension cannot use real terminal for key file input.
Based on issue#242.
2015-01-15 16:03:54 +01:00
Milan Broz
979aec773e Fix activation using (UNSECURE) ECB mode.
Apparently there are some people using ECB.

This mode by design do not use any IV, unfortunately
kernel dmcrypt allows to specify them (but userspace crypto api don't).

Let support activation as it was in previous version.

Should fix issue#238.
2015-01-15 13:21:42 +01:00
Milan Broz
b789b011a2 Fix some compiler warnings introduced recently. 2015-01-15 12:27:34 +01:00
Colin Misare
ea8864badf printing unsigned fields as unsigned 2015-01-15 11:14:42 +01:00
Milan Broz
49335b600f Allow luksSuspend without explicitly specify detached header.
If LUKS device was configured to use detached header, suspend operation
required --header option. For now it is enough that active device in-kernel
UUID type is set properly.

FIxes issue#229.
2015-01-15 10:40:17 +01:00
Milan Broz
7245af59d3 Get rid of libfipscheck library.
With recent RHEL changes we need only check /sys file
and do not need to link to this FIPS monster.
2015-01-12 21:56:44 +01:00
Milan Broz
f7b61b2617 Prevent compiler to optiize-out memset for on-stack variables.
Also see
https://cryptocoding.net/index.php/Coding_rules#Prevent_compiler_interference_with_security-critical_operations

The used code is inspired by the code in Blake2 implementation.
2015-01-11 20:26:45 +01:00
Ondrej Kozina
dc40b91cdf libcryptsetup: drop FIPS power on self test
- cryptsetup library is not required to be FIPS certified anymore
  due to fact gcrypt PBKDF2 algorithm can be used instead of
  cryptsetup internal one.

- check in library constructor is no longer needed and therefore
  removed.

- all other checks regarding MK extraction or random generator
  restrictions remain the same
2015-01-10 21:09:17 +01:00
Milan Broz
eccf347568 Flush stdout when expecting user input on stdin. 2015-01-10 20:36:49 +01:00
Milan Broz
e24a72f84c Fix crash if non-GNU strerror_r is used.
The strerror_r call exists in POSIX and GNU variant,
if POSIX variant is used (like in musl libc replacement)
we cannot rely on char* pointer.

Fixes issue#237.
2015-01-10 20:33:42 +01:00
Milan Broz
2c70c057d6 Fix typo in man page. 2014-11-02 18:18:36 +01:00
Milan Broz
f16f37233f Fix partial reads and handle EINTR in reencryption code.
The partial read usually happens only on IO error,
so reencrypt at least part what is read properly.

For EINTR code must restart read completely.

Fixes issue#226.
2014-10-04 15:39:38 +02:00
Ondrej Kozina
3cffadb508 fix possible close of unrelated fd on error path
- infd var is uninitialised on error path in case where
  maxlen is less than 1
2014-10-01 20:10:23 +02:00
Ondrej Kozina
ce30d5f1fd add vfat test image 2014-09-23 21:31:18 +02:00
Ondrej Kozina
6e0f0408a0 reencrypt-compat-test: test log I/Os on various fs 2014-09-23 21:31:10 +02:00
Ondrej Kozina
3d6bcae84c reencrypt: use fsync instead of O_DIRECT flag
O_DIRECT operations directed towards filesystem are problematic:
There's no sane way how to detect specific filesystem requirements
for such operations.

This patch is replacing O_DIRECT flag with O_SYNC flag for all
open() calls related to reencrypt log. The O_SYNC flag is used
when --use-fsync option is detected.

Man page is modified accordingly.
2014-09-23 18:47:02 +02:00
Milan Broz
b8beedb621 Fix typo in man page. 2014-08-30 10:37:49 +02:00
Milan Broz
fd5c2a5000 Update po files. 2014-08-22 12:43:10 +02:00
Milan Broz
69bc154fca Update po files. 2014-08-18 20:49:11 +02:00
Milan Broz
387041ccf2 Set devel version. 2014-08-16 12:24:25 +02:00
Milan Broz
64d6b339a0 Prepare version 1.6.6. 2014-08-16 11:15:46 +02:00
Milan Broz
4f5f1b78c4 Update po files. 2014-08-16 11:00:18 +02:00
Milan Broz
3e886ecf57 Update po files. 2014-08-13 17:50:00 +02:00
Milan Broz
210ea612b3 Avoid compilation warnings in Python wrapper.
All these are Python interface misconceptions,
the strings (or string arrays) in parameters should be const
parameters.

To avoid gcc confusing warnings just explicitly re-cast them.
2014-08-10 16:09:32 +02:00
Milan Broz
3350ff017f Do not allocate big context on stack for cryptsetup-reencrypt. 2014-08-10 16:09:01 +02:00
Milan Broz
7b42254975 Workaround for scan-build false positive.
Also tidy code to be more readable.
2014-08-10 16:07:47 +02:00
Milan Broz
e84b1ed7c0 Fix scan-build warning (null use).
Probably false positive but defensive approach is better here.
2014-08-10 16:06:21 +02:00
Milan Broz
f3f1bfd73a Update po files. 2014-08-09 15:14:38 +02:00
Milan Broz
89f795d7b4 Fix keyslot device access for devices not supporting O_DIRECT. 2014-08-08 14:49:38 +02:00
Milan Broz
c36a7968f4 Add test for tmpfs / O_DIRECT etc. 2014-08-08 14:09:37 +02:00
Milan Broz
3762c8b76e Report crypto lib version only once (and add kernel version). 2014-07-27 20:39:06 +02:00
Milan Broz
872becdbbd Handle also missing support for tcrypt test in kernel properly. 2014-07-27 19:39:53 +02:00
Milan Broz
c9694437d2 Fix tcrypt test for unsupported combinations. 2014-07-27 18:40:21 +02:00
Milan Broz
64ad90f73c Ignore wrong parameters fail in LUKS images tests if whirlpool hash is used. 2014-07-27 17:02:51 +02:00
Milan Broz
166d23a813 Fix tests for GNU grep syntax. 2014-07-27 16:31:46 +02:00
Milan Broz
59fdf2a6bb Properly allow activation of discard even if dm_crypt module is not yet loaded.
The dm_flags() call cannot be used if dmcrypt module is not present.

Better try to activate volume with dicard flags and if it is not possible,
try to activate device without the discard flag.
2014-07-24 22:11:58 +02:00
Milan Broz
3640eaa726 Re-check flags after DM device creations. 2014-07-24 11:52:58 +02:00
Milan Broz
2250d5f71f Move safe table params wipe into function which allocates it. 2014-07-24 11:37:24 +02:00
Milan Broz
d9678325a2 Update LUKS1 test images. 2014-07-12 21:16:19 +02:00
Milan Broz
dc8c47d936 Fallback to old temporary device mapping method if hash is not supported. 2014-07-12 20:30:24 +02:00
Milan Broz
5b7100ff87 Update po files. 2014-07-10 19:06:11 +02:00
Milan Broz
4afa592160 Set devel version. 2014-06-29 14:36:10 +02:00
Milan Broz
54c7a2b0aa Fix signed/unsigned compiler warnings. 2014-06-29 11:55:11 +02:00
Milan Broz
9cabc9bf05 Bump library version.
There are new use case but it is still backwards compatible.
2014-06-29 10:53:59 +02:00
Milan Broz
dfd46df8a5 Properly fail for unsupported IVs. 2014-06-29 10:38:50 +02:00
Milan Broz
25cd4f3a1d Add debug info for crypto wrapper in LUKS keyslot encryption. 2014-06-28 21:50:05 +02:00
Milan Broz
d5b594dd12 Remove uneeded check in luksFormat to allow operation as normal user. 2014-06-28 15:23:04 +02:00
Milan Broz
803686ea4b Prepare version 1.6.5. 2014-06-28 13:57:32 +02:00
Milan Broz
3add769b51 Add deprecation warning about internal terminal password query. 2014-06-28 13:49:26 +02:00
Milan Broz
d5a72cd65a Fix typo in kernel backend. 2014-06-26 15:38:51 +02:00
Milan Broz
d63163e46c Add notes about Whirlpool hash fail to tests. 2014-06-26 14:47:02 +02:00
Milan Broz
62d690492c Fix unit in reencrypt man page. 2014-06-26 14:44:15 +02:00
Ondrej Kozina
54d81a6258 fix memory leak on error path 2014-06-25 18:03:42 +02:00
Milan Broz
56679a6e4a Update es.po. 2014-06-25 17:57:12 +02:00
Milan Broz
e0788d9d61 Update es.po. 2014-06-24 17:56:05 +02:00
wagner
833e066853 sync with wiki, updated to "toned down" item 2.2 2014-06-24 03:06:36 +02:00
Milan Broz
02f860140d Fix trailing space. 2014-06-23 23:30:11 +02:00
Milan Broz
027cebade3 Update po files. 2014-06-23 21:40:54 +02:00
Milan Broz
bb8dbfdf5b Update author name. 2014-06-23 21:40:12 +02:00
Milan Broz
8e380183f8 Print minimal device size if LUKS header space is too small. 2014-06-22 17:51:31 +02:00
Ondrej Kozina
4f89028c67 modify FIPS checks
- we need a way to notify an user about running misconfigured system which
will turn to be unusable in real FIPS mode. For more details look at:
http://bugzilla.redhat.com/show_bug.cgi?id=1009707#c25

- also fixes invisble verbose log about running in FIPS mode due to its misplacement
2014-06-22 17:24:10 +02:00
Milan Broz
6b4c33d3a5 Enable to specify Python version in configure. 2014-06-18 23:06:04 +02:00
Robert Kuska
7a2e6990ca Port pycryptsetup-test.py to Python3. 2014-06-18 09:19:03 +02:00
Robert Kuska
98ba2f2333 Port pycryptsetup.c to Python3. 2014-06-18 09:09:40 +02:00
Ondrej Kozina
4e4d933d7b fix reencryption tests failure with older grep 2014-06-18 08:56:23 +02:00
Milan Broz
91c739958c Allow ECB mode in cryptsetup benchmark. 2014-06-17 23:09:13 +02:00
Milan Broz
1a6e1ae918 Always remove temporary active device name on load and format. 2014-06-17 22:28:51 +02:00
Milan Broz
aedf39a9ca Remove unused static declaration. 2014-06-17 22:01:59 +02:00
Milan Broz
a274cd3a74 Update TODO. 2014-06-17 21:55:42 +02:00
Milan Broz
6be21469fb Use internel PBKDF2 in Nettle library for Nettle crypto backend.
This also requires Nettle >= 2.6.
2014-06-17 21:54:14 +02:00
Milan Broz
e0d3ff8aeb Fix non-header context init for device in use. 2014-06-14 23:04:43 +02:00
Milan Broz
0614ab6b07 Allow simple status of crypt device without providing metadata header.
If device is activated, we can provide some information from
active kernel parameters instead of header.
2014-06-14 17:42:57 +02:00
Milan Broz
49e55c0f42 Fix keyfile offset parameter for loopaes.
Fixes Issue#216.
2014-06-14 14:35:27 +02:00
Milan Broz
be4edbb460 Update es.po. 2014-06-13 16:51:59 +02:00
Milan Broz
4d30237f7a Handle error better in storage wrapper. 2014-06-01 22:02:32 +02:00
Milan Broz
a3c0f6784b Process LUKS keyslots in userspace through kernel crypto wrapper.
This allow LUKS handling without requiring root privilege.

The dmcrypt device-mapper is used only for device activation now.
2014-06-01 21:34:21 +02:00
Milan Broz
6d4c2db3b1 Fix mode test for nonexisting table. 2014-06-01 20:57:45 +02:00
Milan Broz
1436f2a0a0 Add wrapper for cipher block size query.
There is no better way for now without loading crypto modules.
2014-06-01 20:56:17 +02:00
wagner
e6a46bf827 sync with Wiki version 2014-05-02 08:30:22 +02:00
Milan Broz
9563aa33c8 Fix PBKDF2 for crypto backens which does not support long HMAC keys.
(Or it rehases key in every iteration.)

- Kernel backens seems not to support >20480 HMAC key
- NSS is slow (without proper key reset)

Add some test vectors (commented out by default).
2014-04-13 19:34:50 +02:00
Milan Broz
6225c901fe Use proper images with mentioned hashes in luks test. 2014-04-13 19:34:06 +02:00
Milan Broz
cad0cbf0c8 Fix integer type warnings in debug log. 2014-04-13 16:41:29 +02:00
Milan Broz
1fc441f091 Include images in tarball ans use xz format. 2014-04-13 16:29:21 +02:00
Milan Broz
22849ccd11 Add luks1 compat image testing.
This test use long keyfile to test proper KDF functionality.
2014-04-13 16:21:11 +02:00
Cristian Rodríguez
a809224ec7 Fix all format string issues found by the attribute format patch 2014-04-12 08:52:20 +02:00
Cristian Rodríguez
ae23ecb9b2 annotate two function with __attribute__ ((format (printf...
Helps to find format strings bugs..
2014-04-12 08:52:06 +02:00
Milan Broz
0db77f3ace Update po files. 2014-04-06 18:58:35 +02:00
Milan Broz
779c80c581 Fix some spelling error found by lintian.
Thanks to Jonas Meurer.
2014-03-04 20:27:15 +01:00
wagner
00ced59c1a Sync with Wiki 2014-03-01 14:55:15 +01:00
wagner
20595f4b14 Sync with latest WIKI version of the FAQ 2014-03-01 14:42:12 +01:00
Milan Broz
2e97d8f8e8 Prepare version 1.6.4. 2014-02-27 14:36:13 +01:00
Milan Broz
7effba0f71 Fix return codes from LUKS_set_key. 2014-02-27 14:19:01 +01:00
Milan Broz
2ad69eba90 Verify new passphrase by default in luksChangeKey and luksAddKey. 2014-02-27 13:26:05 +01:00
Milan Broz
4d218e4cbd Update de.po. 2014-02-24 21:57:04 +01:00
Milan Broz
a0346a09ce Update download directory. 2014-02-21 21:44:29 +01:00
Milan Broz
f6e85be3ed Update pl.po. 2014-02-21 21:42:22 +01:00
Milan Broz
04e921846f Update po files. 2014-02-19 19:53:40 +01:00
Milan Broz
e37f3728d7 Add 1.6.4 Release notes. 2014-02-16 10:45:08 +01:00
Milan Broz
2062ece2ab Some new items for TODO list. 2014-02-16 10:15:13 +01:00
Milan Broz
a5fa6f1015 Remove trailing spaces from man pages. 2014-02-16 10:05:39 +01:00
wagner
9bdd5bf4fe clarified hash use for -h and -c in the man-page. 2014-02-13 06:54:58 +01:00
Milan Broz
110ce5607e Update fi.po. 2014-02-08 19:08:26 +01:00
Milan Broz
78f938b0e9 Add old cryptsetup udev rules (for archive reasons).
Do not install these until you know what are you doing.
2014-02-05 17:22:07 +01:00
Milan Broz
ad2f50316f Fix memory leak in Nettle crypto backend. 2014-02-05 17:17:55 +01:00
Milan Broz
cf534f3759 Implement erase command. 2014-02-05 17:17:12 +01:00
Milan Broz
75c105f853 Do not retry to test gcrypt whirlpool bug. 2014-01-21 20:55:21 +01:00
Milan Broz
680eb76e45 Add internal shortcut for flawed whirlpool hash in gcrypt. 2014-01-19 20:31:48 +01:00
Milan Broz
e364041b40 Add --keep-key to cryptsetup-reencrypt.
This allows change of LUKS header hash (and iteration count) without
the need to reencrypt the whole data area.
2014-01-19 15:29:12 +01:00
wagner
de37457a75 sync with Wiki-Version 2014-01-18 20:39:09 +01:00
Milan Broz
057db3b3b3 Do not use gcrypt KDF in 1.6.0, it is slow.
I hope 1.6.1 will have patch included (already in devel).
2014-01-18 13:09:51 +01:00
Milan Broz
461011ad2a Add test for flawed Whirlpool hash to gcrypt backend.
Will be used later, for now add info to debug.
Ref: http://lists.gnupg.org/pipermail/gcrypt-devel/2014-January/002889.html
2014-01-18 13:05:56 +01:00
Milan Broz
aa7346bb36 Allow to use --disable-gcrypt-pbkdf2.
Unfortunately gcrypt PBKDF2 in libgcrypt 1.6.0 is very slow.
Until patch is accepted, let's allow switch back to internal kdf
implementation.

Fixes Issue#199, also see
https://bugzilla.redhat.com/show_bug.cgi?id=1051733
2014-01-15 20:06:12 +01:00
Milan Broz
5206543902 Fix api test keyfile write. 2014-01-12 13:39:15 +01:00
Milan Broz
7f93a49cc3 Support --tries option even for TCRYPT devices in cryptsetup. 2014-01-12 11:37:21 +01:00
Milan Broz
bec86e3d5a Support discard option even for TCRYPT devices. 2014-01-11 22:13:37 +01:00
Axel Lin
3ba95a822f Link against -lrt for clock_gettime
Fix undefined reference to `clock_gettime' error.
This is required since commit f3e398afc5 "Rewrite cipher benchmark loop.".

Below is the build error report:
http://autobuild.buildroot.net/results/9ca/9cad1cf49ee6b5c58d8260ee33beef2e6c1ada4d/build-end.log

Signed-off-by: Axel Lin <axel.lin@ingics.com>
2014-01-01 21:13:09 +01:00
Milan Broz
486ec44c3e Fix previous commit (do not print warning even for wrong passphrase). 2014-01-01 21:11:12 +01:00
Milan Broz
8dc4877697 Fix error message when some algoritmhs are not available.
Fixes http://www.saout.de/pipermail/dm-crypt/2013-December/003721.html
2013-12-29 09:56:23 +01:00
Milan Broz
7415c5858d Count system time in PBKDF2 benchmark if kernel return no self usage info.
This is kind of workaround for Issue#192...
2013-12-22 10:12:36 +01:00
Milan Broz
8e5411f468 Set devel version. 2013-12-14 11:23:10 +01:00
Milan Broz
3bf40bb8dd Add 1.6.3 ChangeLog. 2013-12-13 21:33:53 +01:00
Milan Broz
79956a4d47 Fix skip/offset option description in man page. 2013-12-11 23:22:03 +01:00
Milan Broz
2d755335de Fix previous commit. 2013-12-08 18:15:00 +01:00
Milan Broz
d7762c09dd Add new test images to automake file list. 2013-12-08 18:02:58 +01:00
Milan Broz
957201e758 Fix reencryption tool to work with 4k devices.
See https://bugzilla.redhat.com/show_bug.cgi?id=1029032#c7

Thanks to Ondra Kozina to figure this out.
2013-12-08 17:50:25 +01:00
Milan Broz
004dc271a4 Fix wrong block size if used on 4k block fs through loop device.
Always use page size if running through loop device.
2013-12-08 16:09:25 +01:00
Milan Broz
a9b24ccc82 Remove obsoleted warning. 2013-12-08 00:04:32 +01:00
Milan Broz
c57071a43a Fix TCRYPT system encryption mapping for multiple partitions.
Since this commit, one can use partition directly as device parameter.

Should fix Issue#183 and Issue#188.
2013-12-07 23:58:56 +01:00
Milan Broz
df27f04f61 Update po files. 2013-12-01 10:58:05 +01:00
Milan Broz
f3e398afc5 Rewrite cipher benchmark loop.
Using getrusage seems toi give not adequate precision,
so use clock_gettime and try to scale buffer size a bit
on high performance systems.

If it still fail, return ERANGE error instead calculating
completely unreliable numbers.

Should fix Issue#186.
2013-12-01 10:55:35 +01:00
Milan Broz
65877efe8b Update po files. 2013-11-25 21:26:33 +01:00
Milan Broz
96acd87f0b Update po files. 2013-11-24 17:47:14 +01:00
Milan Broz
fcb35d4e73 Prepare version 1.6.3.
For updating po files (translators).
2013-11-24 12:47:24 +01:00
Ondrej Kozina
0d47e5eb76 Enable reencryption tests using last keyslot 2013-11-21 19:48:17 +01:00
Ondrej Kozina
f30bbbffe7 Fix minimal size expectations failure for backup header file
- backup header file must be page size aligned
- fix for https://bugzilla.redhat.com/show_bug.cgi?id=1030288
- add regression test to api-tests
2013-11-21 19:48:12 +01:00
Ondrej Kozina
6b88461553 modify fips detection also in api-test 2013-11-21 19:48:03 +01:00
Milan Broz
700b558fb6 Fix api test to use proper key size.
LUKS format now reuires correct kernel parameters always,
so validation test must use different but still correct key size.
2013-11-20 22:20:15 +01:00
Milan Broz
58b5be440f Fix initialization of unknown used device.
dm_query can return open count, this should be processed
as success (and properly fail later ;-)
2013-11-19 20:57:23 +01:00
Milan Broz
626801f7df Unify LUKS type check.
Warn if device type is not set (incompatible activation
either by manual dmsetup or other tools).
2013-11-19 20:50:36 +01:00
Ondrej Kozina
77a345d4cb Add tests to reencryption-compat-test
- test --keyslot modification (commit: 5736b0a114)
- test reecryption w/o adding --keyslot option
- use variable instead of static string ("key1" -> KEY1)
- comment one failing test (https://bugzilla.redhat.com/show_bug.cgi?id=1030288)

[gmayland: removed some tests & added -i 1 to save test time]
2013-11-17 21:01:19 +01:00
Dave Reisner
18901fd501 libdevmapper: correctly compare major and minor versions
Previously, this code could incorrectly identify a version of crypt or
dm due to the way it compared versions. For example, if a feature was
gated on crypt version 1.5, it would disable the feature for crypt
version 2.2.
2013-11-14 08:32:02 +01:00
Milan Broz
5b86cb5cc2 Enable TCW dmcrypt version check (patch should be in kernel 3.13). 2013-11-10 22:20:30 +01:00
Milan Broz
ce23225e46 Check if provided cipher and mode is usable before writing LUKS header to disk.
If user provided unusable cipher-mode string, LUKS header was written and
keyslot creation failed later.

Better check early (by creating fake dmcrypt device) if cipher is usable
and fail early (without writing LUKS header to device).

Fixes Issue#176
2013-11-10 22:11:00 +01:00
Milan Broz
09c229fe6c Support limitation for "plain" hash (no hash).
This can be used for mapping problematic cryptosystems which
wipes some key (losetup sometimes set last byte to zero).
2013-11-10 19:31:02 +01:00
Milan Broz
db56125708 Fix hash limiting if parameter is not a number.
If hash lenght specification was not a number, the whole key was set
to zero instead of command failure.

Resolves
https://bugzilla.redhat.com/show_bug.cgi?id=1028362
2013-11-10 19:08:01 +01:00
Ondrej Kozina
5736b0a114 unify --key-slot behavior in cryptsetup_reencrypt
- cryptsetup-reencrypt: unify --key-slot behavior
  across the utility and enable the option even
  without --key-file.

[FIXME: add tests and man page revision]
2013-11-10 18:29:11 +01:00
Ondrej Kozina
a21c0503f8 make FIPS checks compliant with new guidance
(gmazyland: Simplified this NIST nonsense, should be still exactly
equivalent to former patch)
2013-11-10 18:10:39 +01:00
Ondrej Kozina
e52d5f3d98 90reencrypt fixes:
- add loop module to initramfs image
- modprobe loop before reencrypt start
- add rd.luks.reencrypt_keyslot=
- add conflict with dracut crypt module
- drop to emergency_shell after reencryption
2013-11-10 17:38:11 +01:00
Milan Broz
0e96b9d010 Update es.po. 2013-11-10 17:34:39 +01:00
Milan Broz
dcba8c28f2 Update es.po. 2013-10-29 20:37:03 +01:00
Milan Broz
da93a3320b Add commandline option --tcrypt-backup to access TCRYPT backup header. 2013-10-29 20:35:07 +01:00
Milan Broz
53607a0274 Add CBC TCRYPT VFAT id test images and run it by default. 2013-10-26 22:48:05 +02:00
Milan Broz
67d19f3570 Add es.po. 2013-10-26 18:54:12 +02:00
Milan Broz
54c1f71bd3 Detect presence of TCW mode support in kernel dmcrypt. 2013-10-20 13:20:22 +02:00
Milan Broz
a7e2809466 Properly calculate key sizes (inluding IV seed and whitening) for TCRYPT.
Also prepare code for possible activation through dmcrypt for some
CBC container variants.
2013-10-20 13:07:24 +02:00
Milan Broz
3f66e9fe4b Fix error path for DM UUID wrong format. 2013-10-20 13:06:16 +02:00
wagner
f547d0fac3 sunc with wiki version 2013-09-12 17:50:22 +02:00
Milan Broz
cdf272315e Update nl.po. 2013-08-12 08:15:29 +02:00
Milan Broz
31303718da Fix static compilation with OpenSSL.
Resolves issue#172, see
https://bugs.gentoo.org/show_bug.cgi?id=472692
2013-08-08 18:57:45 +02:00
Milan Broz
4192bdd731 Update pl.po. 2013-08-04 20:42:32 +02:00
Milan Broz
c18aa03552 Devel version switch. 2013-08-04 19:45:37 +02:00
Milan Broz
b2283f045a Version 1.6.2. 2013-08-04 19:01:55 +02:00
wagner
8e3863aa20 sync with wiki version 2013-08-02 23:53:22 +02:00
Milan Broz
79899badd0 Update fr.po. 2013-07-31 21:20:14 +02:00
Milan Broz
691b7a63f2 Update po files. 2013-07-30 07:45:12 +02:00
Milan Broz
154731306b Add 1.6.2 release notes.
Remove some TCRYPT comments from man page (FAQ is better for this).
2013-07-27 22:59:40 +02:00
Milan Broz
d67548adfe Fails if more device arguments are present for isLuks.
Fixes
http://code.google.com/p/cryptsetup/issues/detail?id=165
2013-07-27 12:43:48 +02:00
Milan Broz
cfeaaa02fc Fix sscanf cipher string and avoid warning wih -fsanitize=address.
Code need to count terminating zero.
2013-07-23 22:07:13 +02:00
Milan Broz
c5270f85d3 Update de.po. 2013-07-14 11:49:28 +02:00
wagner
45931a890d fixed all items in issue 164
Escaped dashes in options, e.g. \-\-iter-time => \-\-iter\-time
to prevent word-breaks at inner dashes.
2013-07-04 01:03:07 +02:00
wagner
1a5c169c06 Expanded more on protection of hidden TrueCrypt volumes and
its problems.
2013-07-02 03:23:49 +02:00
wagner
d8fbf43022 Added comment that a hidden volume is unprotected against changes
in its outer volume and hence the outer volume should not be mounted.
2013-07-02 03:00:02 +02:00
Milan Broz
3be96efe0b Map TCRYPT system encryption through partition.
Kernel doesn't allow mapping through whle device if some
other partition an the device is used.

So first try to find partition device which match
system encryption (== TCRYPT partition system encryption)
and use that.
2013-06-30 10:46:21 +02:00
Milan Broz
99a2486b09 Simplify sysfs helpers. 2013-06-30 09:05:43 +02:00
Milan Broz
c3c65ee864 Use internally common uint64 parsing for sysfs values. 2013-06-29 13:06:04 +02:00
Milan Broz
db0f5f8d22 Add kernel version to DM debug output. 2013-06-29 11:28:33 +02:00
Milan Broz
8b162ca258 Fix default modes in man page. 2013-06-28 20:39:54 +02:00
Mikulas Patocka
4f990d5a74 dm-verity: Fix a boundary condition that caused failure for certain device sizes
On Fri, 28 Jun 2013, Mikulas Patocka wrote:

Fix a boundary condition that caused failure for certain device sizes

The problem is reported at
http://code.google.com/p/cryptsetup/issues/detail?id=160

This is the userspace fix.

Signed-off-by: Mikulas Patocka <mpatocka@redhat.com
2013-06-28 17:05:45 +02:00
Cristian Rodríguez
1349efa34d Fix buildsytem to always include config.h.
- config.h must always be the first file to be included
- Use AM_CFLAGS and AM_LDFLAGS consistently and properly.

(Modified to disable build without largefile support etc
by Milan Broz <gmazyland@gmail.com>)
2013-06-23 17:14:33 +02:00
Milan Broz
cf99ecb5a9 Force use serial-tests.
Unfortunately, automake did not provided compatible way,
so if anyone need to use old automake, one line change
in is needed.
2013-06-23 16:16:43 +02:00
Milan Broz
0d818d0a92 Copy file in automake, never make symlinks. 2013-06-23 15:37:27 +02:00
Milan Broz
42b0ab437a Print a warning if system encryption is used and device is a partition.
System encryption hav metadata in space located ouside of
partition itself.

Ideally the check should be automatic but for virtualized systems
(where a partition could be "whole device" for another sustem this
can be dangerous.
2013-06-23 15:26:45 +02:00
Milan Broz
a36de633d5 Fix mapping of TCRYPT system encryption for more partitions.
If TCRYPT system encryption uses only partition (not the whole device)
some other partitions could be in use and we have to use
more relaxed check to allow device activation.
2013-06-23 15:24:01 +02:00
Cristian Rodríguez
8a43d49b89 build: test byteswap.h and endian.h for bitops.h
Otherwise the fallback code will be used.
2013-06-03 21:35:56 +02:00
Milan Broz
ae9c9cf369 Disallow explicit small payload offset for detached header.
LUKS detached header has some limitations, one of them
is that you cannot run some explicit check for data offsets
without providing also data device.

Because luksDump and all key handle commands takes only
metadata device (LUKS heaer device), it not easy to properly
support data payload offset validation.

So if detached header is present for luksFormat, code now
allows data payload 0 (IOW whole data device is used)
and explicit offset larger than header+keyslots
(the same as the header is on data device - so some space is wasted).

N.B. with detached header the option --align-payload is used
directly without any round up caculations.

Fixes Issue#155.
2013-05-11 10:59:02 +02:00
wagner
db44c27674 sync with Wiki 2013-04-25 00:08:42 +02:00
Milan Broz
efa2c7b08b Update nl.po. 2013-04-07 09:33:23 +02:00
wagner
a9441043bc sync with wiki version 2013-04-05 11:24:44 +02:00
Milan Broz
aaf0cfa3c1 Set devel version. 2013-03-31 11:59:54 +02:00
102 changed files with 12323 additions and 5683 deletions

View File

@@ -1,3 +1,3 @@
Christophe Saout <christophe@saout.de>
Jana Saout <jana@saout.de>
Clemens Fruhwirth <clemens@endorphin.org>
Milan Broz <gmazyland@gmail.com>

690
FAQ
View File

@@ -23,7 +23,7 @@ A. Contributors
with one master key, anti-forensic features, metadata block at
start of device, ...). The latest version of this FAQ should
usually be available at
http://code.google.com/p/cryptsetup/wiki/FrequentlyAskedQuestions
https://gitlab.com/cryptsetup/cryptsetup/wikis/FrequentlyAskedQuestions
* 1.2 WARNINGS
@@ -41,7 +41,7 @@ A. Contributors
SSDs/FLASH DRIVES: SSDs and Flash are different. Currently it is
unclear how to get LUKS or plain dm-crypt to run on them with the
full set of security features intact. This may or may not be a
problem, depending on the attacher model. See Section 5.19.
problem, depending on the attacker model. See Section 5.19.
BACKUP: Yes, encrypted disks die, just as normal ones do. A full
backup is mandatory, see Section "6. Backup and Data Recovery" on
@@ -64,6 +64,13 @@ A. Contributors
installers after a complete backup of all LUKS containers has been
made.
UBUNTU INSTALLER: In particular the Ubuntu installer seems to be
quite willing to kill LUKS containers in several different ways.
Those responsible at Ubuntu seem not to care very much (it is very
easy to recognize a LUKS container), so treat the process of
installing Ubuntu as a severe hazard to any LUKS container you may
have.
NO WARNING ON NON-INTERACTIVE FORMAT: If you feed cryptsetup from
STDIN (e.g. via GnuPG) on LUKS format, it does not give you the
warning that you are about to format (and e.g. will lose any
@@ -104,8 +111,11 @@ A. Contributors
This issue has been acknowledged by the Ubuntu dev team, see here:
http://launchpad.net/bugs/420080
Update 7/2012: I am unsure whether this has been fixed by now, best
be careful.
Update 4/2013: I am still unsure whether this has been fixed by
now, best be careful. They also seem to have added even more LUKS
killer functionality to the Ubuntu installer. I can only strongly
recommended to not install Ubuntu on a system with existing LUKS
containers without complete backups.
* 1.4 My LUKS-device is broken! Help!
@@ -136,13 +146,17 @@ A. Contributors
* 1.5 Who wrote this?
Current FAQ maintainer is Arno Wagner <arno@wagner.name>. Other
contributors are listed at the end. If you want to contribute, send
your article, including a descriptive headline, to the maintainer,
or the dm-crypt mailing list with something like "FAQ ..." in the
subject. You can also send more raw information and have me write
the section. Please note that by contributing to this FAQ, you
accept the license described below.
Current FAQ maintainer is Arno Wagner <arno@wagner.name>. If you
want to send me encrypted email, my current PGP key is DSA key
CB5D9718, fingerprint 12D6 C03B 1B30 33BB 13CF B774 E35C 5FA1 CB5D
9718.
Other contributors are listed at the end. If you want to contribute,
send your article, including a descriptive headline, to the
maintainer, or the dm-crypt mailing list with something like "FAQ
..." in the subject. You can also send more raw information and
have me write the section. Please note that by contributing to this
FAQ, you accept the license described below.
This work is under the "Attribution-Share Alike 3.0 Unported"
license, which means distribution is unlimited, you may create
@@ -157,14 +171,14 @@ A. Contributors
least problems.
* 1.5 Where is the project website?
* 1.6 Where is the project website?
There is the project website at http://code.google.com/p/cryptsetup/
There is the project website at https://gitlab.com/cryptsetup/cryptsetup/
Please do not post questions there, nobody will read them. Use
the mailing-list instead.
* 1.6 Is there a mailing-list?
* 1.7 Is there a mailing-list?
Instructions on how to subscribe to the mailing-list are at on the
project website. People are generally helpful and friendly on the
@@ -184,7 +198,7 @@ A. Contributors
http://dir.gmane.org/gmane.linux.kernel.device-mapper.dm-crypt
* 1.7 Unsubscribe from the mailing-list
* 1.8 Unsubscribe from the mailing-list
Send mail to dm-crypt-unsubscribe@saout.de from the subscribed
account. You will get an email with instructions.
@@ -254,11 +268,33 @@ A. Contributors
Note that automatic wiping is on the TODO list for cryptsetup, so
at some time in the future this will become unnecessary.
Alternatively, plain cm-crypt can be used for a very fast wipe with
crypto-grade randomness, see Item 2.19
04) Create the LUKS container:
cryptsetup luksFormat <target device>
Just follow the on-screen instructions.
Note: Passphrase iteration is determined by cryptsetup depending on
CPU power. On a slow device, this may be lower than you want. I
recently benchmarked this on a Raspberry Pi and it came out at
about 1/15 of the iteration count for a typical PC. If security is
paramount, you may want to increase the time spent in iteration, at
the cost of a slower unlock later. For the Raspberry Pi, using
cryptsetup luksFormat -i 15000 <target device>
gives you an iteration count and security level equal to an average
PC for passphrase iteration and master-key iteration. If in doubt,
check the iteration counts with
cryptsetup luksDump <target device>
and adjust the iteration count accordingly by creating the container
again with a different iteration time (the number after '-i' is the
iteration time in milicesonds) until your requirements are met.
05) Map the container. Here it will be mapped to /dev/mapper/c1:
cryptsetup luksOpen <target device> c1
@@ -289,7 +325,141 @@ A. Contributors
easy to make, but will compromise your security.
* 2.2 What is the difference between "plain" and LUKS format?
* 2.2 LUKS on partitions or raw disks?
This is a complicated question, and made more so by the availability
of RAID and LVM. I will try to give some scenarios and discuss
advantages and disadvantages. Note that I say LUKS for simplicity,
but you can do all the things described with plain dm-crypt as well.
Also note that your specific scenario may be so special that most
or even all things I say below do not apply.
Be aware that if you add LVM into the mix, things can get very
complicated. Same with RAID but less so. In particular, data
recovery can get exceedingly difficult. Only do so if you have a
really good reason and always remember KISS is what separates an
engineer from an amateur. Of course, if you really need the added
complexity, KISS is satisfied. But be very sure as there is a price
to pay for it. In engineering, complexity is always the enemy and
needs to be fought without mercy when encountered.
Also consider using RAID instead of LVM, as at least with the old
superblock format 0.90, the RAID superblock is in the place (end
of disk) where the risk of it permanently damaging the LUKS header
is smallest and you can have your array assembled by the RAID
controller (i.e. the kernel), as it should be. Use partition type
0xfd for that. I recommend staying away from superblock formats
1.0, 1.1 and 1.2 unless you really need them. Be aware that you
lose autodetection with them and have to fall back to some
user-space script to do it.
Scenarios:
(1) Encrypted partition: Just make a partition to your liking,
and put LUKS on top of it and a filesystem into the LUKS container.
This gives you isolation of differently-tasked data areas, just as
ordinary partitioning does. You can have confidential data,
non-confidential data, data for some specific applications,
user-homes, root, etc. Advantages are simplicity as there is a 1:1
mapping between partitions and filesystems, clear security
functionality and the ability to separate data into different,
independent (!) containers.
Note that you cannot do this for encrypted root, that requires an
initrd. On the other hand, an initrd is about as vulnerable to a
competent attacker as a non-encrypted root, so there really is no
security advantage to doing it that way. An attacker that wants to
compromise your system will just compromise the initrd or the
kernel itself. The better way to deal with this is to make sure the
root partition does not store any critical data and move that to
additional encrypted partitions. If you really are concerned your
root partition may be sabotaged by somebody with physical access
(that would however strangely not, say, sabotage your BIOS,
keyboard, etc.), protect it in some other way. The PC is just not
set-up for a really secure boot-chain (whatever some people may
claim).
(2) Fully encrypted raw block device: For this, put LUKS on the
raw device (e.g. /dev/sdb) and put a filesystem into the LUKS
container, no partitioning whatsoever involved. This is very
suitable for things like external USB disks used for backups or
offline data-storage.
(3) Encrypted RAID: Create your RAID from partitions and/or full
devices. Put LUKS on top of the RAID device, just if it were an
ordinary block device. Applications are just the same as above, but
you get redundancy. (Side note as many people seem to be unaware of
it: You can do RAID1 with an arbitrary number of components in
Linux.) See also Item 2.8.
(4) Now, some people advocate doing the encryption below the RAID
layer. That has several serious problems. One is that suddenly
debugging RAID issues becomes much harder. You cannot do automatic
RAID assembly anymore. You need to keep the encryption keys for the
components in sync or manage them somehow. The only possible
advantage is that things may run a little faster as more CPUs do
the encryption, but if speed is a priority over security and
simplicity, you are doing this wrong anyways. A good way to
mitigate a speed issue is to get a CPU that does hardware AES.
* 2.3 How do I set up encrypted swap?
As things that are confidential can end up in swap (keys,
passphrases, etc. are usually protected against being swapped to
disk, but other things may not be), it may be advisable to do
something about the issue. One option is to run without swap, which
generally works well in a desktop-context. It may cause problems
in a server-setting or under special circumstances. The solution to
that is to encrypt swap with a random key at boot-time.
NOTE: This is for Debian, and should work for Debian-derived
distributions. For others you may have to write your own startup
script or use other mechanisms.
01) Add the swap partition to /etc/crypttab. A line like the following
should do it:
swap /dev/<partition> /dev/urandom swap,noearly
Warning: While Debian refuses to overwrite partitions with a
filesystem or RAID signature on it, if your disk IDs may change
(adding or removing disks, failure of disk during boot, etc.), you
may want to take additional precautions. Yes, this means that your
kernel device names like sda, sdb, ... can change between reboots!
This is not a concern if you have only one disk. One possibility is
to make sure the partition number is not present on additional
disks or also swap there. Another is to encapsulate the swap
partition (by making it a 1-disk RAID1 or by using LVM), so that it
gets a persistent identifier. Specifying it directly by UUID does
not work, unfortunately, as the UUID is part of the swap signature
and that is not visible from the outside due to the encryption and
in addition changes on each reboot with this setup.
Note: Use /dev/random if you are paranoid or in a potential
low-entropy situation (embedded system, etc.). This may cause the
operation to take a long time during boot. If you are in a "no
entropy" situation, you cannot encrypt swap securely. In this
situation you should find some entropy, also because nothing else
using crypto will be secure, like ssh, ssl or GnuPG.
Note: The "noearly" option makes sure things like LVM, RAID, etc.
are running. As swap is non-critical for boot, it is fine to start
it late.
02) Add the swap partition to /etc/fstab. A line like the following
should do it:
/dev/mapper/swap none swap sw 0 0
That is it. Reboot or start it manually to activate encrypted swap.
Manual start would look like this:
/etc/init.d/crypdisks start
swapon /dev/mapper/swap
* 2.4 What is the difference between "plain" and LUKS format?
First, unless you happen to understand the cryptographic background
well, you should use LUKS. It does protect the user from a lot of
@@ -309,13 +479,24 @@ A. Contributors
Side-note: That has limited value against the authorities. In
civilized countries, they cannot force you to give up a crypto-key
anyways. In the US, the UK and dictatorships around the world,
they can force you to give up the keys (using imprisonment or worse
to pressure you), and in the worst case, they only need a
nebulous "suspicion" about the presence of encrypted data. My
advice is to either be ready to give up the keys or to not have
anyways. In quite a few countries around the world, they can force
you to give up the keys (using imprisonment or worse to pressure
you, sometimes without due process), and in the worst case, they
only need a nebulous "suspicion" about the presence of encrypted
data. Sometimes this applies to everybody, sometimes only when you
are suspected of having "illicit data" (definition subject to
change) and sometimes specifically when crossing a border. Note
that this is going on in countries like the US and the UK, to
different degrees and sometimes with courts restricting what the
authorities can actually demand.
My advice is to either be ready to give up the keys or to not have
encrypted data when traveling to those countries, especially when
crossing the borders.
crossing the borders. The latter also means not having any
high-entropy (random) data areas on your disk, unless you can
explain them and demonstrate that explanation. Hence doing a
zero-wipe of all free space, including unused space, may be a good
idea.
Disadvantages are that you do not have all the nice features that
the LUKS metadata offers, like multiple passphrases that can be
@@ -343,7 +524,7 @@ A. Contributors
non-default XTS mode).
* 2.3 Can I encrypt an already existing, non-empty partition to use
* 2.5 Can I encrypt an already existing, non-empty partition to use
LUKS?
There is no converter, and it is not really needed. The way to do
@@ -358,7 +539,7 @@ A. Contributors
to be in a filesystem.
* 2.4 How do I use LUKS with a loop-device?
* 2.6 How do I use LUKS with a loop-device?
This can be very handy for experiments. Setup is just the same as
with any block device. If you want, for example, to use a 100MiB
@@ -372,7 +553,7 @@ A. Contributors
To unmap the file when done, use "losetup -d /dev/loop0".
* 2.5 When I add a new key-slot to LUKS, it asks for a passphrase but
* 2.7 When I add a new key-slot to LUKS, it asks for a passphrase but
then complains about there not being a key-slot with that
passphrase?
@@ -384,7 +565,7 @@ A. Contributors
new key-slot.
* 2.6 Encryption on top of RAID or the other way round?
* 2.8 Encryption on top of RAID or the other way round?
Unless you have special needs, place encryption between RAID and
filesystem, i.e. encryption on top of RAID. You can do it the other
@@ -393,16 +574,39 @@ A. Contributors
not work anymore. Therefore it is better to encrypt the RAID
device, e.g. /dev/dm0 .
This means that the typical layering looks like this:
* 2.7 How do I read a dm-crypt key from file?
Filesystem <- top
|
Encryption
|
RAID
|
Raw partitions
|
Raw disks <- bottom
The big advantage is that you can manage the RAID container just
like any RAID container, it does not care that what is in it is
encrypted.
Note that the file will still be hashed first, just like keyboard
input. Use the --key-file option, like this:
* 2.9 How do I read a dm-crypt key from file?
Use the --key-file option, like this:
cryptsetup create --key-file keyfile e1 /dev/loop0
This will read the binary key from file, i.e. no hashing or
transformation will be applied to the keyfile before its bits are
used as key. Extra bits (beyond the length of the key) at the end
are ignored. Note that if you read from STDIN, the data will still
be hashed, just as a key read interactively from the terminal. See
the man-page sections "NOTES ON PASSPHRASE PROCESSING..." for more
detail.
* 2.8 How do I read a LUKS slot key from file?
* 2.10 How do I read a LUKS slot key from file?
What you really do here is to read a passphrase from file, just as
you would with manual entry of a passphrase for a key-slot. You can
@@ -428,7 +632,7 @@ A. Contributors
cryptsetup luksOpen --key-file keyfile /dev/loop0 e1
* 2.9 How do I read the LUKS master key from file?
* 2.11 How do I read the LUKS master key from file?
The question you should ask yourself first is why you would want to
do this. The only legitimate reason I can think of is if you want
@@ -439,7 +643,7 @@ A. Contributors
do this here.
* 2.10 What are the security requirements for a key read from file?
* 2.12 What are the security requirements for a key read from file?
A file-stored key or passphrase has the same security requirements
as one entered interactively, however you can use random bytes and
@@ -451,7 +655,7 @@ A. Contributors
head -c 256 /dev/random > keyfile
* 2.11 If I map a journaled file system using dm-crypt/LUKS, does it
* 2.13 If I map a journaled file system using dm-crypt/LUKS, does it
still provide its usual transactional guarantees?
Yes, it does, unless a very old kernel is used. The required flags
@@ -479,7 +683,7 @@ A. Contributors
should improve further and eventually the problem should go away.
* 2.12 Can I use LUKS or cryptsetup with a more secure (external)
* 2.14 Can I use LUKS or cryptsetup with a more secure (external)
medium for key storage, e.g. TPM or a smartcard?
Yes, see the answers on using a file-supplied key. You do have to
@@ -488,8 +692,12 @@ A. Contributors
own tool that in turn gets the key from the more secure key
storage.
For TPM support, you may want to have a look at tpm-luks at
https://github.com/shpedoikal/tpm-luks. Note that tpm-luks is not
related to the cryptsetup project.
* 2.13 Can I resize a dm-crypt or LUKS partition?
* 2.15 Can I resize a dm-crypt or LUKS partition?
Yes, you can, as neither dm-crypt nor LUKS stores partition size.
Whether you should is a different question. Personally I recommend
@@ -509,7 +717,7 @@ A. Contributors
for that.
* 2.14 How do I Benchmark the Ciphers, Hashes and Modes?
* 2.16 How do I Benchmark the Ciphers, Hashes and Modes?
Since version 1.60 cryptsetup supports the "benchmark" command.
Simply run as root:
@@ -525,6 +733,76 @@ A. Contributors
and half of it is the cipher key, the other half is the XTS key.
* 2.17 How do I Verify I have an Authentic cryptsetup Source Package?
Current maintainer is Milan Broz and he signs the release packages
with his PGP key. The key he currently uses is the "RSA key ID
D93E98FC", fingerprint 2A29 1824 3FDE 4664 8D06 86F9 D9B0 577B
D93E 98FC. While I have every confidence this really is his key and
that he is who he claims to be, don't depend on it if your life is
at stake. For that matter, if your life is at stake, don't depend
on me being who I claim to be either.
That said, as cryptsetup is under good version control, a malicious
change should be noticed sooner or later, but it may take a while.
Also, the attacker model makes compromising the sources in a
non-obvious way pretty hard. Sure, you could put the master-key
somewhere on disk, but that is rather obvious as soon as somebody
looks as there would be data in an empty LUKS container in a place
it should not be. Doing this in a more nefarious way, for example
hiding the master-key in the salts, would need a look at the
sources to be discovered, but I think that somebody would find that
sooner or later as well.
That said, this discussion is really a lot more complicated and
longer as an FAQ can sustain. If in doubt, ask on the mailing list.
* 2.18 Is there a concern with 4k Sectors?
Not from dm-crypt itself. Encryption will be done in 512B blocks,
but if the partition and filesystem are aligned correctly and the
filesystem uses multiples of 4kiB as block size, the dm-crypt layer
will just process 8 x 512B = 4096B at a time with negligible
overhead. LUKS does place data at an offset, which is 2MiB per
default and will not break alignment. See also Item 6.12 of this
FAQ for more details. Note that if your partition or filesystem is
misaligned, dm-crypt can make the effect worse though.
* 2.19 How can I wipe a device with crypto-grade randomness?
The conventional recommendation if you want to not just do a
zero-wipe is to use something like
cat /dev/urandom > <taget-device>
That is very slow and painful at 10-20MB/s on a fast computer.
Using cryptsetup and a plain dm-crypt device with a random key, it
is much faster and gives you the same level of security. The
defaults are quite enough.
For device set-up, do the following:
cryptsetup open --type plain -d /dev/urandom /dev/<block-device> to_be_wiped
Then you have several options. Simple wipe without
progress-indicator:
cat /dev/zero > /dev/mapper/to_be_wiped
Progress-indicator by dd_rescue:
dd_rescue -w /dev/zero /dev/mapper/to_be_wiped
Progress-indicator by my "wcs" stream meter (available from
http://www.tansi.org/tools/index.html ):
cat /dev/zero | wcs > /dev/mapper/to_be_wiped
Remove the mapping at the end and you are done.
3. Common Problems
@@ -633,7 +911,38 @@ A. Contributors
diagnosing and (if still possible) repairing this.
* 4.2 Can a bad RAM module cause problems?
* 4.2 I cannot unlock my LUKS container! What could be the problem?
First, make sure you have a correct passphrase. Then make sure you
have the correct key-map and correct keyboard. And then make sure
you have the correct character set and encoding, see also
"PASSPHRASE CHARACTER SET" under Section 1.2.
If you are sure you are entering the passphrase right, there is the
possibility that the respective key-slot has been damaged. There
is no way to recover a damaged key-slot, except from a header
backup (see Section 6). For security reasons, there is also no
checksum in the key-slots that could tell you whether a key-slot has
been damaged. The only checksum present allows recognition of a
correct passphrase, but that only works if the passphrase is
correct and the respective key-slot is intact.
In order to find out whether a key-slot is damaged one has to look
for "non-random looking" data in it. There is a tool that
automatizes this in the cryptsetup distribution from version 1.6.0
onwards. It is located in misc/keyslot_checker/. Instructions how
to use and how to interpret results are in the README file. Note
that this tool requires a libcryptsetup from cryptsetup 1.6.0 or
later (which means libcryptsetup.so.4.5.0 or later). If the tool
complains about missing functions in libcryptsetup, you likely
have an earlier version from your distribution still installed. You
can either point the symbolic link(s) from libcryptsetup.so.4 to
the new version manually, or you can uninstall the distribution
version of cryptsetup and re-install that from cryptsetup >= 1.6.0
again to fix this.
* 4.3 Can a bad RAM module cause problems?
LUKS and dm-crypt can give the RAM quite a workout, especially when
combined with software RAID. In particular the combination RAID5 +
@@ -675,7 +984,7 @@ A. Contributors
did a verify.
* 4.3 How do I test RAM?
* 4.4 How do I test RAM?
First you should know that overclocking often makes memory
problems worse. So if you overclock (which I strongly recommend
@@ -749,8 +1058,8 @@ A. Contributors
is easier than it actually is is fine. An attacker may still have
vastly higher cost than estimated here.
LUKS uses SHA1 for hasing per default. The claim in the reference is
63 billion tries/second for SHA1. We will leave aside the check
LUKS uses SHA1 for hashing per default. The claim in the reference
is 63 billion tries/second for SHA1. We will leave aside the check
whether a try actually decrypts a key-slot. Now, the machine has 25
GPUs, which I will estimate at an overall lifetime cost of USD/EUR
1000 each, and an useful lifetime of 2 years. (This is on the low
@@ -929,9 +1238,9 @@ A. Contributors
new filesystem on the raw LUKS partition, making the raw partition
part of a raid array and just writing to the raw partition.
The LUKS header contains a 256 bit "salt" value and without that no
decryption is possible. While the salt is not secret, it is
key-grade material and cannot be reconstructed. This is a
The LUKS header contains a 256 bit "salt" per key-slot and without
that no decryption is possible. While the salts are not secret,
they are key-grade material and cannot be reconstructed. This is a
cryptographically strong "cannot". From observations on the
cryptsetup mailing-list, people typically go though the usual
stages of grief (Denial, Anger, Bargaining, Depression, Acceptance)
@@ -940,12 +1249,13 @@ A. Contributors
fine. Even if we usually cannot help with getting back your data,
most people found the feedback comforting.
If your header does not contain an intact salt, best go directly
to the last stage ("Acceptance") and think about what to do now.
There is one exception that I know of: If your LUKS container is
still open, then it may be possible to extract the master key from
the running system. See Item "How do I recover the master key from
a mapped LUKS container?" in Section "Backup and Data Recovery".
If your header does not contain an intact key-slot salt, best go
directly to the last stage ("Acceptance") and think about what to
do now. There is one exception that I know of: If your LUKS
container is still open, then it may be possible to extract the
master key from the running system. See Item "How do I recover the
master key from a mapped LUKS container?" in Section "Backup and
Data Recovery".
* 5.8 What is a "salt"?
@@ -1197,7 +1507,9 @@ A. Contributors
XTS mode is potentially even more secure than cbc-essiv (but only if
cbc-essiv is insecure in your scenario). It is a NIST standard and
used, e.g. in Truecrypt. At the moment, if you want to use it, you
used, e.g. in Truecrypt. From version 1.6.0 of cryptsetup onwards,
aes-xts-plain64 is the default for LUKS. If you want to use it
with a cryptsetup before version 1.6.0 or with plain dm-crypt, you
have to specify it manually as "aes-xts-plain", i.e.
cryptsetup -c aes-xts-plain luksFormat <device>
@@ -1288,7 +1600,7 @@ A. Contributors
foot, you can figure out how to do it yourself.
* 5.19 What about SSDs or Flash Drives?
* 5.19 What about SSDs, Flash and Hybrid Drives?
The problem is that you cannot reliably erase parts of these
devices, mainly due to wear-leveling and possibly defect
@@ -1302,7 +1614,7 @@ A. Contributors
done in some fashion so that larger writes do not cause a lot of
small internal updates.
The thing is that the mappings between outside-adressable sectors
The thing is that the mappings between outside-addressable sectors
and inside sectors is arbitrary (and the vendors are not talking).
Also the discarded sectors are not necessarily erased immediately.
They may linger a long time.
@@ -1331,28 +1643,107 @@ A. Contributors
If you trust the device vendor (you probably should not...) you can
try an ATA "secure erase" command for SSDs. That does not work for
USB keys though. And if it finishes after a few seconds, it was
possibly faked by the SSD.
USB keys though and may or may not be secure for a hybrid drive. If
it finishes on an SSD after a few seconds, it was possibly faked.
Unfortunately, for hybrid drives that indicator does not work, as
the drive may well take the time to truly erase the magnetic part,
but only mark the SSD/Flash part as erased while data is still in
there.
If you can do without password management and are fine with doing
physical destruction for permenently deleting data (allways after
physical destruction for permanently deleting data (always after
one or several full overwrites!), you can use plain dm-crypt or
LUKS.
If you want or need the original LUKS security features to work,
If you want or need all the original LUKS security features to work,
you can use a detached LUKS header and put that on a conventional,
magnetic disk. That leaves potentially old encrypted data in the
pools on the disk, but otherwise you get LUKS with the same
security as on a magnetic disk.
If you are concerned about your laptop being stolen, you are likely
fine using LUKS on an SSD. An attacker would need to have access
to an old passphrase (and the key-slot for this old passphrase
would actually need to still be somewhere in the SSD) for your
data to be at risk. So unless you pasted your old passphrase all
over the Internet or the attacker has knowledge of it from some
other source and does a targetted laptop theft to get at your
data, you should be fine.
fine using LUKS on an SSD or hybrid drive. An attacker would need
to have access to an old passphrase (and the key-slot for this old
passphrase would actually need to still be somewhere in the SSD)
for your data to be at risk. So unless you pasted your old
passphrase all over the Internet or the attacker has knowledge of
it from some other source and does a targeted laptop theft to get
at your data, you should be fine.
* 5.20 LUKS is broken! It uses SHA-1!
No, it is not. SHA-1 is (academically) broken for finding
collisions, but not for using it in a key-derivation function. And
that collision vulnerability is for non-iterated use only. And you
need the hash-value in verbatim.
This basically means that if you already have a slot-key, and you
have set the PBKDF2 iteration count to 1 (it is > 10'000 normally),
you could (maybe) derive a different passphrase that gives you the
the same slot-key. But if you have the slot-key, you can already
unlock the key-slot and get the master key, breaking everything. So
basically, this SHA-1 vulnerability allows you to open a LUKS
container with high effort when you already have it open.
The real problem here is people that do not understand crypto and
claim things are broken just because some mechanism is used that
has been broken for a specific different use. The way the mechanism
is used matters very much. A hash that is broken for one use can be
completely secure for other uses and here it is.
* 5.21 Why is there no "Nuke-Option"?
A "Nuke-Option" or "Kill-switch" is a password that when entered
upon unlocking instead wipes the header and all passwords. So when
somebody forces you to enter your password, you can destroy the
data instead.
While this sounds attractive at first glance, it does not make sense
once a real security analysis is done. One problem is that you have
to have some kind of HSM (Hardware Security Module) in order to
implement it securely. In the movies, a HSM starts to smoke and
melt once the Nuke-Option has been activated. In reality, it just
wipes some battery-backed RAM cells. A proper HSM costs something
like 20'000...100'000 EUR/USD and there a Nuke-Option may make some
sense. BTW, a chipcard or a TPM is not a HSM, although some
vendors are promoting that myth.
Now, a proper HSMs will have a wipe option but not a Nuke-Option,
i.e. you can explicitly wipe the HSM, but by a different process
than unlocking it takes. Why is that? Simple: If somebody can force
you to reveal passwords, then they can also do bad things to you if
you do not or if you enter a nuke password instead. Think locking
you up for a few years for "destroying evidence" or for far longer
and without trial for being a "terrorist suspect". No HSM maker
will want to expose its customers to that risk.
Now think of the typical LUKS application scenario, i.e. disk
encryption. Usually the ones forcing you to hand over your password
will have access to the disk as well, and, if they have any real
suspicion, they will mirror your disk before entering anything
supplied by you. This neatly negates any Nuke-Option. If they have
no suspicion (just harassing people that cross some border for
example), the Nuke-Option would work, but see above about likely
negative consequences and remember that a Nuke-Option may not work
reliably on SSD and hybrid drives anyways.
Hence my advice is to never take data that you do not want to reveal
into any such situation in the first place. There is no need to
transfer data on physical carriers today. The Internet makes it
quite possible to transfer data between arbitrary places and modern
encryption makes it secure. If you do it right, nobody will even be
able to identify source or destination. (How to do that is out of
scope of this document. It does require advanced skills in this age
of pervasive surveillance.)
Hence, LUKS has not kill option because it would do much more harm
than good.
Still, if you have a good use-case (i.e. non-abstract real-world
situation) where a Nuke-Option would actually be beneficial, please
let me know.
6. Backup and Data Recovery
@@ -1393,6 +1784,16 @@ A. Contributors
cryptsetup luksHeaderRestore --header-backup-file <file> <device>
If you are unsure about a header to be restored, make a backup of
the current one first! You can also test the header-file without
restoring it by using the --header option for a detached header
like this:
cryptsetup --header <file> luksOpen <device> </dev/mapper/ -name>
If that unlocks your keys-lot, you are good. Do not forget to close
the device again.
* 6.3 How do I test a LUKS header?
@@ -1443,7 +1844,16 @@ A. Contributors
cat backup.tbz2.gpg | gpg - | tar djf -
Note: Always verify backups, especially encrypted ones.
Note: Always verify backups, especially encrypted ones!
There is one problem with verifying like this: The kernel may still
have some files cached and in fact verify them against RAM or may
even verify RAM against RAM, which defeats the purpose of the
exercise. The following command empties the kernel caches:
echo 3 > /proc/sys/vm/drop_caches
Run it after backup and before verify.
In both cases GnuPG will ask you interactively for your symmetric
key. The verify will only output errors. Use "tar dvjf -" to get
@@ -1451,6 +1861,13 @@ A. Contributors
unencrypted, turn off swap if it is not encrypted before doing the
backup.
Restore works like certification with the 'd' ('difference')
replaced by 'x' ('eXtract'). Refer to the man-page of tar for more
explanations and instructions. Note that with default options tar
will overwrite already existing files without warning. If you are
unsure about how to use tar, experiment with it in a location
where you cannot do damage.
You can of course use different or no compression and you can use
an asymmetric key if you have one and have a backup of the secret
key that belongs to it.
@@ -1534,14 +1951,15 @@ A. Contributors
damage the LUKS header or key-slots?
There are two critical components for decryption: The salt values
in the header itself and the key-slots. If the salt values are
overwritten or changed, nothing (in the cryptographically strong
sense) can be done to access the data, unless there is a backup
of the LUKS header. If a key-slot is damaged, the data can still
be read with a different key-slot, if there is a remaining
undamaged and used key-slot. Note that in order to make a key-slot
unrecoverable in a cryptographically strong sense, changing about
4-6 bits in random locations of its 128kiB size is quite enough.
in the key-slot descriptors of the header and the key-slots. If the
salt values are overwritten or changed, nothing (in the
cryptographically strong sense) can be done to access the data,
unless there is a backup of the LUKS header. If a key-slot is
damaged, the data can still be read with a different key-slot, if
there is a remaining undamaged and used key-slot. Note that in
order to make a key-slot unrecoverable in a cryptographically
strong sense, changing about 4-6 bits in random locations of its
128kiB size is quite enough.
* 6.9 What happens if I (quick) format a LUKS partition?
@@ -1575,7 +1993,7 @@ A. Contributors
process, except generating a new LUKS header with the old master
key (it prints the command for that though):
http://code.google.com/p/cryptsetup/source/browse/misc/luks-header-from-active
https://gitlab.com/cryptsetup/cryptsetup/blob/master/misc/luks-header-from-active
You can also do this manually. Here is how:
@@ -1633,7 +2051,7 @@ http://code.google.com/p/cryptsetup/source/browse/misc/luks-header-from-active
change the password, you basically have to create a second
encrypted device with the new passphrase and copy your data over.
On the plus side, if you accidentally overwrite any part of a
dm-crypt device, the damage will be limited to the are you
dm-crypt device, the damage will be limited to the area you
overwrote.
@@ -1673,8 +2091,69 @@ http://code.google.com/p/cryptsetup/source/browse/misc/luks-header-from-active
bulk data at 0x200000.
The exact specification of the format is here:
http://code.google.com/p/cryptsetup/wiki/Specification
https://gitlab.com/cryptsetup/cryptsetup/wikis/Specification
For your convenience, here is the LUKS header with hex offsets.
NOTE: The spec counts key-slots from 1 to 8, but the cryptsetup
tool counts from 0 to 7. The numbers here refer to the cryptsetup
numbers.
Refers to LUKS On-Disk Format Specification Version 1.2.1
LUKS header:
offset length name data type description
-----------------------------------------------------------------------
0x0000 0x06 magic byte[] 'L','U','K','S', 0xba, 0xbe
0 6
0x0006 0x02 version uint16_t LUKS version
6 3
0x0008 0x20 cipher-name char[] cipher name spec.
8 32
0x0028 0x20 cipher-mode char[] cipher mode spec.
40 32
0x0048 0x20 hash-spec char[] hash spec.
72 32
0x0068 0x04 payload-offset uint32_t bulk data offset in sectors
104 4 (512 bytes per sector)
0x006c 0x04 key-bytes uint32_t number of bytes in key
108 4
0x0070 0x14 mk-digest byte[] master key checksum
112 20 calculated with PBKDF2
0x0084 0x20 mk-digest-salt byte[] salt for PBKDF2 when
132 32 calculating mk-digest
0x00a4 0x04 mk-digest-iter uint32_t iteration count for PBKDF2
164 4 when calculating mk-digest
0x00a8 0x28 uuid char[] partition UUID
168 40
0x00d0 0x30 key-slot-0 key slot key slot 0
208 48
0x0100 0x30 key-slot-1 key slot key slot 1
256 48
0x0130 0x30 key-slot-2 key slot key slot 2
304 48
0x0160 0x30 key-slot-3 key slot key slot 3
352 48
0x0190 0x30 key-slot-4 key slot key slot 4
400 48
0x01c0 0x30 key-slot-5 key slot key slot 5
448 48
0x01f0 0x30 key-slot-6 key slot key slot 6
496 48
0x0220 0x30 key-slot-7 key slot key slot 7
544 48
Key slot:
offset length name data type description
-------------------------------------------------------------------------
0x0000 0x04 active uint32_t key slot enabled/disabled
0 4
0x0004 0x04 iterations uint32_t PBKDF2 iteration count
4 4
0x0008 0x20 salt byte[] PBKDF2 salt
8 32
0x0028 0x04 key-material-offset uint32_t key start sector
40 4 (512 bytes/sector)
0x002c 0x04 stripes uint32_t number of anti-forensic
44 4 stripes
* 6.13 What is the smallest possible LUKS container?
@@ -1881,10 +2360,10 @@ http://code.google.com/p/cryptsetup/source/browse/misc/luks-header-from-active
accessible anymore!
With cryptsetup 1.1.x, the distro maintainer can define different
default encryption modes for LUKS and plain devices. You can check
these compiled-in defaults using "cryptsetup --help". Moreover, the
plain device default changed because the old IV mode was
vulnerable to a watermarking attack.
default encryption modes. You can check the compiled-in defaults
using "cryptsetup --help". Moreover, the plain device default
changed because the old IV mode was vulnerable to a watermarking
attack.
If you are using a plain device and you need a compatible mode, just
specify cipher, key size and hash algorithm explicitly. For
@@ -1905,6 +2384,56 @@ http://code.google.com/p/cryptsetup/source/browse/misc/luks-header-from-active
not be used anymore as well. My advice would be to drop SLED 10.
* 8.3 Gcrypt after 1.5.3 breaks Whirlpool
It is the other way round: In gcrypt 1.5.3 and before Whirlpool is
broken and it was fixed in the next version. If you selected
whirlpool as hash on creation of a LUKS container, it does not work
anymore with the fixed library. This shows one serious risk of
using rarely used settings.
The only two ways to deal with this are either to decrypt with an
old gcrypt version that has the flaw or to use a compatibility
feature introduced in cryptsetup 1.6.4 and gcrypt 1.6.1 or later.
Versions of gcrypt between 1.5.4 and 1.6.0 cannot be used.
Steps:
- Make a least a header backup or better, refresh your full
backup. (You have a full backup, right? See Item 6.1 and
following.)
- Make sure you have cryptsetup 1.6.4 or later and check the gcrypt
version:
cryptsetup luksDump <your luks device> --debug | grep backend
If gcrypt is at version 1.5.3 or before:
- Reencrypt the LUKS header with a different hash. (Requires
entering all keyslot passphrases. If you do not have all, remove
the ones you do not have before.):
cryptsetup-reencrypt --keep-key --hash sha256 <your luks device>
If gcrypt is at version 1.6.1 or later:
- Patch the hash name in the LUKS header from "whirlpool" to
"whirlpool_gcryptbug". This activates the broken implementation.
The detailed header layout is in Item 6.12 of this FAQ and in the
LUKS on-disk format specification. One way to change the hash is
with the following command:
echo -n -e 'whirlpool_gcryptbug\0' | dd of=<luks device> bs=1 seek=72 conv=notrunc
- You can now open the device again. It is highly advisable to
change the hash now with cryptsetup-reencrypt as described above.
While you can reencrypt to use the fixed whirlpool, that may not
be a good idea as almost nobody seems to use it and hence the long
time until the bug was discovered.
9. References and Further Reading
@@ -1929,8 +2458,7 @@ http://code.google.com/p/cryptsetup/source/browse/misc/luks-header-from-active
* Specifications
- LUKS on-disk format spec:
http://code.google.com/p/cryptsetup/wiki/Specification
https://gitlab.com/cryptsetup/cryptsetup/wikis/Specification
* Code Examples

10
README
View File

@@ -5,11 +5,11 @@ setup cryptographic volumes for dm-crypt (including LUKS extension)
WEB PAGE:
http://code.google.com/p/cryptsetup/
https://gitlab.com/cryptsetup/cryptsetup/
FAQ:
http://code.google.com/p/cryptsetup/wiki/FrequentlyAskedQuestions
https://gitlab.com/cryptsetup/cryptsetup/wikis/FrequentlyAskedQuestions
MAILING LIST:
@@ -18,12 +18,12 @@ MAILING LIST:
DOWNLOAD:
http://code.google.com/p/cryptsetup/downloads/
https://www.kernel.org/pub/linux/utils/cryptsetup/
SOURCE CODE:
URL: http://code.google.com/p/cryptsetup/source/browse/
Checkout: git clone https://code.google.com/p/cryptsetup/
URL: https://gitlab.com/cryptsetup/cryptsetup/tree/master
Checkout: git clone https://gitlab.com/cryptsetup/cryptsetup.git
NLS (PO TRANSLATIONS):

70
README.md Normal file
View File

@@ -0,0 +1,70 @@
![LUKS logo](https://gitlab.com/cryptsetup/cryptsetup/wikis/luks-logo.png)
What the ...?
=============
**Cryptsetup** is utility used to conveniently setup disk encryption based
on [DMCrypt](https://gitlab.com/cryptsetup/cryptsetup/wikis/DMCrypt) kernel module.
These include **plain** **dm-crypt** volumes, **LUKS** volumes, **loop-AES**
and **TrueCrypt** (including **VeraCrypt** extension) format.
Project also includes **veritysetup** utility used to conveniently setup
[DMVerity](https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity) block integrity checking kernel module.
LUKS Design
-----------
**LUKS** is the standard for Linux hard disk encryption. By providing a standard on-disk-format, it does not
only facilitate compatibility among distributions, but also provides secure management of multiple user passwords.
In contrast to existing solution, LUKS stores all setup necessary setup information in the partition header,
enabling the user to transport or migrate his data seamlessly.
Why LUKS?
---------
* compatiblity via standardization,
* secure against low entropy attacks,
* support for multiple keys,
* effective passphrase revocation,
* free.
[Project home page](https://gitlab.com/cryptsetup/cryptsetup/).
-----------------
[Frequently asked questions (FAQ)](https://gitlab.com/cryptsetup/cryptsetup/wikis/FrequentlyAskedQuestions)
--------------------------------
Download
--------
All release tarballs and release notes are hosted on [kernel.org](https://www.kernel.org/pub/linux/utils/cryptsetup/).
**The latest cryptsetup version is 1.6.6**
* [cryptsetup-1.6.6.tar.xz](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.6/cryptsetup-1.6.6.tar.xz)
* Signature [cryptsetup-1.6.6.tar.sign](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.6/cryptsetup-1.6.6.tar.sign)
_(You need to decompress file first to check signature.)_
* [Cryptsetup 1.6.6 Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.6/v1.6.6-ReleaseNotes).
Previous versions
* [Version 1.6.5](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.6/cryptsetup-1.6.5.tar.xz) -
[Signature](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.6/cryptsetup-1.6.5.tar.sign) -
[Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.6/v1.6.5-ReleaseNotes).
* [Version 1.6.4](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.6/cryptsetup-1.6.4.tar.xz) -
[Signature](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.6/cryptsetup-1.6.4.tar.sign) -
[Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.6/v1.6.4-ReleaseNotes).
Source and API docs
-------------------
For development version code, please refer to [source](https://gitlab.com/cryptsetup/cryptsetup/tree/master) page,
mirror on [kernel.org](https://git.kernel.org/cgit/utils/cryptsetup/cryptsetup.git/) or [GitHub](https://github.com/mbroz/cryptsetup).
For libcryptsetup documentation see [libcryptsetup API](https://gitlab.com/cryptsetup/cryptsetup/wikis/API/index.html) page.
NLS PO files are maintained by [TranslationProject](http://translationproject.org/domain/cryptsetup.html).
Help!
-----
Please always read [FAQ](https://gitlab.com/cryptsetup/cryptsetup/wikis/FrequentlyAskedQuestions) first.
For cryptsetup and LUKS related questions, please use the dm-crypt mailing list, [dm-crypt@saout.de](mailto:dm-crypt@saout.de).
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](http://news.gmane.org/gmane.linux.kernel.device-mapper.dm-crypt).

4
TODO
View File

@@ -4,5 +4,5 @@ Version 1.7:
- TRIM for keyslots
- Do we need crypt_data_path() - path to data device (if differs)?
- Resync ETA time is not accurate, calculate it better (last minute window?).
- Crypt benchmark cannot ttest ECB mode.
- Log doesn't work yet in early binary start (FIPS message).
- Extend existing LUKS header to use another KDF? (https://password-hashing.net/)
- Fix all crazy automake warnings (or switch to Cmake).

View File

@@ -78,7 +78,7 @@ autopoint --force $AP_OPTS
libtoolize --force --copy
aclocal -I m4 $AL_OPTS
autoheader $AH_OPTS
automake --add-missing --gnu $AM_OPTS
automake --add-missing --copy --gnu $AM_OPTS
autoconf $AC_OPTS
if test x$NOCONFIGURE = x; then

View File

@@ -1,17 +1,22 @@
AC_PREREQ([2.67])
AC_INIT([cryptsetup],[1.6.1])
AC_INIT([cryptsetup],[1.6.7])
dnl library version from <major>.<minor>.<release>[-<suffix>]
LIBCRYPTSETUP_VERSION=$(echo $PACKAGE_VERSION | cut -f1 -d-)
LIBCRYPTSETUP_VERSION_INFO=9:0:5
dnl library file name for FIPS selfcheck
LIBCRYPTSETUP_VERSION_FIPS="libcryptsetup.so.4"
LIBCRYPTSETUP_VERSION_INFO=11:0:7
AM_SILENT_RULES([yes])
AC_CONFIG_SRCDIR(src/cryptsetup.c)
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_HEADERS([config.h:config.h.in])
AM_INIT_AUTOMAKE(dist-bzip2)
# We do not want to run test in parallel. Really.
# http://lists.gnu.org/archive/html/automake/2013-01/msg00060.html
# For old automake use this
#AM_INIT_AUTOMAKE(dist-xz)
AM_INIT_AUTOMAKE([dist-xz 1.12 serial-tests])
if test "x$prefix" = "xNONE"; then
sysconfdir=/etc
@@ -32,7 +37,7 @@ PKG_PROG_PKG_CONFIG
AC_HEADER_DIRENT
AC_HEADER_STDC
AC_CHECK_HEADERS(fcntl.h malloc.h inttypes.h sys/ioctl.h sys/mman.h \
ctype.h unistd.h locale.h)
ctype.h unistd.h locale.h byteswap.h endian.h)
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.])])
@@ -42,14 +47,20 @@ AC_CHECK_LIB(uuid, uuid_clear, ,[AC_MSG_ERROR([You need the uuid library.])])
AC_SUBST(UUID_LIBS, $LIBS)
LIBS=$saved_LIBS
AC_CHECK_FUNCS([posix_memalign])
AC_SEARCH_LIBS([clock_gettime],[rt posix4])
AC_CHECK_FUNCS([posix_memalign clock_gettime])
if test "x$enable_largefile" = "xno" ; then
AC_MSG_ERROR([Building with --disable-largefile is not supported, it can cause data corruption.])
fi
AC_C_CONST
AC_C_BIGENDIAN
AC_TYPE_OFF_T
AC_SYS_LARGEFILE
AC_FUNC_FSEEKO
AC_PROG_GCC_TRADITIONAL
AC_FUNC_STRERROR_R
dnl ==========================================================================
@@ -65,25 +76,17 @@ AC_SUBST(POPT_LIBS, $LIBS)
LIBS=$saved_LIBS
dnl ==========================================================================
dnl FIPS extensions
dnl FIPS extensions (only for RHEL)
AC_ARG_ENABLE([fips], AS_HELP_STRING([--enable-fips],[enable FIPS mode restrictions]),
[with_fips=$enableval],
[with_fips=no])
if test "x$with_fips" = "xyes"; then
AC_DEFINE(ENABLE_FIPS, 1, [Enable FIPS mode restrictions])
AC_DEFINE_UNQUOTED(LIBCRYPTSETUP_VERSION_FIPS, ["$LIBCRYPTSETUP_VERSION_FIPS"],
[library file name for FIPS selfcheck])
if test "x$enable_static" = "xyes" -o "x$enable_static_cryptsetup" = "xyes" ; then
AC_MSG_ERROR([Static build is not compatible with FIPS.])
fi
saved_LIBS=$LIBS
AC_CHECK_LIB(fipscheck, FIPSCHECK_verify, ,[AC_MSG_ERROR([You need the fipscheck library.])])
AC_SUBST(FIPSCHECK_LIBS, $LIBS)
LIBS=$saved_LIBS
fi
AC_DEFUN([NO_FIPS], [
@@ -118,10 +121,22 @@ AC_DEFUN([CONFIGURE_GCRYPT], [
fi
dnl Check if we can use gcrypt PBKDF2 (1.6.0 supports empty password)
AC_ARG_ENABLE([gcrypt-pbkdf2], AS_HELP_STRING([--enable-gcrypt-pbkdf2],[force enable internal gcrypt PBKDF2]),
[use_internal_pbkdf2=0],
[AM_PATH_LIBGCRYPT([1.6.0], [use_internal_pbkdf2=0], [use_internal_pbkdf2=1])])
if test "x$enableval" = "xyes"; then
[use_internal_pbkdf2=0]
else
[use_internal_pbkdf2=1]
fi,
[AM_PATH_LIBGCRYPT([1.6.1], [use_internal_pbkdf2=0], [use_internal_pbkdf2=1])])
AM_PATH_LIBGCRYPT($GCRYPT_REQ_VERSION,,[AC_MSG_ERROR([You need the gcrypt library.])])
AC_MSG_CHECKING([if internal cryptsetup PBKDF2 is compiled-in])
if test $use_internal_pbkdf2 = 0; then
AC_MSG_RESULT([no])
else
AC_MSG_RESULT([yes])
NO_FIPS([])
fi
if test x$enable_static_cryptsetup = xyes; then
saved_LIBS=$LIBS
LIBS="$saved_LIBS $LIBGCRYPT_LIBS -static"
@@ -149,8 +164,8 @@ AC_DEFUN([CONFIGURE_OPENSSL], [
if test x$enable_static_cryptsetup = xyes; then
saved_PKG_CONFIG=$PKG_CONFIG
PKG_CONFIG="$PKG_CONFIG --static"
PKG_CHECK_MODULES([OPENSSL], [openssl])
CRYPTO_STATIC_LIBS=$OPENSSL_LIBS
PKG_CHECK_MODULES([OPENSSL_STATIC], [openssl])
CRYPTO_STATIC_LIBS=$OPENSSL_STATIC_LIBS
PKG_CONFIG=$saved_PKG_CONFIG
fi
NO_FIPS([])
@@ -192,13 +207,13 @@ AC_DEFUN([CONFIGURE_NETTLE], [
[AC_MSG_ERROR([You need Nettle cryptographic library.])])
saved_LIBS=$LIBS
AC_CHECK_LIB(nettle, nettle_ripemd160_init,,
[AC_MSG_ERROR([You need Nettle library version 2.4 or more recent.])])
AC_CHECK_LIB(nettle, nettle_pbkdf2_hmac_sha256,,
[AC_MSG_ERROR([You need Nettle library version 2.6 or more recent.])])
CRYPTO_LIBS=$LIBS
LIBS=$saved_LIBS
CRYPTO_STATIC_LIBS=$CRYPTO_LIBS
use_internal_pbkdf2=1
use_internal_pbkdf2=0
NO_FIPS([])
])
@@ -336,7 +351,6 @@ AC_SUBST([CRYPTO_STATIC_LIBS])
AC_SUBST([LIBCRYPTSETUP_VERSION])
AC_SUBST([LIBCRYPTSETUP_VERSION_INFO])
AC_SUBST([LIBCRYPTSETUP_VERSION_FIPS])
dnl ==========================================================================
AC_ARG_ENABLE([dev-random], AS_HELP_STRING([--enable-dev-random],
@@ -367,8 +381,12 @@ AC_ARG_ENABLE([python], AS_HELP_STRING([--enable-python],[enable Python bindings
[with_python=$enableval],
[with_python=no])
AC_ARG_WITH([python_version],
AS_HELP_STRING([--with-python_version=VERSION], [required Python version [2.6]]),
[PYTHON_VERSION=$withval], [PYTHON_VERSION=2.6])
if test "x$with_python" = "xyes"; then
AM_PATH_PYTHON([2.4])
AM_PATH_PYTHON([$PYTHON_VERSION])
if ! test -x "$PYTHON-config" ; then
AC_MSG_ERROR([Cannot find python development packages to build bindings])
@@ -376,6 +394,9 @@ if test "x$with_python" = "xyes"; then
PYTHON_INCLUDES=$($PYTHON-config --includes)
AC_SUBST(PYTHON_INCLUDES)
PYTHON_LIBS=$($PYTHON-config --libs)
AC_SUBST(PYTHON_LIBS)
fi
AM_CONDITIONAL([PYTHON_CRYPTSETUP], [test "x$with_python" = "xyes"])

View File

@@ -834,16 +834,16 @@
* lib/utils.c: Add read|write_blockwise functions, to use in
O_DIRECT file accesses.
2004-03-11 Thursday 15:52 Christophe Saout <christophe@saout.de>
2004-03-11 Thursday 15:52 Jana Saout <jana@saout.de>
* lib/blockdev.h: BLKGETSIZE64 really uses size_t as third
argument, the rest is wrong.
2004-03-10 Wednesday 17:50 Christophe Saout <christophe@saout.de>
2004-03-10 Wednesday 17:50 Jana Saout <jana@saout.de>
* lib/: libcryptsetup.h, libdevmapper.c: Small fixes.
2004-03-09 Tuesday 21:41 Christophe Saout <christophe@saout.de>
2004-03-09 Tuesday 21:41 Jana Saout <jana@saout.de>
* lib/internal.h, lib/libcryptsetup.h, lib/libdevmapper.c,
lib/setup.c, po/de.po, src/cryptsetup.c: Added internal flags to
@@ -851,7 +851,7 @@
add a function to free the memory. Also add a readonly flag to
libcryptsetup.
2004-03-09 Tuesday 16:03 Christophe Saout <christophe@saout.de>
2004-03-09 Tuesday 16:03 Jana Saout <jana@saout.de>
* ChangeLog, configure.in, setup-gettext, lib/Makefile.am,
lib/backends.c, lib/blockdev.h, lib/gcrypt.c, lib/internal.h,
@@ -859,7 +859,7 @@
lib/utils.c, po/de.po, src/Makefile.am, src/cryptsetup.c: More
reorganization work.
2004-03-08 Monday 01:38 Christophe Saout <christophe@saout.de>
2004-03-08 Monday 01:38 Jana Saout <jana@saout.de>
* ChangeLog, Makefile.am, acinclude.m4, configure.in,
lib/Makefile.am, lib/backends.c, lib/blockdev.h, lib/gcrypt.c,
@@ -867,19 +867,19 @@
src/Makefile.am: BLKGETSIZE64 fixes and started modularity
enhancements
2004-03-04 Thursday 21:06 Christophe Saout <christophe@saout.de>
2004-03-04 Thursday 21:06 Jana Saout <jana@saout.de>
* Makefile.am, po/de.po, src/cryptsetup.c, src/cryptsetup.h: First
backward compatible working version.
2004-03-04 Thursday 00:42 Christophe Saout <christophe@saout.de>
2004-03-04 Thursday 00:42 Jana Saout <jana@saout.de>
* NEWS, AUTHORS, ChangeLog, Makefile.am, README, autogen.sh,
configure.in, setup-gettext, po/ChangeLog, po/LINGUAS,
po/POTFILES.in, po/de.po, src/cryptsetup.c, src/cryptsetup.h,
src/Makefile.am (utags: initial): Initial checkin.
2004-03-04 Thursday 00:42 Christophe Saout <christophe@saout.de>
2004-03-04 Thursday 00:42 Jana Saout <jana@saout.de>
* NEWS, AUTHORS, ChangeLog, Makefile.am, README, autogen.sh,
configure.in, setup-gettext, po/ChangeLog, po/LINGUAS,

View File

@@ -56,7 +56,7 @@
* in a persistent way on the device. Keyslot area is an array beyond LUKS header, where
* volume key is stored in the encrypted form using user input passphrase. For more info about
* LUKS keyslots and how it's actually protected, please look at
* <A HREF="http://code.google.com/p/cryptsetup/wiki/Specification">LUKS specification</A>.
* <A HREF="https://gitlab.com/cryptsetup/cryptsetup/wikis/Specification">LUKS specification</A>.
* There are two basic methods to create a new keyslot:
*
* @subsection ckeyslot_vol crypt_keyslot_add_by_volume_key()

25
docs/v1.6.2-ReleaseNotes Normal file
View File

@@ -0,0 +1,25 @@
Cryptsetup 1.6.2 Release Notes
==============================
Changes since version 1.6.1
* Print error and fail if more device arguments are present for isLuks command.
* Fix cipher specification string parsing (found by gcc -fsanitize=address option).
* Try to map TCRYPT system encryption through partition
(allows to activate mapping when other partition on the same device is mounted).
* Print a warning if system encryption is used and device is a partition.
(TCRYPT system encryption uses whole device argument.)
* Disallow explicit small payload offset for LUKS detached header.
LUKS detached header only allows data payload 0 (whole data device is used)
or explicit offset larger than header + keyslots size.
* Fix boundary condition for verity device that caused failure for certain device sizes.
* Various fixes to documentation, including update FAQ, default modes
and TCRYPT description.
* Workaround for some recent changes in automake (serial-tests).

50
docs/v1.6.3-ReleaseNotes Normal file
View File

@@ -0,0 +1,50 @@
Cryptsetup 1.6.3 Release Notes
==============================
Changes since version 1.6.2
* Fix cryptsetup reencryption tool to work properly
with devices using 4kB sectors.
* Always use page size if running through loop device,
this fixes failures for external LUKS header and
filesystem requiring 4kB block size.
* Fix TCRYPT system encryption mapping for multiple partitions.
Since this commit, one can use partition directly as device parameter.
If you need to activate such partition from image in file,
please first use map partitioned loop device (losetup -P)
on image.
(Cryptsetup require partition offsets visible in kernel sysfs
in this mode.)
* Support activation of old TrueCrypt containers using CBC mode
and whitening (created in TrueCrypt version < 4.1).
This requires Linux kernel 3.13 or later.
(Containers with cascade CBC ciphers are not supported.)
* Properly display keys in dump --dump-master-key command
for TrueCrypt CBC containers.
* Rewrite cipher benchmark loop which was unreliable
on very fast machines.
* Add warning if LUKS device was activated using non-cryptsetup
library which did not set UUID properly (e.g. cryptmount).
(Some commands, like luksSuspend, are not available then.)
* Support length limitation also for plain (no hash) length.
This can be used for mapping problematic cryptosystems which
wipes some key (losetup sometimes set last 32 byte to zero,
which can be now configured as --hash plain:31 parameter).
* Fix hash limit if parameter is not a number.
(The whole key was set to zero instead of command failure.)
* Unify --key-slot behavior in cryptsetup_reencrypt tool.
* Update dracut example scripts for system reencryption on first boot.
* Add command line option --tcrypt-backup to access TCRYPT backup header.
* Fix static compilation with OpenSSL.

57
docs/v1.6.4-ReleaseNotes Normal file
View File

@@ -0,0 +1,57 @@
Cryptsetup 1.6.4 Release Notes
==============================
Changes since version 1.6.3
* Implement new erase (with alias luksErase) command.
The erase cryptsetup command can be used to permanently erase
all keyslots and make the LUKS container inaccessible.
(The only way to unlock such device is to use LUKS header backup
created before erase command was used.)
You do not need to provide any password for this operation.
This operation is irreversible.
* Add internal "whirlpool_gcryptbug hash" for accessing flawed
Whirlpool hash in gcrypt (requires gcrypt 1.6.1 or above).
The gcrypt version of Whirlpool hash algorithm was flawed in some
situations.
This means that if you used Whirlpool in LUKS header and upgraded
to new gcrypt library your LUKS container become inaccessible.
Please refer to cryptsetup FAQ for detail how to fix this situation.
* Allow to use --disable-gcrypt-pbkdf2 during configuration
to force use internal PBKDF2 code.
* Require gcrypt 1.6.1 for imported implementation of PBKDF2
(PBKDF2 in gcrypt 1.6.0 is too slow).
* Add --keep-key to cryptsetup-reencrypt.
This allows change of LUKS header hash (and iteration count) without
the need to reencrypt the whole data area.
(Reencryption of LUKS header only without master key change.)
* By default verify new passphrase in luksChangeKey and luksAddKey
commands (if input is from terminal).
* Fix memory leak in Nettle crypto backend.
* Support --tries option even for TCRYPT devices in cryptsetup.
* Support --allow-discards option even for TCRYPT devices.
(Note that this could destroy hidden volume and it is not suggested
by original TrueCrypt security model.)
* Link against -lrt for clock_gettime to fix undefined reference
to clock_gettime error (introduced in 1.6.2).
* Fix misleading error message when some algorithms are not available.
* Count system time in PBKDF2 benchmark if kernel returns no self usage info.
(Workaround to broken getrusage() syscall with some hypervisors.)

54
docs/v1.6.5-ReleaseNotes Normal file
View File

@@ -0,0 +1,54 @@
Cryptsetup 1.6.5 Release Notes
==============================
Changes since version 1.6.4
* Allow LUKS header operation handling without requiring root privilege.
It means that you can manipulate with keyslots as a regular user, only
write access to device (or image) is required.
This requires kernel crypto wrapper (similar to TrueCrypt device handling)
to be available (CRYPTO_USER_API_SKCIPHER kernel option).
If this kernel interface is not available, code fallbacks to old temporary
keyslot device creation (where root privilege is required).
Note that activation, deactivation, resize and suspend operations still
need root privilege (limitation of kernel device-mapper backend).
* Fix internal PBKDF2 key derivation function implementation for alternative
crypto backends (kernel, NSS) which do not support PBKDF2 directly and have
issues with longer HMAC keys.
This fixes the problem for long keyfiles where either calculation is too slow
(because of internal rehashing in every iteration) or there is a limit
(kernel backend seems to not support HMAC key longer than 20480 bytes).
(Note that for recent version of gcrypt, nettle or openssl the internal
PBKDF2 code is not compiled in and crypto library internal functions are
used instead.)
* Support for Python3 for simple Python binding.
Python >= 2.6 is now required. You can set Python compiled version by setting
--with-python_version configure option (together with --enable-python).
* Use internal PBKDF2 in Nettle library for Nettle crypto backend.
Cryptsetup compilation requires Nettle >= 2.6 (if using Nettle crypto backend).
* Allow simple status of crypt device without providing metadata header.
The command "cryptsetup status" will print basic info, even if you
do not provide detached header argument.
* Allow to specify ECB mode in cryptsetup benchmark.
* Add some LUKS images for regression testing.
Note that if image with Whirlpool fails, the most probable cause is that
you have old gcrypt library with flawed whirlpool hash.
Read FAQ section 8.3 for more info.
Cryptsetup API NOTE:
The direct terminal handling for passphrase entry will be removed from
libcryptsetup in next major version (application should handle it itself).
It means that you have to always either provide password in buffer or set
your own password callback function trhough crypt_set_password_callback().
See API documentation (or libcryptsetup.h) for more info.

29
docs/v1.6.6-ReleaseNotes Normal file
View File

@@ -0,0 +1,29 @@
Cryptsetup 1.6.6 Release Notes
==============================
Changes since version 1.6.5
* LUKS: Fix keyslot device access for devices which
do not support direct IO operations. (Regression in 1.6.5.)
* LUKS: Fallback to old temporary keyslot device mapping method
if hash (for ESSIV) is not supported by userspace crypto
library. (Regression in 1.6.5.)
* Properly activate device with discard (TRIM for SSDs)
if requested even if dm_crypt module is not yet loaded.
Only if discard is not supported by the old kernel then
the discard option is ignored.
* Fix some static analysis build warnings (scan-build).
* Report crypto lib version only once (and always add kernel
version) in debug output.
Cryptsetup API NOTE:
The direct terminal handling for passphrase entry will be removed from
libcryptsetup in next major version (application should handle it itself).
It means that you have to always either provide password in buffer or set
your own password callback function through crypt_set_password_callback().
See API documentation (or libcryptsetup.h) for more info.

84
docs/v1.6.7-ReleaseNotes Normal file
View File

@@ -0,0 +1,84 @@
Cryptsetup 1.6.7 Release Notes
==============================
Changes since version 1.6.6
* Cryptsetup git and wiki are now hosted on GitLab.
https://gitlab.com/cryptsetup/cryptsetup
Repository of stable releases remains on kernel.org site
https://www.kernel.org/pub/linux/utils/cryptsetup/
For more info please see README file.
* Cryptsetup TCRYPT mode now supports VeraCrypt devices (TrueCrypt extension).
The VeraCrypt extension only increases iteration count for the key
derivation function (on-disk format is the same as TrueCrypt format).
Note that unlocking of a VeraCrypt device can take very long time if used
on slow machines.
To use this extension, add --veracrypt option, for example
cryptsetup open --type tcrypt --veracrypt <container> <name>
For use through libcryptsetup, just add CRYPT_TCRYPT_VERA_MODES flag.
* Support keyfile-offset and keyfile-size options even for plain volumes.
* Support keyfile option for luksAddKey if the master key is specified.
* For historic reasons, hashing in the plain mode is not used
if keyfile is specified (with exception of --key-file=-).
Print a warning if these parameters are ignored.
* Support permanent device decryption for cryptsetup-reencrypt.
To remove LUKS encryption from a device, you can now use --decrypt option.
* Allow to use --header option in all LUKS commands.
The --header always takes precedence over positional device argument.
* Allow luksSuspend without need to specify a detached header.
* Detect if O_DIRECT is usable on a device allocation.
There are some strange storage stack configurations which wrongly allows
to open devices with direct-io but fails on all IO operations later.
Cryptsetup now tries to read the device first sector to ensure it can use
direct-io.
* Add low-level performance options tuning for dmcrypt (for Linux 4.0 and later).
Linux kernel 4.0 contains rewritten dmcrypt code which tries to better utilize
encryption on parallel CPU cores.
While tests show that this change increases performance on most configurations,
dmcrypt now provides some switches to change its new behavior.
You can use them (per-device) with these cryptsetup switches:
--perf-same_cpu_crypt
--perf-submit_from_crypt_cpus
Please use these only in the case of serious performance problems.
Refer to the cryptsetup man page and dm-crypt documentation
(for same_cpu_crypt and submit_from_crypt_cpus options).
https://gitlab.com/cryptsetup/cryptsetup/wikis/DMCrypt
* Get rid of libfipscheck library.
(Note that this option was used only for Red Hat and derived distributions.)
With recent FIPS changes we do not need to link to this FIPS monster anymore.
Also drop some no longer needed FIPS mode checks.
* Many fixes and clarifications to man pages.
* Prevent compiler to optimize-out zeroing of buffers for on-stack variables.
* Fix a crash if non-GNU strerror_r is used.
Cryptsetup API NOTE:
The direct terminal handling for passphrase entry will be removed from
libcryptsetup in next major version (application should handle it itself).
It means that you have to always either provide password in buffer or set
your own password callback function through crypt_set_password_callback().
See API documentation (or libcryptsetup.h) for more info.

View File

@@ -5,7 +5,7 @@ moduledir = $(libdir)/cryptsetup
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libcryptsetup.pc
AM_CPPFLAGS = \
AM_CPPFLAGS = -include config.h \
-I$(top_srcdir) \
-I$(top_srcdir)/lib/crypto_backend \
-I$(top_srcdir)/lib/luks1 \
@@ -16,10 +16,7 @@ AM_CPPFLAGS = \
-DLIBDIR=\""$(libdir)"\" \
-DPREFIX=\""$(prefix)"\" \
-DSYSCONFDIR=\""$(sysconfdir)"\" \
-DVERSION=\""$(VERSION)"\" \
-D_GNU_SOURCE \
-D_LARGEFILE64_SOURCE \
-D_FILE_OFFSET_BITS=64
-DVERSION=\""$(VERSION)"\"
lib_LTLIBRARIES = libcryptsetup.la
@@ -32,17 +29,16 @@ common_ldadd = \
libcryptsetup_la_DEPENDENCIES = $(common_ldadd) libcryptsetup.sym
libcryptsetup_la_LDFLAGS = \
libcryptsetup_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined \
-Wl,--version-script=$(top_srcdir)/lib/libcryptsetup.sym \
-version-info @LIBCRYPTSETUP_VERSION_INFO@
libcryptsetup_la_CFLAGS = -Wall @CRYPTO_CFLAGS@
libcryptsetup_la_CFLAGS = -Wall $(AM_CFLAGS) @CRYPTO_CFLAGS@
libcryptsetup_la_LIBADD = \
@UUID_LIBS@ \
@DEVMAPPER_LIBS@ \
@CRYPTO_LIBS@ \
@FIPSCHECK_LIBS@ \
$(common_ldadd)

View File

@@ -1,7 +1,7 @@
/*
* cryptsetup plain device helper functions
*
* Copyright (C) 2004, Christophe Saout <christophe@saout.de>
* Copyright (C) 2004, Jana Saout <jana@saout.de>
* Copyright (C) 2010-2012 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2012, Milan Broz
*
@@ -21,7 +21,7 @@
*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include "libcryptsetup.h"
@@ -83,7 +83,11 @@ int crypt_plain_hash(struct crypt_device *ctx __attribute__((unused)),
/* hash[:hash_length] */
if ((s = strchr(hash_name_buf, ':'))) {
*s = '\0';
hash_size = atoi(++s);
s++;
if (!*s || sscanf(s, "%zd", &hash_size) != 1) {
log_dbg("Hash length is not a number");
return -EINVAL;
}
if (hash_size > key_size) {
log_dbg("Hash length %zd > key length %zd",
hash_size, key_size);
@@ -95,7 +99,16 @@ int crypt_plain_hash(struct crypt_device *ctx __attribute__((unused)),
pad_size = 0;
}
r = hash(hash_name_buf, hash_size, key, passphrase_size, passphrase);
/* No hash, copy passphrase directly */
if (!strcmp(hash_name_buf, "plain")) {
if (passphrase_size < hash_size) {
log_dbg("Too short plain passphrase.");
return -EINVAL;
}
memcpy(key, passphrase, hash_size);
r = 0;
} else
r = hash(hash_name_buf, hash_size, key, passphrase_size, passphrase);
if (r == 0 && pad_size)
memset(key + hash_size, 0, pad_size);

View File

@@ -2,10 +2,10 @@ moduledir = $(libdir)/cryptsetup
noinst_LTLIBRARIES = libcrypto_backend.la
libcrypto_backend_la_CFLAGS = -Wall @CRYPTO_CFLAGS@
libcrypto_backend_la_CFLAGS = $(AM_CFLAGS) -Wall @CRYPTO_CFLAGS@
libcrypto_backend_la_SOURCES = crypto_backend.h \
crypto_cipher_kernel.c pbkdf_check.c crc32.c
crypto_cipher_kernel.c crypto_storage.c pbkdf_check.c crc32.c
if CRYPTO_BACKEND_GCRYPT
libcrypto_backend_la_SOURCES += crypto_gcrypt.c
@@ -27,4 +27,4 @@ if CRYPTO_INTERNAL_PBKDF2
libcrypto_backend_la_SOURCES += pbkdf2_generic.c
endif
AM_CPPFLAGS = -D_GNU_SOURCE -I$(top_srcdir)/lib
AM_CPPFLAGS = -include config.h -I$(top_srcdir)/lib

View File

@@ -2,7 +2,7 @@
* crypto backend implementation
*
* Copyright (C) 2010-2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2012, Milan Broz
* Copyright (C) 2010-2014, 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,12 +23,12 @@
#include <stdint.h>
#include <string.h>
#include "config.h"
struct crypt_device;
struct crypt_hash;
struct crypt_hmac;
struct crypt_cipher;
struct crypt_storage;
int crypt_backend_init(struct crypt_device *ctx);
@@ -73,13 +73,15 @@ int pkcs5_pbkdf2(const char *hash,
const char *P, size_t Plen,
const char *S, size_t Slen,
unsigned int c,
unsigned int dkLen,char *DK);
unsigned int dkLen, char *DK,
unsigned int hash_block_size);
#endif
/* CRC32 */
uint32_t crypt_crc32(uint32_t seed, const unsigned char *buf, size_t len);
/* ciphers */
int crypt_cipher_blocksize(const char *name);
int crypt_cipher_init(struct crypt_cipher **ctx, const char *name,
const char *mode, const void *buffer, size_t length);
int crypt_cipher_destroy(struct crypt_cipher *ctx);
@@ -90,4 +92,21 @@ int crypt_cipher_decrypt(struct crypt_cipher *ctx,
const char *in, char *out, size_t length,
const char *iv, size_t iv_length);
/* storage encryption wrappers */
int crypt_storage_init(struct crypt_storage **ctx, uint64_t sector_start,
const char *cipher, const char *cipher_mode,
char *key, size_t key_length);
int crypt_storage_destroy(struct crypt_storage *ctx);
int crypt_storage_decrypt(struct crypt_storage *ctx, uint64_t sector,
size_t count, char *buffer);
int crypt_storage_encrypt(struct crypt_storage *ctx, uint64_t sector,
size_t count, char *buffer);
/* Memzero helper (memset on stack can be optimized out) */
static inline void crypt_backend_memzero(void *s, size_t n)
{
volatile uint8_t *p = (volatile uint8_t *)s;
while(n--) *p++ = 0;
}
#endif /* _CRYPTO_BACKEND_H */

View File

@@ -2,7 +2,7 @@
* Linux kernel userspace API crypto backend implementation (skcipher)
*
* Copyright (C) 2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2012, Milan Broz
* Copyright (C) 2012-2014, Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -44,6 +44,50 @@ struct crypt_cipher {
int opfd;
};
struct cipher_alg {
const char *name;
int blocksize;
};
/* FIXME: Getting block size should be dynamic from cipher backend. */
static struct cipher_alg cipher_algs[] = {
{ "cipher_null", 16 },
{ "aes", 16 },
{ "serpent", 16 },
{ "twofish", 16 },
{ "anubis", 16 },
{ "blowfish", 8 },
{ "camellia", 16 },
{ "cast5", 8 },
{ "cast6", 16 },
{ "des", 8 },
{ "des3_ede", 8 },
{ "khazad", 8 },
{ "seed", 16 },
{ "tea", 8 },
{ "xtea", 8 },
{ NULL, 0 }
};
static struct cipher_alg *_get_alg(const char *name)
{
int i = 0;
while (name && cipher_algs[i].name) {
if (!strcasecmp(name, cipher_algs[i].name))
return &cipher_algs[i];
i++;
}
return NULL;
}
int crypt_cipher_blocksize(const char *name)
{
struct cipher_alg *ca = _get_alg(name);
return ca ? ca->blocksize : -EINVAL;
}
/* Shared with hash kernel backend */
int crypt_kernel_socket_init(struct sockaddr_alg *sa, int *tfmfd, int *opfd);
@@ -99,7 +143,8 @@ int crypt_cipher_init(struct crypt_cipher **ctx, const char *name,
return r;
}
if (setsockopt(h->tfmfd, SOL_ALG, ALG_SET_KEY, buffer, length) == -1) {
if (length && strcmp(name, "cipher_null") &&
setsockopt(h->tfmfd, SOL_ALG, ALG_SET_KEY, buffer, length) == -1) {
crypt_cipher_destroy(h);
return -EINVAL;
}
@@ -142,6 +187,9 @@ static int crypt_cipher_crypt(struct crypt_cipher *ctx,
/* Set encrypt/decrypt operation */
header = CMSG_FIRSTHDR(&msg);
if (!header)
return -EINVAL;
header->cmsg_level = SOL_ALG;
header->cmsg_type = ALG_SET_OP;
header->cmsg_len = CMSG_LEN(sizeof(*type));
@@ -169,7 +217,7 @@ static int crypt_cipher_crypt(struct crypt_cipher *ctx,
if (len != (ssize_t)length)
r = -EIO;
bad:
memset(buffer, 0, sizeof(buffer));
crypt_backend_memzero(buffer, sizeof(buffer));
return r;
}
@@ -202,6 +250,11 @@ int crypt_cipher_destroy(struct crypt_cipher *ctx)
#else /* ENABLE_AF_ALG */
int crypt_cipher_blocksize(const char *name)
{
return -EINVAL;
}
int crypt_cipher_init(struct crypt_cipher **ctx, const char *name,
const char *mode, const void *buffer, size_t length)
{

View File

@@ -2,7 +2,7 @@
* GCRYPT crypto backend implementation
*
* Copyright (C) 2010-2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2012, Milan Broz
* Copyright (C) 2010-2014, Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -28,6 +28,7 @@
static int crypto_backend_initialised = 0;
static int crypto_backend_secmem = 1;
static int crypto_backend_whirlpool_bug = -1;
static char version[64];
struct crypt_hash {
@@ -42,6 +43,44 @@ struct crypt_hmac {
int hash_len;
};
/*
* Test for wrong Whirlpool variant,
* Ref: http://lists.gnupg.org/pipermail/gcrypt-devel/2014-January/002889.html
*/
static void crypt_hash_test_whirlpool_bug(void)
{
struct crypt_hash *h;
char buf[2] = "\0\0", hash_out1[64], hash_out2[64];
int r;
if (crypto_backend_whirlpool_bug >= 0)
return;
crypto_backend_whirlpool_bug = 0;
if (crypt_hash_init(&h, "whirlpool"))
return;
/* One shot */
if ((r = crypt_hash_write(h, &buf[0], 2)) ||
(r = crypt_hash_final(h, hash_out1, 64))) {
crypt_hash_destroy(h);
return;
}
/* Split buf (crypt_hash_final resets hash state) */
if ((r = crypt_hash_write(h, &buf[0], 1)) ||
(r = crypt_hash_write(h, &buf[1], 1)) ||
(r = crypt_hash_final(h, hash_out2, 64))) {
crypt_hash_destroy(h);
return;
}
crypt_hash_destroy(h);
if (memcmp(hash_out1, hash_out2, 64))
crypto_backend_whirlpool_bug = 1;
}
int crypt_backend_init(struct crypt_device *ctx)
{
if (crypto_backend_initialised)
@@ -70,10 +109,15 @@ int crypt_backend_init(struct crypt_device *ctx)
gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
}
snprintf(version, 64, "gcrypt %s%s",
gcry_check_version(NULL),
crypto_backend_secmem ? "" : ", secmem disabled");
crypto_backend_initialised = 1;
crypt_hash_test_whirlpool_bug();
snprintf(version, 64, "gcrypt %s%s%s",
gcry_check_version(NULL),
crypto_backend_secmem ? "" : ", secmem disabled",
crypto_backend_whirlpool_bug > 0 ? ", flawed whirlpool" : ""
);
return 0;
}
@@ -87,6 +131,23 @@ uint32_t crypt_backend_flags(void)
return 0;
}
static const char *crypt_hash_compat_name(const char *name, unsigned int *flags)
{
const char *hash_name = name;
/* "whirlpool_gcryptbug" is out shortcut to flawed whirlpool
* in libgcrypt < 1.6.0 */
if (name && !strcasecmp(name, "whirlpool_gcryptbug")) {
#if GCRYPT_VERSION_NUMBER >= 0x010601
if (flags)
*flags |= GCRY_MD_FLAG_BUGEMU1;
#endif
hash_name = "whirlpool";
}
return hash_name;
}
/* HASH */
int crypt_hash_size(const char *name)
{
@@ -94,7 +155,7 @@ int crypt_hash_size(const char *name)
assert(crypto_backend_initialised);
hash_id = gcry_md_map_name(name);
hash_id = gcry_md_map_name(crypt_hash_compat_name(name, NULL));
if (!hash_id)
return -EINVAL;
@@ -104,6 +165,7 @@ int crypt_hash_size(const char *name)
int crypt_hash_init(struct crypt_hash **ctx, const char *name)
{
struct crypt_hash *h;
unsigned int flags = 0;
assert(crypto_backend_initialised);
@@ -111,13 +173,13 @@ int crypt_hash_init(struct crypt_hash **ctx, const char *name)
if (!h)
return -ENOMEM;
h->hash_id = gcry_md_map_name(name);
h->hash_id = gcry_md_map_name(crypt_hash_compat_name(name, &flags));
if (!h->hash_id) {
free(h);
return -EINVAL;
}
if (gcry_md_open(&h->hd, h->hash_id, 0)) {
if (gcry_md_open(&h->hd, h->hash_id, flags)) {
free(h);
return -EINVAL;
}
@@ -173,6 +235,7 @@ int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
const void *buffer, size_t length)
{
struct crypt_hmac *h;
unsigned int flags = GCRY_MD_FLAG_HMAC;
assert(crypto_backend_initialised);
@@ -180,13 +243,13 @@ int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
if (!h)
return -ENOMEM;
h->hash_id = gcry_md_map_name(name);
h->hash_id = gcry_md_map_name(crypt_hash_compat_name(name, &flags));
if (!h->hash_id) {
free(h);
return -EINVAL;
}
if (gcry_md_open(&h->hd, h->hash_id, GCRY_MD_FLAG_HMAC)) {
if (gcry_md_open(&h->hd, h->hash_id, flags)) {
free(h);
return -EINVAL;
}
@@ -261,15 +324,17 @@ int crypt_pbkdf(const char *kdf, const char *hash,
char *key, size_t key_length,
unsigned int iterations)
{
const char *hash_name = crypt_hash_compat_name(hash, NULL);
#if USE_INTERNAL_PBKDF2
if (!kdf || strncmp(kdf, "pbkdf2", 6))
return -EINVAL;
return pkcs5_pbkdf2(hash, password, password_length, salt, salt_length,
iterations, key_length, key);
return pkcs5_pbkdf2(hash_name, password, password_length, salt, salt_length,
iterations, key_length, key, 0);
#else /* USE_INTERNAL_PBKDF2 */
int hash_id = gcry_md_map_name(hash);
int hash_id = gcry_md_map_name(hash_name);
int kdf_id;
if (!hash_id)

View File

@@ -2,7 +2,7 @@
* Linux kernel userspace API crypto backend implementation
*
* Copyright (C) 2010-2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2012, Milan Broz
* Copyright (C) 2010-2014, Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -44,15 +44,16 @@ struct hash_alg {
const char *name;
const char *kernel_name;
int length;
unsigned int block_length;
};
static struct hash_alg hash_algs[] = {
{ "sha1", "sha1", 20 },
{ "sha256", "sha256", 32 },
{ "sha512", "sha512", 64 },
{ "ripemd160", "rmd160", 20 },
{ "whirlpool", "wp512", 64 },
{ NULL, NULL, 0 }
{ "sha1", "sha1", 20, 64 },
{ "sha256", "sha256", 32, 64 },
{ "sha512", "sha512", 64, 128 },
{ "ripemd160", "rmd160", 20, 64 },
{ "whirlpool", "wp512", 64, 64 },
{ NULL, NULL, 0, 0 }
};
struct crypt_hash {
@@ -289,9 +290,11 @@ int crypt_pbkdf(const char *kdf, const char *hash,
char *key, size_t key_length,
unsigned int iterations)
{
if (!kdf || strncmp(kdf, "pbkdf2", 6))
struct hash_alg *ha = _get_alg(hash);
if (!ha || !kdf || strncmp(kdf, "pbkdf2", 6))
return -EINVAL;
return pkcs5_pbkdf2(hash, password, password_length, salt, salt_length,
iterations, key_length, key);
iterations, key_length, key, ha->block_length);
}

View File

@@ -2,7 +2,7 @@
* Nettle crypto backend implementation
*
* Copyright (C) 2011-2012 Red Hat, Inc. All rights reserved.
* Copyright (C) 2011-2012, Milan Broz
* Copyright (C) 2011-2014, Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -24,6 +24,7 @@
#include <errno.h>
#include <nettle/sha.h>
#include <nettle/hmac.h>
#include <nettle/pbkdf2.h>
#include "crypto_backend.h"
static char *version = "Nettle";
@@ -265,8 +266,8 @@ int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length)
int crypt_hmac_destroy(struct crypt_hmac *ctx)
{
memset(ctx->key, 0, ctx->key_length);
memset(ctx, 0, sizeof(*ctx));
free(ctx->key);
memset(ctx, 0, sizeof(*ctx));
free(ctx);
return 0;
}
@@ -284,10 +285,21 @@ int crypt_pbkdf(const char *kdf, const char *hash,
char *key, size_t key_length,
unsigned int iterations)
{
struct crypt_hmac *h;
int r;
if (!kdf || strncmp(kdf, "pbkdf2", 6))
return -EINVAL;
/* FIXME: switch to internal implementation in Nettle 2.6 */
return pkcs5_pbkdf2(hash, password, password_length, salt, salt_length,
iterations, key_length, key);
r = crypt_hmac_init(&h, hash, password, password_length);
if (r < 0)
return r;
nettle_pbkdf2(&h->nettle_ctx, h->hash->nettle_hmac_update,
h->hash->nettle_hmac_digest, h->hash->length, iterations,
salt_length, (const uint8_t *)salt, key_length,
(uint8_t *)key);
crypt_hmac_destroy(h);
return 0;
}

View File

@@ -2,7 +2,7 @@
* NSS crypto backend implementation
*
* Copyright (C) 2010-2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2012, Milan Broz
* Copyright (C) 2010-2014, 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,14 +35,15 @@ struct hash_alg {
SECOidTag oid;
CK_MECHANISM_TYPE ck_type;
int length;
unsigned int block_length;
};
static struct hash_alg hash_algs[] = {
{ "sha1", SEC_OID_SHA1, CKM_SHA_1_HMAC, 20 },
{ "sha256", SEC_OID_SHA256, CKM_SHA256_HMAC, 32 },
{ "sha384", SEC_OID_SHA384, CKM_SHA384_HMAC, 48 },
{ "sha512", SEC_OID_SHA512, CKM_SHA512_HMAC, 64 },
// { "ripemd160", SEC_OID_RIPEMD160, CKM_RIPEMD160_HMAC, 20 },
{ "sha1", SEC_OID_SHA1, CKM_SHA_1_HMAC, 20, 64 },
{ "sha256", SEC_OID_SHA256, CKM_SHA256_HMAC, 32, 64 },
{ "sha384", SEC_OID_SHA384, CKM_SHA384_HMAC, 48, 128 },
{ "sha512", SEC_OID_SHA512, CKM_SHA512_HMAC, 64, 128 },
// { "ripemd160", SEC_OID_RIPEMD160, CKM_RIPEMD160_HMAC, 20, 64 },
{ NULL, 0, 0, 0 }
};
@@ -163,7 +164,7 @@ int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length)
return -EINVAL;
memcpy(buffer, tmp, length);
memset(tmp, 0, sizeof(tmp));
crypt_backend_memzero(tmp, sizeof(tmp));
if (tmp_len < length)
return -EINVAL;
@@ -265,7 +266,7 @@ int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length)
return -EINVAL;
memcpy(buffer, tmp, length);
memset(tmp, 0, sizeof(tmp));
crypt_backend_memzero(tmp, sizeof(tmp));
if (tmp_len < length)
return -EINVAL;
@@ -308,9 +309,11 @@ int crypt_pbkdf(const char *kdf, const char *hash,
char *key, size_t key_length,
unsigned int iterations)
{
if (!kdf || strncmp(kdf, "pbkdf2", 6))
struct hash_alg *ha = _get_alg(hash);
if (!ha || !kdf || strncmp(kdf, "pbkdf2", 6))
return -EINVAL;
return pkcs5_pbkdf2(hash, password, password_length, salt, salt_length,
iterations, key_length, key);
iterations, key_length, key, ha->block_length);
}

View File

@@ -2,7 +2,7 @@
* OPENSSL crypto backend implementation
*
* Copyright (C) 2010-2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2012, Milan Broz
* Copyright (C) 2010-2014, Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -133,7 +133,7 @@ int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length)
return -EINVAL;
memcpy(buffer, tmp, length);
memset(tmp, 0, sizeof(tmp));
crypt_backend_memzero(tmp, sizeof(tmp));
if (tmp_len < length)
return -EINVAL;
@@ -203,7 +203,7 @@ int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length)
HMAC_Final(&ctx->md, tmp, &tmp_len);
memcpy(buffer, tmp, length);
memset(tmp, 0, sizeof(tmp));
crypt_backend_memzero(tmp, sizeof(tmp));
if (tmp_len < length)
return -EINVAL;

View File

@@ -0,0 +1,293 @@
/*
* Generic wrapper for storage encryption modes and Initial Vectors
* (reimplementation of some functions from Linux dm-crypt kernel)
*
* Copyright (C) 2014, Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this file; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdlib.h>
#include <errno.h>
#include "bitops.h"
#include "crypto_backend.h"
#define SECTOR_SHIFT 9
#define SECTOR_SIZE (1 << SECTOR_SHIFT)
/*
* Internal IV helper
* 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 } type;
int iv_size;
char *iv;
struct crypt_cipher *essiv_cipher;
int benbi_shift;
};
/* Block encryption storage context */
struct crypt_storage {
uint64_t sector_start;
struct crypt_cipher *cipher;
struct crypt_sector_iv cipher_iv;
};
static int int_log2(unsigned int x)
{
int r = 0;
for (x >>= 1; x > 0; x >>= 1)
r++;
return r;
}
static int crypt_sector_iv_init(struct crypt_sector_iv *ctx,
const char *cipher_name, const char *mode_name,
const char *iv_name, char *key, size_t key_length)
{
memset(ctx, 0, sizeof(*ctx));
ctx->iv_size = crypt_cipher_blocksize(cipher_name);
if (ctx->iv_size < 0)
return -ENOENT;
if (!iv_name ||
!strcmp(cipher_name, "cipher_null") ||
!strcmp(mode_name, "ecb")) {
ctx->type = IV_NONE;
ctx->iv_size = 0;
return 0;
} else if (!strcasecmp(iv_name, "null")) {
ctx->type = IV_NULL;
} else if (!strcasecmp(iv_name, "plain64")) {
ctx->type = IV_PLAIN64;
} else if (!strcasecmp(iv_name, "plain")) {
ctx->type = IV_PLAIN;
} else if (!strncasecmp(iv_name, "essiv:", 6)) {
struct crypt_hash *h = NULL;
char *hash_name = strchr(iv_name, ':');
int hash_size;
char tmp[256];
int r;
if (!hash_name)
return -EINVAL;
hash_size = crypt_hash_size(++hash_name);
if (hash_size < 0)
return -ENOENT;
if ((unsigned)hash_size > sizeof(tmp))
return -EINVAL;
if (crypt_hash_init(&h, hash_name))
return -EINVAL;
r = crypt_hash_write(h, key, key_length);
if (r) {
crypt_hash_destroy(h);
return r;
}
r = crypt_hash_final(h, tmp, hash_size);
crypt_hash_destroy(h);
if (r) {
crypt_backend_memzero(tmp, sizeof(tmp));
return r;
}
r = crypt_cipher_init(&ctx->essiv_cipher, cipher_name, "ecb",
tmp, hash_size);
crypt_backend_memzero(tmp, sizeof(tmp));
if (r)
return r;
ctx->type = IV_ESSIV;
} else if (!strncasecmp(iv_name, "benbi", 5)) {
int log = int_log2(ctx->iv_size);
if (log > SECTOR_SHIFT)
return -EINVAL;
ctx->type = IV_BENBI;
ctx->benbi_shift = SECTOR_SHIFT - log;
} else
return -ENOENT;
ctx->iv = malloc(ctx->iv_size);
if (!ctx->iv)
return -ENOMEM;
return 0;
}
static int crypt_sector_iv_generate(struct crypt_sector_iv *ctx, uint64_t sector)
{
uint64_t val;
switch (ctx->type) {
case IV_NONE:
break;
case IV_NULL:
memset(ctx->iv, 0, ctx->iv_size);
break;
case IV_PLAIN:
memset(ctx->iv, 0, ctx->iv_size);
*(uint32_t *)ctx->iv = cpu_to_le32(sector & 0xffffffff);
break;
case IV_PLAIN64:
memset(ctx->iv, 0, ctx->iv_size);
*(uint64_t *)ctx->iv = cpu_to_le64(sector);
break;
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,
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);
memcpy(ctx->iv + ctx->iv_size - sizeof(val), &val, sizeof(val));
break;
default:
return -EINVAL;
}
return 0;
}
static int crypt_sector_iv_destroy(struct crypt_sector_iv *ctx)
{
if (ctx->type == IV_ESSIV)
crypt_cipher_destroy(ctx->essiv_cipher);
if (ctx->iv) {
memset(ctx->iv, 0, ctx->iv_size);
free(ctx->iv);
}
memset(ctx, 0, sizeof(*ctx));
return 0;
}
/* Block encryption storage wrappers */
int crypt_storage_init(struct crypt_storage **ctx,
uint64_t sector_start,
const char *cipher,
const char *cipher_mode,
char *key, size_t key_length)
{
struct crypt_storage *s;
char mode_name[64];
char *cipher_iv = NULL;
int r = -EIO;
s = malloc(sizeof(*s));
if (!s)
return -ENOMEM;
memset(s, 0, sizeof(*s));
/* Remove IV if present */
strncpy(mode_name, cipher_mode, sizeof(mode_name));
mode_name[sizeof(mode_name) - 1] = 0;
cipher_iv = strchr(mode_name, '-');
if (cipher_iv) {
*cipher_iv = '\0';
cipher_iv++;
}
r = crypt_cipher_init(&s->cipher, cipher, mode_name, key, key_length);
if (r) {
crypt_storage_destroy(s);
return r;
}
r = crypt_sector_iv_init(&s->cipher_iv, cipher, mode_name, cipher_iv, key, key_length);
if (r) {
crypt_storage_destroy(s);
return r;
}
s->sector_start = sector_start;
*ctx = s;
return 0;
}
int crypt_storage_decrypt(struct crypt_storage *ctx,
uint64_t sector, size_t count,
char *buffer)
{
unsigned int i;
int r = 0;
for (i = 0; i < count; i++) {
r = crypt_sector_iv_generate(&ctx->cipher_iv, sector + i);
if (r)
break;
r = crypt_cipher_decrypt(ctx->cipher,
&buffer[i * SECTOR_SIZE],
&buffer[i * SECTOR_SIZE],
SECTOR_SIZE,
ctx->cipher_iv.iv,
ctx->cipher_iv.iv_size);
if (r)
break;
}
return r;
}
int crypt_storage_encrypt(struct crypt_storage *ctx,
uint64_t sector, size_t count,
char *buffer)
{
unsigned int i;
int r = 0;
for (i = 0; i < count; i++) {
r = crypt_sector_iv_generate(&ctx->cipher_iv, sector + i);
if (r)
break;
r = crypt_cipher_encrypt(ctx->cipher,
&buffer[i * SECTOR_SIZE],
&buffer[i * SECTOR_SIZE],
SECTOR_SIZE,
ctx->cipher_iv.iv,
ctx->cipher_iv.iv_size);
if (r)
break;
}
return r;
}
int crypt_storage_destroy(struct crypt_storage *ctx)
{
if (!ctx)
return 0;
crypt_sector_iv_destroy(&ctx->cipher_iv);
if (ctx->cipher)
crypt_cipher_destroy(ctx->cipher);
memset(ctx, 0, sizeof(*ctx));
free(ctx);
return 0;
}

View File

@@ -5,6 +5,7 @@
*
* cryptsetup related changes
* Copyright (C) 2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2014, Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -26,6 +27,25 @@
#include <alloca.h>
#include "crypto_backend.h"
static int hash_buf(const char *src, size_t src_len,
char *dst, size_t dst_len,
const char *hash_name)
{
struct crypt_hash *hd = NULL;
int r;
if (crypt_hash_init(&hd, hash_name))
return -EINVAL;
r = crypt_hash_write(hd, src, src_len);
if (!r)
r = crypt_hash_final(hd, dst, dst_len);
crypt_hash_destroy(hd);
return r;
}
/*
* 5.2 PBKDF2
*
@@ -52,17 +72,26 @@
* Output: DK derived key, a dkLen-octet string
*/
/*
* if hash_block_size is not zero, the HMAC key is pre-hashed
* inside this function.
* This prevents situation when crypto backend doesn't support
* long HMAC keys or it tries hash long key in every iteration
* (because of crypt_final() cannot do simple key reset.
*/
#define MAX_PRF_BLOCK_LEN 80
int pkcs5_pbkdf2(const char *hash,
const char *P, size_t Plen,
const char *S, size_t Slen,
unsigned int c, unsigned int dkLen,
char *DK)
char *DK, unsigned int hash_block_size)
{
struct crypt_hmac *hmac;
char U[MAX_PRF_BLOCK_LEN];
char T[MAX_PRF_BLOCK_LEN];
char P_hash[MAX_PRF_BLOCK_LEN];
int i, k, rc = -EINVAL;
unsigned int u, hLen, l, r;
size_t tmplen = Slen + 4;
@@ -152,8 +181,18 @@ int pkcs5_pbkdf2(const char *hash,
*
*/
if (crypt_hmac_init(&hmac, hash, P, Plen))
return -EINVAL;
/* If hash_block_size is provided, hash password in advance. */
if (hash_block_size > 0 && Plen > hash_block_size) {
if (hash_buf(P, Plen, P_hash, hLen, hash))
return -EINVAL;
if (crypt_hmac_init(&hmac, hash, P_hash, hLen))
return -EINVAL;
crypt_backend_memzero(P_hash, sizeof(P_hash));
} else {
if (crypt_hmac_init(&hmac, hash, P, Plen))
return -EINVAL;
}
for (i = 1; (unsigned int) i <= l; i++) {
memset(T, 0, hLen);
@@ -185,5 +224,203 @@ int pkcs5_pbkdf2(const char *hash,
rc = 0;
out:
crypt_hmac_destroy(hmac);
crypt_backend_memzero(U, sizeof(U));
crypt_backend_memzero(T, sizeof(T));
crypt_backend_memzero(tmp, tmplen);
return rc;
}
#if 0
#include <stdio.h>
struct test_vector {
const char *hash;
unsigned int hash_block_length;
unsigned int iterations;
const char *password;
unsigned int password_length;
const char *salt;
unsigned int salt_length;
const char *output;
unsigned int output_length;
};
struct test_vector test_vectors[] = {
/* RFC 3962 */
{
"sha1", 64, 1,
"password", 8,
"ATHENA.MIT.EDUraeburn", 21,
"\xcd\xed\xb5\x28\x1b\xb2\xf8\x01"
"\x56\x5a\x11\x22\xb2\x56\x35\x15"
"\x0a\xd1\xf7\xa0\x4b\xb9\xf3\xa3"
"\x33\xec\xc0\xe2\xe1\xf7\x08\x37", 32
}, {
"sha1", 64, 2,
"password", 8,
"ATHENA.MIT.EDUraeburn", 21,
"\x01\xdb\xee\x7f\x4a\x9e\x24\x3e"
"\x98\x8b\x62\xc7\x3c\xda\x93\x5d"
"\xa0\x53\x78\xb9\x32\x44\xec\x8f"
"\x48\xa9\x9e\x61\xad\x79\x9d\x86", 32
}, {
"sha1", 64, 1200,
"password", 8,
"ATHENA.MIT.EDUraeburn", 21,
"\x5c\x08\xeb\x61\xfd\xf7\x1e\x4e"
"\x4e\xc3\xcf\x6b\xa1\xf5\x51\x2b"
"\xa7\xe5\x2d\xdb\xc5\xe5\x14\x2f"
"\x70\x8a\x31\xe2\xe6\x2b\x1e\x13", 32
}, {
"sha1", 64, 5,
"password", 8,
"\0224VxxV4\022", 8, // "\x1234567878563412
"\xd1\xda\xa7\x86\x15\xf2\x87\xe6"
"\xa1\xc8\xb1\x20\xd7\x06\x2a\x49"
"\x3f\x98\xd2\x03\xe6\xbe\x49\xa6"
"\xad\xf4\xfa\x57\x4b\x6e\x64\xee", 32
}, {
"sha1", 64, 1200,
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 64,
"pass phrase equals block size", 29,
"\x13\x9c\x30\xc0\x96\x6b\xc3\x2b"
"\xa5\x5f\xdb\xf2\x12\x53\x0a\xc9"
"\xc5\xec\x59\xf1\xa4\x52\xf5\xcc"
"\x9a\xd9\x40\xfe\xa0\x59\x8e\xd1", 32
}, {
"sha1", 64, 1200,
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 65,
"pass phrase exceeds block size", 30,
"\x9c\xca\xd6\xd4\x68\x77\x0c\xd5"
"\x1b\x10\xe6\xa6\x87\x21\xbe\x61"
"\x1a\x8b\x4d\x28\x26\x01\xdb\x3b"
"\x36\xbe\x92\x46\x91\x5e\xc8\x2a", 32
}, {
"sha1", 64, 50,
"\360\235\204\236", 4, // g-clef ("\xf09d849e)
"EXAMPLE.COMpianist", 18,
"\x6b\x9c\xf2\x6d\x45\x45\x5a\x43"
"\xa5\xb8\xbb\x27\x6a\x40\x3b\x39"
"\xe7\xfe\x37\xa0\xc4\x1e\x02\xc2"
"\x81\xff\x30\x69\xe1\xe9\x4f\x52", 32
}, {
/* RFC-6070 */
"sha1", 64, 1,
"password", 8,
"salt", 4,
"\x0c\x60\xc8\x0f\x96\x1f\x0e\x71\xf3\xa9"
"\xb5\x24\xaf\x60\x12\x06\x2f\xe0\x37\xa6", 20
}, {
"sha1", 64, 2,
"password", 8,
"salt", 4,
"\xea\x6c\x01\x4d\xc7\x2d\x6f\x8c\xcd\x1e"
"\xd9\x2a\xce\x1d\x41\xf0\xd8\xde\x89\x57", 20
}, {
"sha1", 64, 4096,
"password", 8,
"salt", 4,
"\x4b\x00\x79\x01\xb7\x65\x48\x9a\xbe\xad"
"\x49\xd9\x26\xf7\x21\xd0\x65\xa4\x29\xc1", 20
}, {
"sha1", 64, 16777216,
"password", 8,
"salt", 4,
"\xee\xfe\x3d\x61\xcd\x4d\xa4\xe4\xe9\x94"
"\x5b\x3d\x6b\xa2\x15\x8c\x26\x34\xe9\x84", 20
}, {
"sha1", 64, 4096,
"passwordPASSWORDpassword", 24,
"saltSALTsaltSALTsaltSALTsaltSALTsalt", 36,
"\x3d\x2e\xec\x4f\xe4\x1c\x84\x9b\x80\xc8"
"\xd8\x36\x62\xc0\xe4\x4a\x8b\x29\x1a\x96"
"\x4c\xf2\xf0\x70\x38", 25
}, {
"sha1", 64, 4096,
"pass\0word", 9,
"sa\0lt", 5,
"\x56\xfa\x6a\xa7\x55\x48\x09\x9d\xcc\x37"
"\xd7\xf0\x34\x25\xe0\xc3", 16
}, {
/* empty password test */
"sha1", 64, 2,
"", 0,
"salt", 4,
"\x13\x3a\x4c\xe8\x37\xb4\xd2\x52\x1e\xe2"
"\xbf\x03\xe1\x1c\x71\xca\x79\x4e\x07\x97", 20
}, {
/* Password exceeds block size test */
"sha256", 64, 1200,
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 65,
"pass phrase exceeds block size", 30,
"\x22\x34\x4b\xc4\xb6\xe3\x26\x75"
"\xa8\x09\x0f\x3e\xa8\x0b\xe0\x1d"
"\x5f\x95\x12\x6a\x2c\xdd\xc3\xfa"
"\xcc\x4a\x5e\x6d\xca\x04\xec\x58", 32
}, {
"sha512", 128, 1200,
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 129,
"pass phrase exceeds block size", 30,
"\x0f\xb2\xed\x2c\x0e\x6e\xfb\x7d"
"\x7d\x8e\xdd\x58\x01\xb4\x59\x72"
"\x99\x92\x16\x30\x5e\xa4\x36\x8d"
"\x76\x14\x80\xf3\xe3\x7a\x22\xb9", 32
}, {
"whirlpool", 64, 1200,
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 65,
"pass phrase exceeds block size", 30,
"\x9c\x1c\x74\xf5\x88\x26\xe7\x6a"
"\x53\x58\xf4\x0c\x39\xe7\x80\x89"
"\x07\xc0\x31\x19\x9a\x50\xa2\x48"
"\xf1\xd9\xfe\x78\x64\xe5\x84\x50", 32
}
};
static void printhex(const char *s, const char *buf, size_t len)
{
size_t i;
printf("%s: ", s);
for (i = 0; i < len; i++)
printf("\\x%02x", (unsigned char)buf[i]);
printf("\n");
fflush(stdout);
}
static int pkcs5_pbkdf2_test_vectors(void)
{
char result[64];
unsigned int i, j;
struct test_vector *vec;
for (i = 0; i < (sizeof(test_vectors) / sizeof(*test_vectors)); i++) {
vec = &test_vectors[i];
for (j = 1; j <= vec->output_length; j++) {
if (pkcs5_pbkdf2(vec->hash,
vec->password, vec->password_length,
vec->salt, vec->salt_length,
vec->iterations,
j, result, vec->hash_block_length)) {
printf("pbkdf2 failed, vector %d\n", i);
return -EINVAL;
}
if (memcmp(result, vec->output, j) != 0) {
printf("vector %u\n", i);
printhex(" got", result, j);
printhex("want", vec->output, j);
return -EINVAL;
}
memset(result, 0, sizeof(result));
}
}
return 0;
}
#endif

View File

@@ -1,7 +1,7 @@
/*
* PBKDF performance check
* Copyright (C) 2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2012, Milan Broz
* Copyright (C) 2012-2014, Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -25,12 +25,24 @@
static long time_ms(struct rusage *start, struct rusage *end)
{
int count_kernel_time = 0;
long ms;
if (crypt_backend_flags() & CRYPT_BACKEND_KERNEL)
count_kernel_time = 1;
/*
* FIXME: if there is no self usage info, count system time.
* This seem like getrusage() bug in some hypervisors...
*/
if (!end->ru_utime.tv_sec && !start->ru_utime.tv_sec &&
!end->ru_utime.tv_usec && !start->ru_utime.tv_usec)
count_kernel_time = 1;
ms = (end->ru_utime.tv_sec - start->ru_utime.tv_sec) * 1000;
ms += (end->ru_utime.tv_usec - start->ru_utime.tv_usec) / 1000;
if (crypt_backend_flags() & CRYPT_BACKEND_KERNEL) {
if (count_kernel_time) {
ms += (end->ru_stime.tv_sec - start->ru_stime.tv_sec) * 1000;
ms += (end->ru_stime.tv_usec - start->ru_stime.tv_usec) / 1000;
}

View File

@@ -1,7 +1,7 @@
/*
* libcryptsetup - cryptsetup library internal
*
* Copyright (C) 2004, Christophe Saout <christophe@saout.de>
* Copyright (C) 2004, Jana Saout <jana@saout.de>
* Copyright (C) 2004-2007, Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2012, Milan Broz
@@ -24,10 +24,6 @@
#ifndef INTERNAL_H
#define INTERNAL_H
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdint.h>
#include <stdarg.h>
#include <unistd.h>
@@ -96,7 +92,11 @@ struct device *crypt_data_device(struct crypt_device *cd);
int crypt_confirm(struct crypt_device *cd, const char *msg);
char *crypt_lookup_dev(const char *dev_id);
int crypt_sysfs_get_rotational(int major, int minor, int *rotational);
int crypt_dev_is_rotational(int major, int minor);
int crypt_dev_is_partition(const char *dev_path);
char *crypt_get_partition_device(const char *dev_path, uint64_t offset, uint64_t size);
char *crypt_get_base_device(const char *dev_path);
uint64_t crypt_dev_partition_offset(const char *dev_path);
ssize_t write_blockwise(int fd, int bsize, void *buf, size_t count);
ssize_t read_blockwise(int fd, int bsize, void *_buf, size_t count);
@@ -105,7 +105,7 @@ ssize_t write_lseek_blockwise(int fd, int bsize, char *buf, size_t count, off_t
unsigned crypt_getpagesize(void);
int init_crypto(struct crypt_device *ctx);
void logger(struct crypt_device *cd, int class, const char *file, int line, const char *format, ...);
void logger(struct crypt_device *cd, int class, const char *file, int line, const char *format, ...) __attribute__ ((format (printf, 5, 6)));
#define log_dbg(x...) logger(NULL, CRYPT_LOG_DEBUG, __FILE__, __LINE__, x)
#define log_std(c, x...) logger(c, CRYPT_LOG_NORMAL, __FILE__, __LINE__, x)
#define log_verbose(c, x...) logger(c, CRYPT_LOG_VERBOSE, __FILE__, __LINE__, x)

View File

@@ -1,10 +1,10 @@
/*
* libcryptsetup - cryptsetup library
*
* Copyright (C) 2004, Christophe Saout <christophe@saout.de>
* Copyright (C) 2004, Jana Saout <jana@saout.de>
* Copyright (C) 2004-2007, Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2012, Milan Broz
* Copyright (C) 2009-2015, Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2015, Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -176,6 +176,8 @@ void crypt_set_confirm_callback(struct crypt_device *cd,
* @note Only zero terminated passwords can be entered this way, for complex
* use API functions directly.
* @note Maximal length of password is limited to @e length @e - @e 1 (minimal 511 chars)
* @note Internal compiled-in terminal input is DEPRECATED and will be removed
* in future versions.
*
* @see Callback function is used in these call provided, that certain conditions are met:
* @li crypt_keyslot_add_by_passphrase
@@ -304,7 +306,7 @@ int crypt_memory_lock(struct crypt_device *cd, int lock);
#define CRYPT_LOOPAES "LOOPAES"
/** dm-verity mode */
#define CRYPT_VERITY "VERITY"
/** TCRYPT (TrueCrypt-compatible) mode */
/** TCRYPT (TrueCrypt-compatible and VeraCrypt-compatible) mode */
#define CRYPT_TCRYPT "TCRYPT"
/**
@@ -403,7 +405,7 @@ struct crypt_params_tcrypt {
uint32_t flags; /**< CRYPT_TCRYPT* flags */
};
/** Include legacy modes ehn scannig for header*/
/** Include legacy modes when scanning for header*/
#define CRYPT_TCRYPT_LEGACY_MODES (1 << 0)
/** Try to load hidden header (describing hidden device) */
#define CRYPT_TCRYPT_HIDDEN_HEADER (1 << 1)
@@ -411,6 +413,11 @@ struct crypt_params_tcrypt {
#define CRYPT_TCRYPT_BACKUP_HEADER (1 << 2)
/** Device contains encrypted system (with boot loader) */
#define CRYPT_TCRYPT_SYSTEM_HEADER (1 << 3)
/** Include VeraCrypt modes when scanning for header,
* all other TCRYPT flags applies as well.
* VeraCrypt device is reported as TCRYPT type.
*/
#define CRYPT_TCRYPT_VERA_MODES (1 << 4)
/** @} */
@@ -530,6 +537,8 @@ int crypt_suspend(struct crypt_device *cd,
* @return unlocked key slot number or negative errno otherwise.
*
* @note Only LUKS device type is supported
* @note If passphrase is @e NULL always use crypt_set_password_callback.
* Internal terminal password query is DEPRECATED and will be removed in next version.
*/
int crypt_resume_by_passphrase(struct crypt_device *cd,
const char *name,
@@ -548,6 +557,9 @@ int crypt_resume_by_passphrase(struct crypt_device *cd,
* @param keyfile_offset number of bytes to skip at start of keyfile
*
* @return unlocked key slot number or negative errno otherwise.
*
* @note If passphrase is @e NULL always use crypt_set_password_callback.
* Internal terminal password query is DEPRECATED and will be removed in next version.
*/
int crypt_resume_by_keyfile_offset(struct crypt_device *cd,
const char *name,
@@ -594,6 +606,9 @@ void crypt_free(struct crypt_device *cd);
* @param new_passphrase_size size of @e new_passphrase (binary data)
*
* @return allocated key slot number or negative errno otherwise.
*
* @note If passphrase is @e NULL always use crypt_set_password_callback.
* Internal terminal password query is DEPRECATED and will be removed in next version.
*/
int crypt_keyslot_add_by_passphrase(struct crypt_device *cd,
int keyslot,
@@ -620,6 +635,9 @@ int crypt_keyslot_add_by_passphrase(struct crypt_device *cd,
* @note This function is just internal implementation of luksChange
* command to avoid reading of volume key outside libcryptsetup boundary
* in FIPS mode.
*
* @note If passphrase is @e NULL always use crypt_set_password_callback.
* Internal terminal password query is DEPRECATED and will be removed in next version.
*/
int crypt_keyslot_change_by_passphrase(struct crypt_device *cd,
int keyslot_old,
@@ -646,7 +664,6 @@ int crypt_keyslot_change_by_passphrase(struct crypt_device *cd,
* @return allocated key slot number or negative errno otherwise.
*
* @note Note that @e keyfile can be "-" for STDIN
*
*/
int crypt_keyslot_add_by_keyfile_offset(struct crypt_device *cd,
int keyslot,
@@ -680,6 +697,8 @@ int crypt_keyslot_add_by_keyfile(struct crypt_device *cd,
*
* @return allocated key slot number or negative errno otherwise.
*
* @note If passphrase is @e NULL always use crypt_set_password_callback.
* Internal terminal password query is DEPRECATED and will be removed in next version.
*/
int crypt_keyslot_add_by_volume_key(struct crypt_device *cd,
int keyslot,
@@ -725,6 +744,11 @@ int crypt_keyslot_destroy(struct crypt_device *cd, int keyslot);
#define CRYPT_ACTIVATE_PRIVATE (1 << 4)
/** corruption detected (verity), output only */
#define CRYPT_ACTIVATE_CORRUPTED (1 << 5)
/** use same_cpu_crypt option for dm-crypt */
#define CRYPT_ACTIVATE_SAME_CPU_CRYPT (1 << 6)
/** use submit_from_crypt_cpus for dm-crypt */
#define CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS (1 << 7)
/**
* Active device runtime attributes
@@ -763,6 +787,9 @@ int crypt_get_active_device(struct crypt_device *cd,
* @param flags activation flags
*
* @return unlocked key slot number or negative errno otherwise.
*
* @note If passphrase is @e NULL always use crypt_set_password_callback.
* Internal terminal password query is DEPRECATED and will be removed in next version.
*/
int crypt_activate_by_passphrase(struct crypt_device *cd,
const char *name,
@@ -1019,6 +1046,9 @@ int crypt_get_verity_info(struct crypt_device *cd,
* @param decryption_mbs measured decryption speed in MiB/s
*
* @return @e 0 on success or negative errno value otherwise.
*
* @note If encryption_buffer_size is too small and encryption time
* cannot be properly measured, -ERANGE is returned.
*/
int crypt_benchmark(struct crypt_device *cd,
const char *cipher,

View File

@@ -1,10 +1,10 @@
/*
* libdevmapper - device-mapper backend for cryptsetup
*
* Copyright (C) 2004, Christophe Saout <christophe@saout.de>
* Copyright (C) 2004, Jana Saout <jana@saout.de>
* Copyright (C) 2004-2007, Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2012, Milan Broz
* Copyright (C) 2009-2015, Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2015, Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -85,12 +85,12 @@ static void set_dm_error(int level,
va_start(va, f);
if (vasprintf(&msg, f, va) > 0) {
if (level < 4 && !_quiet_log) {
log_err(_context, msg);
log_err(_context, "%s", msg);
log_err(_context, "\n");
} else {
/* We do not use DM visual stack backtrace here */
if (strncmp(msg, "<backtrace>", 11))
log_dbg(msg);
log_dbg("%s", msg);
}
}
free(msg);
@@ -99,6 +99,18 @@ static void set_dm_error(int level,
static int _dm_simple(int task, const char *name, int udev_wait);
static int _dm_satisfies_version(unsigned target_maj, unsigned target_min,
unsigned actual_maj, unsigned actual_min)
{
if (actual_maj > target_maj)
return 1;
if (actual_maj == target_maj && actual_min >= target_min)
return 1;
return 0;
}
static void _dm_set_crypt_compat(const char *dm_version, unsigned crypt_maj,
unsigned crypt_min, unsigned crypt_patch)
{
@@ -110,24 +122,32 @@ static void _dm_set_crypt_compat(const char *dm_version, unsigned crypt_maj,
log_dbg("Detected dm-crypt version %i.%i.%i, dm-ioctl version %u.%u.%u.",
crypt_maj, crypt_min, crypt_patch, dm_maj, dm_min, dm_patch);
if (crypt_maj >= 1 && crypt_min >= 2)
if (_dm_satisfies_version(1, 2, crypt_maj, crypt_min))
_dm_crypt_flags |= DM_KEY_WIPE_SUPPORTED;
else
log_dbg("Suspend and resume disabled, no wipe key support.");
if (crypt_maj >= 1 && crypt_min >= 10)
if (_dm_satisfies_version(1, 10, crypt_maj, crypt_min))
_dm_crypt_flags |= DM_LMK_SUPPORTED;
if (dm_maj >= 4 && dm_min >= 20)
if (_dm_satisfies_version(4, 20, dm_maj, dm_min))
_dm_crypt_flags |= DM_SECURE_SUPPORTED;
/* not perfect, 2.6.33 supports with 1.7.0 */
if (crypt_maj >= 1 && crypt_min >= 8)
if (_dm_satisfies_version(1, 8, crypt_maj, crypt_min))
_dm_crypt_flags |= DM_PLAIN64_SUPPORTED;
if (crypt_maj >= 1 && crypt_min >= 11)
if (_dm_satisfies_version(1, 11, crypt_maj, crypt_min))
_dm_crypt_flags |= DM_DISCARDS_SUPPORTED;
if (_dm_satisfies_version(1, 13, crypt_maj, crypt_min))
_dm_crypt_flags |= DM_TCW_SUPPORTED;
if (_dm_satisfies_version(1, 14, crypt_maj, crypt_min)) {
_dm_crypt_flags |= DM_SAME_CPU_CRYPT_SUPPORTED;
_dm_crypt_flags |= DM_SUBMIT_FROM_CRYPT_CPUS_SUPPORTED;
}
/* Repeat test if dm-crypt is not present */
if (crypt_maj > 0)
_dm_crypt_checked = 1;
@@ -277,23 +297,30 @@ static void hex_key(char *hexkey, size_t key_size, const char *key)
sprintf(&hexkey[i * 2], "%02x", (unsigned char)key[i]);
}
/* http://code.google.com/p/cryptsetup/wiki/DMCrypt */
static char *get_dm_crypt_params(struct crypt_dm_active_device *dmd)
/* https://gitlab.com/cryptsetup/cryptsetup/wikis/DMCrypt */
static char *get_dm_crypt_params(struct crypt_dm_active_device *dmd, uint32_t flags)
{
int r, max_size, null_cipher = 0;
int r, max_size, null_cipher = 0, num_options = 0;
char *params, *hexkey;
const char *features = "";
char features[256];
if (!dmd)
return NULL;
if (dmd->flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) {
if (dm_flags() & DM_DISCARDS_SUPPORTED) {
features = " 1 allow_discards";
log_dbg("Discard/TRIM is allowed.");
} else
log_dbg("Discard/TRIM is not supported by the kernel.");
}
if (flags & CRYPT_ACTIVATE_ALLOW_DISCARDS)
num_options++;
if (flags & CRYPT_ACTIVATE_SAME_CPU_CRYPT)
num_options++;
if (flags & CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS)
num_options++;
if (num_options)
snprintf(features, sizeof(features)-1, " %d%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" : "");
else
*features = '\0';
if (!strncmp(dmd->u.crypt.cipher, "cipher_null-", 12))
null_cipher = 1;
@@ -327,7 +354,7 @@ out:
return params;
}
/* http://code.google.com/p/cryptsetup/wiki/DMVerity */
/* https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity */
static char *get_dm_verity_params(struct crypt_params_verity *vp,
struct crypt_dm_active_device *dmd)
{
@@ -503,7 +530,7 @@ static int dm_prepare_uuid(const char *name, const char *type, const char *uuid,
if (uuid) {
if (uuid_parse(uuid, uu) < 0) {
log_dbg("Requested UUID %s has invalid format.", uuid);
return -EINVAL;
return 0;
}
for (ptr = uuid2, i = 0; i < UUID_LEN; i++)
@@ -522,7 +549,7 @@ static int dm_prepare_uuid(const char *name, const char *type, const char *uuid,
if (i >= buflen)
log_err(NULL, _("DM-UUID for device %s was truncated.\n"), name);
return 0;
return 1;
}
static int _dm_create_device(const char *name, const char *type,
@@ -538,6 +565,9 @@ static int _dm_create_device(const char *name, const char *type,
uint32_t cookie = 0;
uint16_t udev_flags = 0;
if (!params)
return -EINVAL;
if (flags & CRYPT_ACTIVATE_PRIVATE)
udev_flags = CRYPT_TEMP_UDEV_FLAGS;
@@ -549,9 +579,8 @@ static int _dm_create_device(const char *name, const char *type,
if (!dm_task_set_name(dmt, name))
goto out_no_removal;
} else {
r = dm_prepare_uuid(name, type, uuid, dev_uuid, sizeof(dev_uuid));
if (r < 0)
return r;
if (!dm_prepare_uuid(name, type, uuid, dev_uuid, sizeof(dev_uuid)))
goto out_no_removal;
if (!(dmt = dm_task_create(DM_DEVICE_CREATE)))
goto out_no_removal;
@@ -615,12 +644,14 @@ out_no_removal:
if (cookie && _dm_use_udev())
(void)_dm_udev_wait(cookie);
if (params)
crypt_safe_free(params);
if (dmt)
dm_task_destroy(dmt);
dm_task_update_nodes();
/* If code just loaded target module, update versions */
_dm_check_versions();
return r;
}
@@ -630,7 +661,8 @@ int dm_create_device(struct crypt_device *cd, const char *name,
int reload)
{
char *table_params = NULL;
int r = -EINVAL;
uint32_t dmd_flags;
int r;
if (!type)
return -EINVAL;
@@ -638,15 +670,34 @@ int dm_create_device(struct crypt_device *cd, const char *name,
if (dm_init_context(cd))
return -ENOTSUP;
dmd_flags = dmd->flags;
if (dmd->target == DM_CRYPT)
table_params = get_dm_crypt_params(dmd);
table_params = get_dm_crypt_params(dmd, dmd_flags);
else if (dmd->target == DM_VERITY)
table_params = get_dm_verity_params(dmd->u.verity.vp, dmd);
if (table_params)
r = _dm_create_device(name, type, dmd->data_device,
dmd->flags, dmd->uuid, dmd->size,
table_params, reload);
r = _dm_create_device(name, type, dmd->data_device, dmd_flags,
dmd->uuid, dmd->size, table_params, reload);
/* If discard not supported try to load without discard */
if (!reload && r && dmd->target == DM_CRYPT &&
(dmd->flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) &&
!(dm_flags() & DM_DISCARDS_SUPPORTED)) {
log_dbg("Discard/TRIM is not supported, retrying activation.");
dmd_flags = dmd_flags & ~CRYPT_ACTIVATE_ALLOW_DISCARDS;
crypt_safe_free(table_params);
table_params = get_dm_crypt_params(dmd, dmd_flags);
r = _dm_create_device(name, type, dmd->data_device, dmd_flags,
dmd->uuid, dmd->size, table_params, reload);
}
if (r == -EINVAL &&
dmd_flags & (CRYPT_ACTIVATE_SAME_CPU_CRYPT|CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS) &&
!(dm_flags() & (DM_SAME_CPU_CRYPT_SUPPORTED|DM_SUBMIT_FROM_CRYPT_CPUS_SUPPORTED)))
log_err(cd, _("Requested dmcrypt performance options are not supported.\n"));
crypt_safe_free(table_params);
dm_exit_context();
return r;
}
@@ -833,6 +884,10 @@ static int _dm_query_crypt(uint32_t get_flags,
arg = strsep(&params, " ");
if (!strcasecmp(arg, "allow_discards"))
dmd->flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS;
else if (!strcasecmp(arg, "same_cpu_crypt"))
dmd->flags |= CRYPT_ACTIVATE_SAME_CPU_CRYPT;
else if (!strcasecmp(arg, "submit_from_crypt_cpus"))
dmd->flags |= CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS;
else /* unknown option */
return -EINVAL;
}

View File

@@ -2,15 +2,13 @@ moduledir = $(libdir)/cryptsetup
noinst_LTLIBRARIES = libloopaes.la
libloopaes_la_CFLAGS = -Wall @CRYPTO_CFLAGS@
libloopaes_la_CFLAGS = -Wall $(AM_CFLAGS) @CRYPTO_CFLAGS@
libloopaes_la_SOURCES = \
loopaes.c \
loopaes.h
AM_CPPFLAGS = -D_GNU_SOURCE \
-D_LARGEFILE64_SOURCE \
-D_FILE_OFFSET_BITS=64 \
AM_CPPFLAGS = -include config.h \
-I$(top_srcdir)/lib \
-I$(top_srcdir)/lib/crypto_backend

View File

@@ -137,7 +137,7 @@ int LOOPAES_parse_keyfile(struct crypt_device *cd,
unsigned int key_lengths[LOOPAES_KEYS_MAX];
unsigned int i, key_index, key_len, offset;
log_dbg("Parsing loop-AES keyfile of size %d.", buffer_len);
log_dbg("Parsing loop-AES keyfile of size %zu.", buffer_len);
if (!buffer_len)
return -EINVAL;

View File

@@ -23,7 +23,6 @@
#define _LOOPAES_H
#include <unistd.h>
#include "config.h"
struct crypt_device;
struct volume_key;

View File

@@ -2,7 +2,7 @@ moduledir = $(libdir)/cryptsetup
noinst_LTLIBRARIES = libluks1.la
libluks1_la_CFLAGS = -Wall @CRYPTO_CFLAGS@
libluks1_la_CFLAGS = -Wall $(AM_CFLAGS) @CRYPTO_CFLAGS@
libluks1_la_SOURCES = \
af.c \
@@ -11,9 +11,7 @@ libluks1_la_SOURCES = \
af.h \
luks.h
AM_CPPFLAGS = -D_GNU_SOURCE \
-D_LARGEFILE64_SOURCE \
-D_FILE_OFFSET_BITS=64 \
AM_CPPFLAGS = -include config.h \
-I$(top_srcdir)/lib \
-I$(top_srcdir)/lib/crypto_backend

View File

@@ -3,6 +3,7 @@
*
* Copyright (C) 2004-2006, Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2014, 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,8 +27,13 @@
#include "internal.h"
static void _error_hint(struct crypt_device *ctx, const char *device,
const char *cipher_spec, const char *mode, size_t keyLength)
const char *cipher, const char *mode, size_t keyLength)
{
char cipher_spec[MAX_CIPHER_LEN * 3];
if (snprintf(cipher_spec, sizeof(cipher_spec), "%s-%s", cipher, mode) < 0)
return;
log_err(ctx, _("Failed to setup dm-crypt key mapping for device %s.\n"
"Check that kernel supports %s cipher (check syslog for more info).\n"),
device, cipher_spec);
@@ -60,6 +66,8 @@ static int LUKS_endec_template(char *src, size_t srcLength,
};
int r, bsize, devfd = -1;
log_dbg("Using dmcrypt to access keyslot area.");
bsize = device_block_size(dmd.data_device);
if (bsize <= 0)
return -EINVAL;
@@ -94,7 +102,7 @@ static int LUKS_endec_template(char *src, size_t srcLength,
if (r < 0) {
if (r != -EACCES && r != -ENOTSUP)
_error_hint(ctx, device_path(dmd.data_device),
cipher_spec, cipher_mode, vk->keylength * 8);
cipher, cipher_mode, vk->keylength * 8);
return -EIO;
}
@@ -125,8 +133,64 @@ int LUKS_encrypt_to_storage(char *src, size_t srcLength,
unsigned int sector,
struct crypt_device *ctx)
{
return LUKS_endec_template(src, srcLength, cipher, cipher_mode,
vk, sector, write_blockwise, O_RDWR, ctx);
struct device *device = crypt_metadata_device(ctx);
struct crypt_storage *s;
int devfd = -1, bsize, r = 0;
/* Only whole sector writes supported */
if (srcLength % SECTOR_SIZE)
return -EINVAL;
/* Encrypt buffer */
r = crypt_storage_init(&s, 0, cipher, cipher_mode, vk->key, vk->keylength);
if (r)
log_dbg("Userspace crypto wrapper cannot use %s-%s (%d).",
cipher, cipher_mode, r);
/* Fallback to old temporary dmcrypt device */
if (r == -ENOTSUP || r == -ENOENT)
return LUKS_endec_template(src, srcLength, cipher, cipher_mode,
vk, sector, write_blockwise, O_RDWR, ctx);
if (r) {
_error_hint(ctx, device_path(device), cipher, cipher_mode,
vk->keylength * 8);
return r;
}
log_dbg("Using userspace crypto wrapper to access keyslot area.");
r = crypt_storage_encrypt(s, 0, srcLength / SECTOR_SIZE, src);
crypt_storage_destroy(s);
if (r)
return r;
r = -EIO;
/* Write buffer to device */
bsize = device_block_size(device);
if (bsize <= 0)
goto out;
devfd = device_open(device, O_RDWR);
if (devfd == -1)
goto out;
if (lseek(devfd, sector * SECTOR_SIZE, SEEK_SET) == -1 ||
write_blockwise(devfd, bsize, src, srcLength) == -1)
goto out;
r = 0;
out:
if(devfd != -1)
close(devfd);
if (r)
log_err(ctx, _("IO error while encrypting keyslot.\n"));
return r;
}
int LUKS_decrypt_from_storage(char *dst, size_t dstLength,
@@ -136,6 +200,61 @@ int LUKS_decrypt_from_storage(char *dst, size_t dstLength,
unsigned int sector,
struct crypt_device *ctx)
{
return LUKS_endec_template(dst, dstLength, cipher, cipher_mode,
vk, sector, read_blockwise, O_RDONLY, ctx);
struct device *device = crypt_metadata_device(ctx);
struct crypt_storage *s;
int devfd = -1, bsize, r = 0;
/* Only whole sector reads supported */
if (dstLength % SECTOR_SIZE)
return -EINVAL;
r = crypt_storage_init(&s, 0, cipher, cipher_mode, vk->key, vk->keylength);
if (r)
log_dbg("Userspace crypto wrapper cannot use %s-%s (%d).",
cipher, cipher_mode, r);
/* Fallback to old temporary dmcrypt device */
if (r == -ENOTSUP || r == -ENOENT)
return LUKS_endec_template(dst, dstLength, cipher, cipher_mode,
vk, sector, read_blockwise, O_RDONLY, ctx);
if (r) {
_error_hint(ctx, device_path(device), cipher, cipher_mode,
vk->keylength * 8);
return r;
}
log_dbg("Using userspace crypto wrapper to access keyslot area.");
r = -EIO;
/* Read buffer from device */
bsize = device_block_size(device);
if (bsize <= 0)
goto bad;
devfd = device_open(device, O_RDONLY);
if (devfd == -1)
goto bad;
if (lseek(devfd, sector * SECTOR_SIZE, SEEK_SET) == -1 ||
read_blockwise(devfd, bsize, dst, dstLength) == -1)
goto bad;
close(devfd);
/* Decrypt buffer */
r = crypt_storage_decrypt(s, 0, dstLength / SECTOR_SIZE, dst);
crypt_storage_destroy(s);
return r;
bad:
if(devfd != -1)
close(devfd);
log_err(ctx, _("IO error while decrypting keyslot.\n"));
crypt_storage_destroy(s);
return r;
}

View File

@@ -3,6 +3,7 @@
*
* Copyright (C) 2004-2006, Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2013-2014, Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -82,11 +83,12 @@ static int LUKS_check_device_size(struct crypt_device *ctx, size_t keyLength)
dev_sectors >>= SECTOR_SHIFT;
hdr_sectors = LUKS_device_sectors(keyLength);
log_dbg("Key length %u, device size %" PRIu64 " sectors, header size %"
log_dbg("Key length %zu, device size %" PRIu64 " sectors, header size %"
PRIu64 " sectors.",keyLength, dev_sectors, hdr_sectors);
if (hdr_sectors > dev_sectors) {
log_err(ctx, _("Device %s is too small.\n"), device_path(device));
log_err(ctx, _("Device %s is too small. (LUKS requires at least %" PRIu64 " bytes.)\n"),
device_path(device), hdr_sectors * SECTOR_SIZE);
return -EINVAL;
}
@@ -146,29 +148,32 @@ static const char *dbg_slot_state(crypt_keyslot_info ki)
}
}
int LUKS_hdr_backup(
const char *backup_file,
struct luks_phdr *hdr,
struct crypt_device *ctx)
int LUKS_hdr_backup(const char *backup_file, struct crypt_device *ctx)
{
struct device *device = crypt_metadata_device(ctx);
struct luks_phdr hdr;
int r = 0, devfd = -1;
ssize_t hdr_size;
ssize_t buffer_size;
char *buffer = NULL;
r = LUKS_read_phdr(hdr, 1, 0, ctx);
r = LUKS_read_phdr(&hdr, 1, 0, ctx);
if (r)
return r;
buffer_size = LUKS_device_sectors(hdr->keyBytes) << SECTOR_SHIFT;
hdr_size = LUKS_device_sectors(hdr.keyBytes) << SECTOR_SHIFT;
buffer_size = size_round_up(hdr_size, crypt_getpagesize());
buffer = crypt_safe_alloc(buffer_size);
if (!buffer || buffer_size < LUKS_ALIGN_KEYSLOTS) {
if (!buffer || hdr_size < LUKS_ALIGN_KEYSLOTS || hdr_size > buffer_size) {
r = -ENOMEM;
goto out;
}
log_dbg("Storing backup of header (%u bytes) and keyslot area (%u bytes).",
sizeof(*hdr), buffer_size - LUKS_ALIGN_KEYSLOTS);
log_dbg("Storing backup of header (%zu bytes) and keyslot area (%zu bytes).",
sizeof(hdr), hdr_size - LUKS_ALIGN_KEYSLOTS);
log_dbg("Output backup file size: %zu bytes.", buffer_size);
devfd = device_open(device, O_RDONLY);
if(devfd == -1) {
@@ -177,15 +182,15 @@ int LUKS_hdr_backup(
goto out;
}
if (read_blockwise(devfd, device_block_size(device), buffer, buffer_size) < buffer_size) {
if (read_blockwise(devfd, device_block_size(device), buffer, hdr_size) < hdr_size) {
r = -EIO;
goto out;
}
close(devfd);
/* Wipe unused area, so backup cannot contain old signatures */
if (hdr->keyblock[0].keyMaterialOffset * SECTOR_SIZE == LUKS_ALIGN_KEYSLOTS)
memset(buffer + sizeof(*hdr), 0, LUKS_ALIGN_KEYSLOTS - sizeof(*hdr));
if (hdr.keyblock[0].keyMaterialOffset * SECTOR_SIZE == LUKS_ALIGN_KEYSLOTS)
memset(buffer + sizeof(hdr), 0, LUKS_ALIGN_KEYSLOTS - sizeof(hdr));
devfd = open(backup_file, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR);
if (devfd == -1) {
@@ -207,6 +212,7 @@ int LUKS_hdr_backup(
out:
if (devfd != -1)
close(devfd);
crypt_memzero(&hdr, sizeof(hdr));
crypt_safe_free(buffer);
return r;
}
@@ -281,7 +287,7 @@ int LUKS_hdr_restore(
goto out;
}
log_dbg("Storing backup of header (%u bytes) and keyslot area (%u bytes) to device %s.",
log_dbg("Storing backup of header (%zu bytes) and keyslot area (%zu bytes) to device %s.",
sizeof(*hdr), buffer_size - LUKS_ALIGN_KEYSLOTS, device_path(device));
devfd = device_open(device, O_RDWR);
@@ -392,7 +398,7 @@ static int _keyslot_repair(struct luks_phdr *phdr, struct crypt_device *ctx)
}
out:
crypt_free_volume_key(vk);
memset(&temp_phdr, 0, sizeof(temp_phdr));
crypt_memzero(&temp_phdr, sizeof(temp_phdr));
return r;
}
@@ -465,6 +471,13 @@ static void LUKS_fix_header_compatible(struct luks_phdr *header)
/* Old cryptsetup expects "sha1", gcrypt allows case insensistive names,
* so always convert hash to lower case in header */
_to_lower(header->hashSpec, LUKS_HASHSPEC_L);
/* ECB mode does not use IV but dmcrypt silently allows it.
* Drop any IV here if ECB is used (that is not secure anyway).*/
if (!strncmp(header->cipherMode, "ecb-", 4)) {
memset(header->cipherMode, 0, LUKS_CIPHERMODE_L);
strcpy(header->cipherMode, "ecb");
}
}
int LUKS_read_phdr_backup(const char *backup_file,
@@ -514,7 +527,7 @@ int LUKS_read_phdr(struct luks_phdr *hdr,
if (repair && !require_luks_device)
return -EINVAL;
log_dbg("Reading LUKS header of size %d from device %s",
log_dbg("Reading LUKS header of size %zu from device %s",
hdr_size, device_path(device));
devfd = device_open(device, O_RDONLY);
@@ -546,7 +559,7 @@ int LUKS_write_phdr(struct luks_phdr *hdr,
struct luks_phdr convHdr;
int r;
log_dbg("Updating LUKS header of size %d on device %s",
log_dbg("Updating LUKS header of size %zu on device %s",
sizeof(struct luks_phdr), device_path(device));
r = LUKS_check_device_size(ctx, hdr->keyBytes);
@@ -594,6 +607,28 @@ int LUKS_write_phdr(struct luks_phdr *hdr,
return r;
}
/* Check that kernel supports requested cipher by decryption of one sector */
static int LUKS_check_cipher(struct luks_phdr *hdr, struct crypt_device *ctx)
{
int r;
struct volume_key *empty_key;
char buf[SECTOR_SIZE];
log_dbg("Checking if cipher %s-%s is usable.", hdr->cipherName, hdr->cipherMode);
empty_key = crypt_alloc_volume_key(hdr->keyBytes, NULL);
if (!empty_key)
return -ENOMEM;
r = LUKS_decrypt_from_storage(buf, sizeof(buf),
hdr->cipherName, hdr->cipherMode,
empty_key, 0, ctx);
crypt_free_volume_key(empty_key);
crypt_memzero(buf, sizeof(buf));
return r;
}
int LUKS_generate_phdr(struct luks_phdr *header,
const struct volume_key *vk,
const char *cipherName, const char *cipherMode, const char *hashSpec,
@@ -605,7 +640,7 @@ int LUKS_generate_phdr(struct luks_phdr *header,
int detached_metadata_device,
struct crypt_device *ctx)
{
unsigned int i=0;
unsigned int i = 0, hdr_sectors = LUKS_device_sectors(vk->keylength);
size_t blocksPerStripeSet, currentSector;
int r;
uuid_t partitionUuid;
@@ -615,6 +650,13 @@ int LUKS_generate_phdr(struct luks_phdr *header,
if (alignPayload == 0 && !detached_metadata_device)
alignPayload = DEFAULT_DISK_ALIGNMENT / SECTOR_SIZE;
if (alignPayload && detached_metadata_device && alignPayload < hdr_sectors) {
log_err(ctx, _("Data offset for detached LUKS header must be "
"either 0 or higher than header size (%d sectors).\n"),
hdr_sectors);
return -EINVAL;
}
if (crypt_hmac_size(hashSpec) < LUKS_DIGESTSIZE) {
log_err(ctx, _("Requested LUKS hash %s is not supported.\n"), hashSpec);
return -EINVAL;
@@ -640,6 +682,10 @@ int LUKS_generate_phdr(struct luks_phdr *header,
LUKS_fix_header_compatible(header);
r = LUKS_check_cipher(header, ctx);
if (r < 0)
return r;
log_dbg("Generating LUKS header version %d using hash %s, %s, %s, MK %d bytes",
header->version, header->hashSpec ,header->cipherName, header->cipherMode,
header->keyBytes);
@@ -765,7 +811,7 @@ int LUKS_set_key(unsigned int keyIndex,
hdr->keyblock[keyIndex].passwordIterations = at_least((uint32_t)PBKDF2_temp,
LUKS_SLOT_ITERATIONS_MIN);
log_dbg("Key slot %d use %d password iterations.", keyIndex, hdr->keyblock[keyIndex].passwordIterations);
log_dbg("Key slot %d use %" PRIu32 " password iterations.", keyIndex, hdr->keyblock[keyIndex].passwordIterations);
derived_key = crypt_alloc_volume_key(hdr->keyBytes, NULL);
if (!derived_key)

View File

@@ -130,7 +130,6 @@ int LUKS_hdr_uuid_set(
int LUKS_hdr_backup(
const char *backup_file,
struct luks_phdr *hdr,
struct crypt_device *ctx);
int LUKS_hdr_restore(

View File

@@ -1,10 +1,10 @@
/*
* libcryptsetup - cryptsetup library
*
* Copyright (C) 2004, Christophe Saout <christophe@saout.de>
* Copyright (C) 2004, Jana Saout <jana@saout.de>
* Copyright (C) 2004-2007, Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2013, Milan Broz
* Copyright (C) 2009-2014, Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -25,6 +25,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <sys/utsname.h>
#include <fcntl.h>
#include <errno.h>
@@ -78,6 +79,13 @@ struct crypt_device {
struct crypt_params_tcrypt params;
struct tcrypt_phdr hdr;
} tcrypt;
struct { /* used if initialized without header by name */
char *active_name;
/* buffers, must refresh from kernel on every query */
char cipher[MAX_CIPHER_LEN];
char cipher_mode[MAX_CIPHER_LEN];
unsigned int key_size;
} none;
} u;
/* callbacks definitions */
@@ -92,6 +100,9 @@ struct crypt_device {
char error[MAX_ERROR_LENGTH];
};
/* Just to suppress redundant messages about crypto backend */
static int _crypto_logged = 0;
/* Global error */
/* FIXME: not thread safe, remove this later */
static char global_error[MAX_ERROR_LENGTH] = {0};
@@ -181,10 +192,9 @@ struct device *crypt_data_device(struct crypt_device *cd)
int init_crypto(struct crypt_device *ctx)
{
struct utsname uts;
int r;
crypt_fips_libcryptsetup_check(ctx);
r = crypt_random_init(ctx);
if (r < 0) {
log_err(ctx, _("Cannot initialize crypto RNG backend.\n"));
@@ -195,7 +205,14 @@ int init_crypto(struct crypt_device *ctx)
if (r < 0)
log_err(ctx, _("Cannot initialize crypto backend.\n"));
log_dbg("Crypto backend (%s) initialized.", crypt_backend_version());
if (!r && !_crypto_logged) {
log_dbg("Crypto backend (%s) initialized.", crypt_backend_version());
if (!uname(&uts))
log_dbg("Detected kernel %s %s %s.",
uts.sysname, uts.release, uts.machine);
_crypto_logged = 1;
}
return r;
}
@@ -259,6 +276,41 @@ static int isTCRYPT(const char *type)
return (type && !strcmp(CRYPT_TCRYPT, type));
}
static int onlyLUKS(struct crypt_device *cd)
{
int r = 0;
if (cd && !cd->type) {
log_err(cd, _("Cannot determine device type. Incompatible activation of device?\n"));
r = -EINVAL;
}
if (!cd || !isLUKS(cd->type)) {
log_err(cd, _("This operation is supported only for LUKS device.\n"));
r = -EINVAL;
}
return r;
}
static void crypt_set_null_type(struct crypt_device *cd)
{
if (!cd->type)
return;
free(cd->type);
cd->type = NULL;
cd->u.none.active_name = NULL;
}
static void crypt_reset_null_type(struct crypt_device *cd)
{
if (cd->type)
return;
free(cd->u.none.active_name);
cd->u.none.active_name = NULL;
}
/* keyslot helpers */
static int keyslot_verify_or_find_empty(struct crypt_device *cd, int *keyslot)
{
@@ -316,6 +368,36 @@ static int crypt_uuid_cmp(const char *dm_uuid, const char *hdr_uuid)
return 0;
}
/*
* compares type of active device to provided string (only if there is no explicit type)
*/
static int crypt_uuid_type_cmp(struct crypt_device *cd, const char *type)
{
struct crypt_dm_active_device dmd = {};
size_t len;
int r;
/* Must user header-on-disk if we know type here */
if (cd->type || !cd->u.none.active_name)
return -EINVAL;
log_dbg("Checking if active device %s without header has UUID type %s.",
cd->u.none.active_name, type);
r = dm_query_device(cd, cd->u.none.active_name, DM_ACTIVE_UUID, &dmd);
if (r < 0)
return r;
r = -ENODEV;
len = strlen(type);
if (dmd.uuid && strlen(dmd.uuid) > len &&
!strncmp(dmd.uuid, type, len) && dmd.uuid[len] == '-')
r = 0;
free(CONST_CAST(void*)dmd.uuid);
return r;
}
int PLAIN_activate(struct crypt_device *cd,
const char *name,
struct volume_key *vk,
@@ -706,6 +788,8 @@ static int _init_by_name_crypt(struct crypt_device *cd, const char *name)
DM_ACTIVE_CRYPT_KEYSIZE, &dmd);
if (r < 0)
goto out;
if (r > 0)
r = 0;
if (isPLAIN(cd->type)) {
cd->u.plain.hdr.hash = NULL; /* no way to get this */
@@ -736,8 +820,7 @@ static int _init_by_name_crypt(struct crypt_device *cd, const char *name)
r = _crypt_load_luks1(cd, 0, 0);
if (r < 0) {
log_dbg("LUKS device header does not match active device.");
free(cd->type);
cd->type = NULL;
crypt_set_null_type(cd);
r = 0;
goto out;
}
@@ -746,14 +829,12 @@ static int _init_by_name_crypt(struct crypt_device *cd, const char *name)
if (r < 0) {
log_dbg("LUKS device header uuid: %s mismatches DM returned uuid %s",
cd->u.luks1.hdr.uuid, dmd.uuid);
free(cd->type);
cd->type = NULL;
crypt_set_null_type(cd);
r = 0;
}
} else {
log_dbg("LUKS device header not available.");
free(cd->type);
cd->type = NULL;
crypt_set_null_type(cd);
r = 0;
}
} else if (isTCRYPT(cd->type)) {
@@ -783,6 +864,8 @@ static int _init_by_name_verity(struct crypt_device *cd, const char *name)
DM_ACTIVE_VERITY_PARAMS, &dmd);
if (r < 0)
goto out;
if (r > 0)
r = 0;
if (isVERITY(cd->type)) {
cd->u.verity.uuid = NULL; // FIXME
@@ -885,7 +968,11 @@ out:
if (r < 0) {
crypt_free(*cd);
*cd = NULL;
} else if (!(*cd)->type && name) {
/* For anonymous device (no header found) remember initialized name */
(*cd)->u.none.active_name = strdup(name);
}
device_free(dmd.data_device);
free(CONST_CAST(void*)dmd.uuid);
return r;
@@ -985,11 +1072,6 @@ static int _crypt_format_luks1(struct crypt_device *cd,
&required_alignment,
&alignment_offset, DEFAULT_DISK_ALIGNMENT);
/* Check early if we cannot allocate block device for key slot access */
r = device_block_adjust(cd, cd->device, DEV_OK, 0, NULL, NULL);
if(r < 0)
return r;
r = LUKS_generate_phdr(&cd->u.luks1.hdr, cd->volume_key, cipher, cipher_mode,
(params && params->hash) ? params->hash : "sha1",
uuid, LUKS_STRIPES,
@@ -1183,6 +1265,8 @@ int crypt_format(struct crypt_device *cd,
log_dbg("Formatting device %s as type %s.", mdata_device_path(cd) ?: "(none)", type);
crypt_reset_null_type(cd);
r = init_crypto(cd);
if (r < 0)
return r;
@@ -1203,8 +1287,7 @@ int crypt_format(struct crypt_device *cd,
}
if (r < 0) {
free(cd->type);
cd->type = NULL;
crypt_set_null_type(cd);
crypt_free_volume_key(cd->volume_key);
cd->volume_key = NULL;
}
@@ -1224,6 +1307,8 @@ int crypt_load(struct crypt_device *cd,
if (!crypt_metadata_device(cd))
return -EINVAL;
crypt_reset_null_type(cd);
if (!requested_type || isLUKS(requested_type)) {
if (cd->type && !isLUKS(cd->type)) {
log_dbg("Context is already initialised to type %s", cd->type);
@@ -1272,10 +1357,8 @@ int crypt_repair(struct crypt_device *cd,
/* cd->type and header must be set in context */
r = crypt_check_data_device_size(cd);
if (r < 0) {
free(cd->type);
cd->type = NULL;
}
if (r < 0)
crypt_set_null_type(cd);
return r;
}
@@ -1364,6 +1447,9 @@ int crypt_header_backup(struct crypt_device *cd,
if ((requested_type && !isLUKS(requested_type)) || !backup_file)
return -EINVAL;
if (cd->type && !isLUKS(cd->type))
return -EINVAL;
r = init_crypto(cd);
if (r < 0)
return r;
@@ -1371,13 +1457,15 @@ int crypt_header_backup(struct crypt_device *cd,
log_dbg("Requested header backup of device %s (%s) to "
"file %s.", mdata_device_path(cd), requested_type, backup_file);
return LUKS_hdr_backup(backup_file, &cd->u.luks1.hdr, cd);
r = LUKS_hdr_backup(backup_file, cd);
return r;
}
int crypt_header_restore(struct crypt_device *cd,
const char *requested_type,
const char *backup_file)
{
struct luks_phdr hdr;
int r;
if (requested_type && !isLUKS(requested_type))
@@ -1393,7 +1481,10 @@ int crypt_header_restore(struct crypt_device *cd,
log_dbg("Requested header restore to device %s (%s) from "
"file %s.", mdata_device_path(cd), requested_type, backup_file);
return LUKS_hdr_restore(backup_file, &cd->u.luks1.hdr, cd);
r = LUKS_hdr_restore(backup_file, isLUKS(cd->type) ? &cd->u.luks1.hdr : &hdr, cd);
crypt_memzero(&hdr, sizeof(hdr));
return r;
}
void crypt_free(struct crypt_device *cd)
@@ -1419,11 +1510,13 @@ void crypt_free(struct crypt_device *cd)
free(CONST_CAST(void*)cd->u.verity.hdr.salt);
free(cd->u.verity.root_hash);
free(cd->u.verity.uuid);
} else if (!cd->type) {
free(cd->u.none.active_name);
}
free(cd->type);
/* Some structures can contain keys (TCRYPT), wipe it */
memset(cd, 0, sizeof(*cd));
crypt_memzero(cd, sizeof(*cd));
free(cd);
}
}
@@ -1436,12 +1529,17 @@ int crypt_suspend(struct crypt_device *cd,
log_dbg("Suspending volume %s.", name);
if (!cd || !isLUKS(cd->type)) {
log_err(cd, _("This operation is supported only for LUKS device.\n"));
r = -EINVAL;
goto out;
if (cd->type) {
r = onlyLUKS(cd);
} else {
r = crypt_uuid_type_cmp(cd, CRYPT_LUKS1);
if (r < 0)
log_err(cd, _("This operation is supported only for LUKS device.\n"));
}
if (r < 0)
return r;
ci = crypt_status(NULL, name);
if (ci < CRYPT_ACTIVE) {
log_err(cd, _("Volume %s is not active.\n"), name);
@@ -1481,11 +1579,9 @@ int crypt_resume_by_passphrase(struct crypt_device *cd,
log_dbg("Resuming volume %s.", name);
if (!isLUKS(cd->type)) {
log_err(cd, _("This operation is supported only for LUKS device.\n"));
r = -EINVAL;
goto out;
}
r = onlyLUKS(cd);
if (r < 0)
return r;
r = dm_status_suspended(cd, name);
if (r < 0)
@@ -1511,7 +1607,7 @@ int crypt_resume_by_passphrase(struct crypt_device *cd,
log_err(cd, _("Error during resuming device %s.\n"), name);
} else
r = keyslot;
out:
crypt_free_volume_key(vk);
return r < 0 ? r : keyslot;
}
@@ -1530,11 +1626,9 @@ int crypt_resume_by_keyfile_offset(struct crypt_device *cd,
log_dbg("Resuming volume %s.", name);
if (!isLUKS(cd->type)) {
log_err(cd, _("This operation is supported only for LUKS device.\n"));
r = -EINVAL;
goto out;
}
r = onlyLUKS(cd);
if (r < 0)
return r;
r = dm_status_suspended(cd, name);
if (r < 0)
@@ -1596,10 +1690,9 @@ int crypt_keyslot_add_by_passphrase(struct crypt_device *cd,
"new passphrase %sprovided.",
passphrase ? "" : "not ", new_passphrase ? "" : "not ");
if (!isLUKS(cd->type)) {
log_err(cd, _("This operation is supported only for LUKS device.\n"));
return -EINVAL;
}
r = onlyLUKS(cd);
if (r < 0)
return r;
r = keyslot_verify_or_find_empty(cd, &keyslot);
if (r)
@@ -1645,14 +1738,15 @@ int crypt_keyslot_add_by_passphrase(struct crypt_device *cd,
r = LUKS_set_key(keyslot, new_password, new_passwordLen,
&cd->u.luks1.hdr, vk, cd->iteration_time, &cd->u.luks1.PBKDF2_per_sec, cd);
if(r < 0) goto out;
if(r < 0)
goto out;
r = 0;
out:
if (!new_passphrase)
crypt_safe_free(new_password);
crypt_free_volume_key(vk);
return r ?: keyslot;
return r < 0 ? r : keyslot;
}
int crypt_keyslot_change_by_passphrase(struct crypt_device *cd,
@@ -1664,15 +1758,14 @@ int crypt_keyslot_change_by_passphrase(struct crypt_device *cd,
size_t new_passphrase_size)
{
struct volume_key *vk = NULL;
int r = -EINVAL;
int r;
log_dbg("Changing passphrase from old keyslot %d to new %d.",
keyslot_old, keyslot_new);
if (!isLUKS(cd->type)) {
log_err(cd, _("This operation is supported only for LUKS device.\n"));
return -EINVAL;
}
r = onlyLUKS(cd);
if (r < 0)
return r;
r = LUKS_open_key_with_hdr(keyslot_old, passphrase, passphrase_size,
&cd->u.luks1.hdr, &vk, cd);
@@ -1702,10 +1795,10 @@ int crypt_keyslot_change_by_passphrase(struct crypt_device *cd,
if (keyslot_old == keyslot_new) {
if (r >= 0)
log_verbose(cd, _("Key slot %d changed.\n"), r);
log_verbose(cd, _("Key slot %d changed.\n"), keyslot_new);
} else {
if (r >= 0) {
log_verbose(cd, _("Replaced with key slot %d.\n"), r);
log_verbose(cd, _("Replaced with key slot %d.\n"), keyslot_new);
r = crypt_keyslot_destroy(cd, keyslot_old);
}
}
@@ -1713,7 +1806,7 @@ int crypt_keyslot_change_by_passphrase(struct crypt_device *cd,
log_err(cd, _("Failed to swap new key slot.\n"));
out:
crypt_free_volume_key(vk);
return r ?: keyslot_new;
return r < 0 ? r : keyslot_new;
}
int crypt_keyslot_add_by_keyfile_offset(struct crypt_device *cd,
@@ -1733,10 +1826,9 @@ int crypt_keyslot_add_by_keyfile_offset(struct crypt_device *cd,
log_dbg("Adding new keyslot, existing keyfile %s, new keyfile %s.",
keyfile ?: "[none]", new_keyfile ?: "[none]");
if (!isLUKS(cd->type)) {
log_err(cd, _("This operation is supported only for LUKS device.\n"));
return -EINVAL;
}
r = onlyLUKS(cd);
if (r < 0)
return r;
r = keyslot_verify_or_find_empty(cd, &keyslot);
if (r)
@@ -1809,15 +1901,14 @@ int crypt_keyslot_add_by_volume_key(struct crypt_device *cd,
size_t passphrase_size)
{
struct volume_key *vk = NULL;
int r = -EINVAL;
int r;
char *new_password = NULL; size_t new_passwordLen;
log_dbg("Adding new keyslot %d using volume key.", keyslot);
if (!isLUKS(cd->type)) {
log_err(cd, _("This operation is supported only for LUKS device.\n"));
return -EINVAL;
}
r = onlyLUKS(cd);
if (r < 0)
return r;
if (volume_key)
vk = crypt_alloc_volume_key(volume_key_size, volume_key);
@@ -1857,13 +1948,13 @@ out:
int crypt_keyslot_destroy(struct crypt_device *cd, int keyslot)
{
crypt_keyslot_info ki;
int r;
log_dbg("Destroying keyslot %d.", keyslot);
if (!isLUKS(cd->type)) {
log_err(cd, _("This operation is supported only for LUKS device.\n"));
return -EINVAL;
}
r = onlyLUKS(cd);
if (r < 0)
return r;
ki = crypt_keyslot_status(cd, keyslot);
if (ki == CRYPT_SLOT_INVALID) {
@@ -2234,10 +2325,9 @@ int crypt_volume_key_verify(struct crypt_device *cd,
struct volume_key *vk;
int r;
if (!isLUKS(cd->type)) {
log_err(cd, _("This operation is supported only for LUKS device.\n"));
return -EINVAL;
}
r = onlyLUKS(cd);
if (r < 0)
return r;
vk = crypt_alloc_volume_key(volume_key_size, volume_key);
if (!vk)
@@ -2341,12 +2431,12 @@ static int _luks_dump(struct crypt_device *cd)
int i;
log_std(cd, "LUKS header information for %s\n\n", mdata_device_path(cd));
log_std(cd, "Version: \t%d\n", cd->u.luks1.hdr.version);
log_std(cd, "Version: \t%" PRIu16 "\n", cd->u.luks1.hdr.version);
log_std(cd, "Cipher name: \t%s\n", cd->u.luks1.hdr.cipherName);
log_std(cd, "Cipher mode: \t%s\n", cd->u.luks1.hdr.cipherMode);
log_std(cd, "Hash spec: \t%s\n", cd->u.luks1.hdr.hashSpec);
log_std(cd, "Payload offset:\t%d\n", cd->u.luks1.hdr.payloadOffset);
log_std(cd, "MK bits: \t%d\n", cd->u.luks1.hdr.keyBytes * 8);
log_std(cd, "Payload offset:\t%" PRIu32 "\n", cd->u.luks1.hdr.payloadOffset);
log_std(cd, "MK bits: \t%" PRIu32 "\n", cd->u.luks1.hdr.keyBytes * 8);
log_std(cd, "MK digest: \t");
hexprint(cd, cd->u.luks1.hdr.mkDigest, LUKS_DIGESTSIZE, " ");
log_std(cd, "\n");
@@ -2355,12 +2445,12 @@ static int _luks_dump(struct crypt_device *cd)
log_std(cd, "\n \t");
hexprint(cd, cd->u.luks1.hdr.mkDigestSalt+LUKS_SALTSIZE/2, LUKS_SALTSIZE/2, " ");
log_std(cd, "\n");
log_std(cd, "MK iterations: \t%d\n", cd->u.luks1.hdr.mkDigestIterations);
log_std(cd, "MK iterations: \t%" PRIu32 "\n", cd->u.luks1.hdr.mkDigestIterations);
log_std(cd, "UUID: \t%s\n\n", cd->u.luks1.hdr.uuid);
for(i = 0; i < LUKS_NUMKEYS; i++) {
if(cd->u.luks1.hdr.keyblock[i].active == LUKS_KEY_ENABLED) {
log_std(cd, "Key Slot %d: ENABLED\n",i);
log_std(cd, "\tIterations: \t%d\n",
log_std(cd, "\tIterations: \t%" PRIu32 "\n",
cd->u.luks1.hdr.keyblock[i].passwordIterations);
log_std(cd, "\tSalt: \t");
hexprint(cd, cd->u.luks1.hdr.keyblock[i].passwordSalt,
@@ -2370,9 +2460,9 @@ static int _luks_dump(struct crypt_device *cd)
LUKS_SALTSIZE/2, LUKS_SALTSIZE/2, " ");
log_std(cd, "\n");
log_std(cd, "\tKey material offset:\t%d\n",
log_std(cd, "\tKey material offset:\t%" PRIu32 "\n",
cd->u.luks1.hdr.keyblock[i].keyMaterialOffset);
log_std(cd, "\tAF stripes: \t%d\n",
log_std(cd, "\tAF stripes: \t%" PRIu32 "\n",
cd->u.luks1.hdr.keyblock[i].stripes);
}
else
@@ -2417,6 +2507,31 @@ int crypt_dump(struct crypt_device *cd)
return -EINVAL;
}
static int _init_by_name_crypt_none(struct crypt_device *cd)
{
struct crypt_dm_active_device dmd = {};
int r;
if (cd->type || !cd->u.none.active_name)
return -EINVAL;
r = dm_query_device(cd, cd->u.none.active_name,
DM_ACTIVE_CRYPT_CIPHER |
DM_ACTIVE_CRYPT_KEYSIZE, &dmd);
if (r >= 0)
r = crypt_parse_name_and_mode(dmd.u.crypt.cipher,
cd->u.none.cipher, NULL,
cd->u.none.cipher_mode);
if (!r)
cd->u.none.key_size = dmd.u.crypt.vk->keylength;
crypt_free_volume_key(dmd.u.crypt.vk);
free(CONST_CAST(void*)dmd.u.crypt.cipher);
return r;
}
const char *crypt_get_cipher(struct crypt_device *cd)
{
if (isPLAIN(cd->type))
@@ -2431,6 +2546,9 @@ const char *crypt_get_cipher(struct crypt_device *cd)
if (isTCRYPT(cd->type))
return cd->u.tcrypt.params.cipher;
if (!cd->type && !_init_by_name_crypt_none(cd))
return cd->u.none.cipher;
return NULL;
}
@@ -2448,6 +2566,9 @@ const char *crypt_get_cipher_mode(struct crypt_device *cd)
if (isTCRYPT(cd->type))
return cd->u.tcrypt.params.mode;
if (!cd->type && !_init_by_name_crypt_none(cd))
return cd->u.none.cipher_mode;
return NULL;
}
@@ -2489,6 +2610,9 @@ int crypt_get_volume_key_size(struct crypt_device *cd)
if (isTCRYPT(cd->type))
return cd->u.tcrypt.params.key_size;
if (!cd->type && !_init_by_name_crypt_none(cd))
return cd->u.none.key_size;
return 0;
}
@@ -2528,10 +2652,8 @@ uint64_t crypt_get_iv_offset(struct crypt_device *cd)
crypt_keyslot_info crypt_keyslot_status(struct crypt_device *cd, int keyslot)
{
if (!isLUKS(cd->type)) {
log_err(cd, _("This operation is supported only for LUKS device.\n"));
if (onlyLUKS(cd) < 0)
return CRYPT_SLOT_INVALID;
}
return LUKS_keyslot_info(&cd->u.luks1.hdr, keyslot);
}

View File

@@ -2,15 +2,13 @@ moduledir = $(libdir)/cryptsetup
noinst_LTLIBRARIES = libtcrypt.la
libtcrypt_la_CFLAGS = -Wall @CRYPTO_CFLAGS@
libtcrypt_la_CFLAGS = -Wall $(AM_CFLAGS) @CRYPTO_CFLAGS@
libtcrypt_la_SOURCES = \
tcrypt.c \
tcrypt.h
AM_CPPFLAGS = -D_GNU_SOURCE \
-D_LARGEFILE64_SOURCE \
-D_FILE_OFFSET_BITS=64 \
AM_CPPFLAGS = -include config.h \
-I$(top_srcdir)/lib \
-I$(top_srcdir)/lib/crypto_backend

View File

@@ -1,8 +1,8 @@
/*
* TCRYPT (TrueCrypt-compatible) volume handling
* TCRYPT (TrueCrypt-compatible) and VeraCrypt volume handling
*
* Copyright (C) 2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2013, Milan Broz
* Copyright (C) 2012-2015, Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -33,16 +33,23 @@
/* TCRYPT PBKDF variants */
static struct {
unsigned int legacy:1;
unsigned int veracrypt:1;
const char *name;
const char *hash;
unsigned int iterations;
} tcrypt_kdf[] = {
{ 0, "pbkdf2", "ripemd160", 2000 },
{ 0, "pbkdf2", "ripemd160", 1000 },
{ 0, "pbkdf2", "sha512", 1000 },
{ 0, "pbkdf2", "whirlpool", 1000 },
{ 1, "pbkdf2", "sha1", 2000 },
{ 0, NULL, NULL, 0 }
{ 0, 0, "pbkdf2", "ripemd160", 2000 },
{ 0, 0, "pbkdf2", "ripemd160", 1000 },
{ 0, 0, "pbkdf2", "sha512", 1000 },
{ 0, 0, "pbkdf2", "whirlpool", 1000 },
{ 1, 0, "pbkdf2", "sha1", 2000 },
{ 0, 1, "pbkdf2", "sha512", 500000 },
{ 0, 1, "pbkdf2", "ripemd160", 655331 },
{ 0, 1, "pbkdf2", "ripemd160", 327661 }, // boot only
{ 0, 1, "pbkdf2", "whirlpool", 500000 },
{ 0, 1, "pbkdf2", "sha256", 500000 }, // VeraCrypt 1.0f
{ 0, 1, "pbkdf2", "sha256", 200000 }, // boot only
{ 0, 0, NULL, NULL, 0 }
};
struct tcrypt_alg {
@@ -51,6 +58,7 @@ struct tcrypt_alg {
unsigned int iv_size;
unsigned int key_offset;
unsigned int iv_offset; /* or tweak key offset */
unsigned int key_extra_size;
};
struct tcrypt_algs {
@@ -66,101 +74,107 @@ struct tcrypt_algs {
static struct tcrypt_algs tcrypt_cipher[] = {
/* XTS mode */
{0,1,64,"aes","xts-plain64",
{{"aes", 64,16,0,32}}},
{{"aes", 64,16,0,32,0}}},
{0,1,64,"serpent","xts-plain64",
{{"serpent",64,16,0,32}}},
{{"serpent",64,16,0,32,0}}},
{0,1,64,"twofish","xts-plain64",
{{"twofish",64,16,0,32}}},
{{"twofish",64,16,0,32,0}}},
{0,2,128,"twofish-aes","xts-plain64",
{{"twofish",64,16, 0,64},
{"aes", 64,16,32,96}}},
{{"twofish",64,16, 0,64,0},
{"aes", 64,16,32,96,0}}},
{0,3,192,"serpent-twofish-aes","xts-plain64",
{{"serpent",64,16, 0, 96},
{"twofish",64,16,32,128},
{"aes", 64,16,64,160}}},
{{"serpent",64,16, 0, 96,0},
{"twofish",64,16,32,128,0},
{"aes", 64,16,64,160,0}}},
{0,2,128,"aes-serpent","xts-plain64",
{{"aes", 64,16, 0,64},
{"serpent",64,16,32,96}}},
{{"aes", 64,16, 0,64,0},
{"serpent",64,16,32,96,0}}},
{0,3,192,"aes-twofish-serpent","xts-plain64",
{{"aes", 64,16, 0, 96},
{"twofish",64,16,32,128},
{"serpent",64,16,64,160}}},
{{"aes", 64,16, 0, 96,0},
{"twofish",64,16,32,128,0},
{"serpent",64,16,64,160,0}}},
{0,2,128,"serpent-twofish","xts-plain64",
{{"serpent",64,16, 0,64},
{"twofish",64,16,32,96}}},
{{"serpent",64,16, 0,64,0},
{"twofish",64,16,32,96,0}}},
/* LRW mode */
{0,1,48,"aes","lrw-benbi",
{{"aes", 48,16,32,0}}},
{{"aes", 48,16,32,0,0}}},
{0,1,48,"serpent","lrw-benbi",
{{"serpent",48,16,32,0}}},
{{"serpent",48,16,32,0,0}}},
{0,1,48,"twofish","lrw-benbi",
{{"twofish",48,16,32,0}}},
{{"twofish",48,16,32,0,0}}},
{0,2,96,"twofish-aes","lrw-benbi",
{{"twofish",48,16,32,0},
{"aes", 48,16,64,0}}},
{{"twofish",48,16,32,0,0},
{"aes", 48,16,64,0,0}}},
{0,3,144,"serpent-twofish-aes","lrw-benbi",
{{"serpent",48,16,32,0},
{"twofish",48,16,64,0},
{"aes", 48,16,96,0}}},
{{"serpent",48,16,32,0,0},
{"twofish",48,16,64,0,0},
{"aes", 48,16,96,0,0}}},
{0,2,96,"aes-serpent","lrw-benbi",
{{"aes", 48,16,32,0},
{"serpent",48,16,64,0}}},
{{"aes", 48,16,32,0,0},
{"serpent",48,16,64,0,0}}},
{0,3,144,"aes-twofish-serpent","lrw-benbi",
{{"aes", 48,16,32,0},
{"twofish",48,16,64,0},
{"serpent",48,16,96,0}}},
{{"aes", 48,16,32,0,0},
{"twofish",48,16,64,0,0},
{"serpent",48,16,96,0,0}}},
{0,2,96,"serpent-twofish", "lrw-benbi",
{{"serpent",48,16,32,0},
{"twofish",48,16,64,0}}},
{{"serpent",48,16,32,0,0},
{"twofish",48,16,64,0,0}}},
/* Kernel LRW block size is fixed to 16 bytes for GF(2^128)
* thus cannot be used with blowfish where block is 8 bytes.
* There also no GF(2^64) support.
{1,1,64,"blowfish_le","lrw-benbi",
{{"blowfish_le",64,8,32,0}}},
{{"blowfish_le",64,8,32,0,0}}},
{1,2,112,"blowfish_le-aes","lrw-benbi",
{{"blowfish_le",64, 8,32,0},
{"aes", 48,16,88,0}}},
{{"blowfish_le",64, 8,32,0,0},
{"aes", 48,16,88,0,0}}},
{1,3,160,"serpent-blowfish_le-aes","lrw-benbi",
{{"serpent", 48,16, 32,0},
{"blowfish_le",64, 8, 64,0},
{"aes", 48,16,120,0}}},*/
/* CBC + "outer" CBC (both with whitening) */
{1,1,32,"aes","cbc-tcrypt",
{{"aes", 32,16,32,0}}},
{1,1,32,"serpent","cbc-tcrypt",
{{"serpent",32,16,32,0}}},
{1,1,32,"twofish","cbc-tcrypt",
{{"twofish",32,16,32,0}}},
{1,2,64,"twofish-aes","cbci-tcrypt",
{{"twofish",32,16,32,0},
{"aes", 32,16,64,0}}},
{1,3,96,"serpent-twofish-aes","cbci-tcrypt",
{{"serpent",32,16,32,0},
{"twofish",32,16,64,0},
{"aes", 32,16,96,0}}},
{1,2,64,"aes-serpent","cbci-tcrypt",
{{"aes", 32,16,32,0},
{"serpent",32,16,64,0}}},
{1,3,96,"aes-twofish-serpent", "cbci-tcrypt",
{{"aes", 32,16,32,0},
{"twofish",32,16,64,0},
{"serpent",32,16,96,0}}},
{1,2,64,"serpent-twofish", "cbci-tcrypt",
{{"serpent",32,16,32,0},
{"twofish",32,16,64,0}}},
{1,1,16,"cast5","cbc-tcrypt",
{{"cast5", 16,8,32,0}}},
{1,1,24,"des3_ede","cbc-tcrypt",
{{"des3_ede",24,8,32,0}}},
{1,1,56,"blowfish_le","cbc-tcrypt",
{{"blowfish_le",56,8,32,0}}},
{1,2,88,"blowfish_le-aes","cbc-tcrypt",
{{"blowfish_le",56, 8,32,0},
{"aes", 32,16,88,0}}},
{1,3,120,"serpent-blowfish_le-aes","cbc-tcrypt",
{{"serpent", 32,16, 32,0},
{"blowfish_le",56, 8, 64,0},
{"aes", 32,16,120,0}}},
{{"serpent", 48,16, 32,0,0},
{"blowfish_le",64, 8, 64,0,0},
{"aes", 48,16,120,0,0}}},*/
/*
* CBC + "outer" CBC (both with whitening)
* chain_key_size: alg_keys_bytes + IV_seed_bytes + whitening_bytes
*/
{1,1,32+16+16,"aes","cbc-tcw",
{{"aes", 32,16,32,0,32}}},
{1,1,32+16+16,"serpent","cbc-tcw",
{{"serpent",32,16,32,0,32}}},
{1,1,32+16+16,"twofish","cbc-tcw",
{{"twofish",32,16,32,0,32}}},
{1,2,64+16+16,"twofish-aes","cbci-tcrypt",
{{"twofish",32,16,32,0,0},
{"aes", 32,16,64,0,32}}},
{1,3,96+16+16,"serpent-twofish-aes","cbci-tcrypt",
{{"serpent",32,16,32,0,0},
{"twofish",32,16,64,0,0},
{"aes", 32,16,96,0,32}}},
{1,2,64+16+16,"aes-serpent","cbci-tcrypt",
{{"aes", 32,16,32,0,0},
{"serpent",32,16,64,0,32}}},
{1,3,96+16+16,"aes-twofish-serpent", "cbci-tcrypt",
{{"aes", 32,16,32,0,0},
{"twofish",32,16,64,0,0},
{"serpent",32,16,96,0,32}}},
{1,2,64+16+16,"serpent-twofish", "cbci-tcrypt",
{{"serpent",32,16,32,0,0},
{"twofish",32,16,64,0,32}}},
{1,1,16+8+16,"cast5","cbc-tcw",
{{"cast5", 16,8,32,0,24}}},
{1,1,24+8+16,"des3_ede","cbc-tcw",
{{"des3_ede",24,8,32,0,24}}},
{1,1,56+8+16,"blowfish_le","cbc-tcrypt",
{{"blowfish_le",56,8,32,0,24}}},
{1,2,88+16+16,"blowfish_le-aes","cbc-tcrypt",
{{"blowfish_le",56, 8,32,0,0},
{"aes", 32,16,88,0,32}}},
{1,3,120+16+16,"serpent-blowfish_le-aes","cbc-tcrypt",
{{"serpent", 32,16, 32,0,0},
{"blowfish_le",56, 8, 64,0,0},
{"aes", 32,16,120,0,32}}},
{}
};
@@ -189,7 +203,7 @@ static int TCRYPT_hdr_from_disk(struct tcrypt_phdr *hdr,
/* Convert header to cpu format */
hdr->d.version = be16_to_cpu(hdr->d.version);
hdr->d.version_tc = le16_to_cpu(hdr->d.version_tc);
hdr->d.version_tc = be16_to_cpu(hdr->d.version_tc);
hdr->d.keys_crc32 = be32_to_cpu(hdr->d.keys_crc32);
@@ -262,8 +276,8 @@ static int decrypt_blowfish_le_cbc(struct tcrypt_alg *alg,
}
crypt_cipher_destroy(cipher);
memset(iv, 0, bs);
memset(iv_old, 0, bs);
crypt_memzero(iv, bs);
crypt_memzero(iv_old, bs);
return r;
}
@@ -289,6 +303,9 @@ static void TCRYPT_copy_key(struct tcrypt_alg *alg, const char *mode,
memcpy(&out_key[ks2], key, TCRYPT_LRW_IKEY_LEN);
} else if (!strncmp(mode, "cbc", 3)) {
memcpy(out_key, &key[alg->key_offset], alg->key_size);
/* IV + whitening */
memcpy(&out_key[alg->key_size], &key[alg->iv_offset],
alg->key_extra_size);
}
}
@@ -326,8 +343,8 @@ static int TCRYPT_decrypt_hdr_one(struct tcrypt_alg *alg, const char *mode,
crypt_cipher_destroy(cipher);
}
memset(backend_key, 0, sizeof(backend_key));
memset(iv, 0, TCRYPT_HDR_IV_LEN);
crypt_memzero(backend_key, sizeof(backend_key));
crypt_memzero(iv, TCRYPT_HDR_IV_LEN);
return r;
}
@@ -377,19 +394,19 @@ out:
if (cipher[j])
crypt_cipher_destroy(cipher[j]);
memset(iv, 0, bs);
memset(iv_old, 0, bs);
crypt_memzero(iv, bs);
crypt_memzero(iv_old, bs);
return r;
}
static int TCRYPT_decrypt_hdr(struct crypt_device *cd, struct tcrypt_phdr *hdr,
const char *key, int legacy_modes)
const char *key, uint32_t flags)
{
struct tcrypt_phdr hdr2;
int i, j, r = -EINVAL;
for (i = 0; tcrypt_cipher[i].chain_count; i++) {
if (!legacy_modes && tcrypt_cipher[i].legacy)
if (!(flags & CRYPT_TCRYPT_LEGACY_MODES) && tcrypt_cipher[i].legacy)
continue;
log_dbg("TCRYPT: trying cipher %s-%s",
tcrypt_cipher[i].long_name, tcrypt_cipher[i].mode);
@@ -421,10 +438,17 @@ static int TCRYPT_decrypt_hdr(struct crypt_device *cd, struct tcrypt_phdr *hdr,
r = i;
break;
}
if ((flags & CRYPT_TCRYPT_VERA_MODES) &&
!strncmp(hdr2.d.magic, VCRYPT_HDR_MAGIC, TCRYPT_HDR_MAGIC_LEN)) {
log_dbg("TCRYPT: Signature magic detected (Veracrypt).");
memcpy(&hdr->e, &hdr2.e, TCRYPT_HDR_LEN);
r = i;
break;
}
r = -EPERM;
}
memset(&hdr2, 0, sizeof(hdr2));
crypt_memzero(&hdr2, sizeof(hdr2));
return r;
}
@@ -461,8 +485,8 @@ static int TCRYPT_pool_keyfile(struct crypt_device *cd,
j %= TCRYPT_KEY_POOL_LEN;
}
memset(&crc, 0, sizeof(crc));
memset(data, 0, TCRYPT_KEYFILE_LEN);
crypt_memzero(&crc, sizeof(crc));
crypt_memzero(data, TCRYPT_KEYFILE_LEN);
return 0;
}
@@ -475,7 +499,7 @@ static int TCRYPT_init_hdr(struct crypt_device *cd,
size_t passphrase_size;
char *key;
unsigned int i, skipped = 0;
int r = -EINVAL, legacy_modes;
int r = -EPERM;
if (posix_memalign((void*)&key, crypt_getpagesize(), TCRYPT_HDR_KEY_LEN))
return -ENOMEM;
@@ -488,7 +512,7 @@ static int TCRYPT_init_hdr(struct crypt_device *cd,
if (params->passphrase_size > TCRYPT_KEY_POOL_LEN) {
log_err(cd, _("Maximum TCRYPT passphrase length (%d) exceeded.\n"),
TCRYPT_KEY_POOL_LEN);
return -EPERM;
goto out;
}
/* Calculate pool content from keyfiles */
@@ -502,9 +526,10 @@ static int TCRYPT_init_hdr(struct crypt_device *cd,
for (i = 0; i < params->passphrase_size; i++)
pwd[i] += params->passphrase[i];
legacy_modes = params->flags & CRYPT_TCRYPT_LEGACY_MODES ? 1 : 0;
for (i = 0; tcrypt_kdf[i].name; i++) {
if (!legacy_modes && tcrypt_kdf[i].legacy)
if (!(params->flags & CRYPT_TCRYPT_LEGACY_MODES) && tcrypt_kdf[i].legacy)
continue;
if (!(params->flags & CRYPT_TCRYPT_VERA_MODES) && tcrypt_kdf[i].veracrypt)
continue;
/* Derive header key */
log_dbg("TCRYPT: trying KDF: %s-%s-%d.",
@@ -523,16 +548,16 @@ static int TCRYPT_init_hdr(struct crypt_device *cd,
break;
/* Decrypt header */
r = TCRYPT_decrypt_hdr(cd, hdr, key, legacy_modes);
r = TCRYPT_decrypt_hdr(cd, hdr, key, params->flags);
if (r == -ENOENT) {
skipped++;
continue;
r = -EPERM;
}
if (r != -EPERM)
break;
}
if ((skipped && skipped == i) || r == -ENOTSUP) {
if ((r < 0 && r != -EPERM && skipped && skipped == i) || r == -ENOTSUP) {
log_err(cd, _("Required kernel crypto interface not available.\n"));
#ifdef ENABLE_AF_ALG
log_err(cd, _("Ensure you have algif_skcipher kernel module loaded.\n"));
@@ -543,18 +568,19 @@ static int TCRYPT_init_hdr(struct crypt_device *cd,
r = TCRYPT_hdr_from_disk(hdr, params, i, r);
if (!r) {
log_dbg("TCRYPT: Header version: %d, req. %d, sector %d"
log_dbg("TCRYPT: Magic: %s, Header version: %d, req. %d, sector %d"
", mk_offset %" PRIu64 ", hidden_size %" PRIu64
", volume size %" PRIu64, (int)hdr->d.version,
(int)hdr->d.version_tc, (int)hdr->d.sector_size,
", volume size %" PRIu64, tcrypt_kdf[i].veracrypt ?
VCRYPT_HDR_MAGIC : TCRYPT_HDR_MAGIC,
(int)hdr->d.version, (int)hdr->d.version_tc, (int)hdr->d.sector_size,
hdr->d.mk_offset, hdr->d.hidden_volume_size, hdr->d.volume_size);
log_dbg("TCRYPT: Header cipher %s-%s, key size %d",
log_dbg("TCRYPT: Header cipher %s-%s, key size %zu",
params->cipher, params->mode, params->key_size);
}
out:
memset(pwd, 0, TCRYPT_KEY_POOL_LEN);
crypt_memzero(pwd, TCRYPT_KEY_POOL_LEN);
if (key)
memset(key, 0, TCRYPT_HDR_KEY_LEN);
crypt_memzero(key, TCRYPT_HDR_KEY_LEN);
free(key);
return r;
}
@@ -563,20 +589,37 @@ int TCRYPT_read_phdr(struct crypt_device *cd,
struct tcrypt_phdr *hdr,
struct crypt_params_tcrypt *params)
{
struct device *device = crypt_metadata_device(cd);
struct device *base_device, *device = crypt_metadata_device(cd);
ssize_t hdr_size = sizeof(struct tcrypt_phdr);
char *base_device_path;
int devfd = 0, r, bs;
assert(sizeof(struct tcrypt_phdr) == 512);
log_dbg("Reading TCRYPT header of size %d bytes from device %s.",
log_dbg("Reading TCRYPT header of size %zu bytes from device %s.",
hdr_size, device_path(device));
bs = device_block_size(device);
if (bs < 0)
return bs;
devfd = device_open(device, O_RDONLY);
if (params->flags & CRYPT_TCRYPT_SYSTEM_HEADER &&
crypt_dev_is_partition(device_path(device))) {
base_device_path = crypt_get_base_device(device_path(device));
log_dbg("Reading TCRYPT system header from device %s.", base_device_path ?: "?");
if (!base_device_path)
return -EINVAL;
r = device_alloc(&base_device, base_device_path);
if (r < 0)
return r;
devfd = device_open(base_device, O_RDONLY);
free(base_device_path);
device_free(base_device);
} else
devfd = device_open(device, O_RDONLY);
if (devfd == -1) {
log_err(cd, _("Cannot open device %s.\n"), device_path(device));
return -EINVAL;
@@ -585,8 +628,9 @@ int TCRYPT_read_phdr(struct crypt_device *cd,
r = -EIO;
if (params->flags & CRYPT_TCRYPT_SYSTEM_HEADER) {
if (lseek(devfd, TCRYPT_HDR_SYSTEM_OFFSET, SEEK_SET) >= 0 &&
read_blockwise(devfd, bs, hdr, hdr_size) == hdr_size)
read_blockwise(devfd, bs, hdr, hdr_size) == hdr_size) {
r = TCRYPT_init_hdr(cd, hdr, params);
}
} else if (params->flags & CRYPT_TCRYPT_HIDDEN_HEADER) {
if (params->flags & CRYPT_TCRYPT_BACKUP_HEADER) {
if (lseek(devfd, TCRYPT_HDR_HIDDEN_OFFSET_BCK, SEEK_END) >= 0 &&
@@ -636,10 +680,13 @@ int TCRYPT_activate(struct crypt_device *cd,
uint32_t flags)
{
char cipher[MAX_CIPHER_LEN], dm_name[PATH_MAX], dm_dev_name[PATH_MAX];
struct device *device = NULL;
char *part_path;
struct device *device = NULL, *part_device = NULL;
unsigned int i;
int r;
uint32_t req_flags;
struct tcrypt_algs *algs;
enum devcheck device_check;
struct crypt_dm_active_device dmd = {
.target = DM_CRYPT,
.size = 0,
@@ -667,22 +714,55 @@ int TCRYPT_activate(struct crypt_device *cd,
return -ENOTSUP;
}
if (strstr(params->mode, "-tcw"))
req_flags = DM_TCW_SUPPORTED;
else
req_flags = DM_PLAIN64_SUPPORTED;
algs = TCRYPT_get_algs(params->cipher, params->mode);
if (!algs)
return -EINVAL;
if (params->flags & CRYPT_TCRYPT_HIDDEN_HEADER)
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;
else
dmd.size = hdr->d.volume_size / hdr->d.sector_size;
r = device_block_adjust(cd, dmd.data_device, DEV_EXCL,
if (dmd.flags & CRYPT_ACTIVATE_SHARED)
device_check = DEV_SHARED;
else
device_check = DEV_EXCL;
if ((params->flags & CRYPT_TCRYPT_SYSTEM_HEADER) &&
!crypt_dev_is_partition(device_path(dmd.data_device))) {
part_path = crypt_get_partition_device(device_path(dmd.data_device),
dmd.u.crypt.offset, dmd.size);
if (part_path) {
if (!device_alloc(&part_device, part_path)) {
log_verbose(cd, _("Activating TCRYPT system encryption for partition %s.\n"),
part_path);
dmd.data_device = part_device;
dmd.u.crypt.offset = 0;
}
free(part_path);
} else
/*
* System encryption use the whole device mapping, there can
* be active partitions.
*/
device_check = DEV_SHARED;
}
r = device_block_adjust(cd, dmd.data_device, device_check,
dmd.u.crypt.offset, &dmd.size, &dmd.flags);
if (r)
return r;
/* Frome here, key size for every cipher must be the same */
dmd.u.crypt.vk = crypt_alloc_volume_key(algs->cipher[0].key_size, NULL);
dmd.u.crypt.vk = crypt_alloc_volume_key(algs->cipher[0].key_size +
algs->cipher[0].key_extra_size, NULL);
if (!dmd.u.crypt.vk)
return -ENOMEM;
@@ -722,11 +802,12 @@ int TCRYPT_activate(struct crypt_device *cd,
break;
}
if (r < 0 && !(dm_flags() & DM_PLAIN64_SUPPORTED)) {
log_err(cd, _("Kernel doesn't support plain64 IV.\n"));
if (r < 0 && !(dm_flags() & req_flags)) {
log_err(cd, _("Kernel doesn't support TCRYPT compatible mapping.\n"));
r = -ENOTSUP;
}
device_free(part_device);
crypt_free_volume_key(dmd.u.crypt.vk);
return r;
}
@@ -876,8 +957,11 @@ uint64_t TCRYPT_get_data_offset(struct crypt_device *cd,
goto hdr_offset;
/* Mapping through whole device, not partition! */
if (params->flags & CRYPT_TCRYPT_SYSTEM_HEADER)
if (params->flags & CRYPT_TCRYPT_SYSTEM_HEADER) {
if (crypt_dev_is_partition(device_path(crypt_metadata_device(cd))))
return 0;
goto hdr_offset;
}
if (params->mode && !strncmp(params->mode, "xts", 3)) {
if (hdr->d.version < 3)
@@ -907,15 +991,21 @@ hdr_offset:
uint64_t TCRYPT_get_iv_offset(struct crypt_device *cd,
struct tcrypt_phdr *hdr,
struct crypt_params_tcrypt *params
)
struct crypt_params_tcrypt *params)
{
if (params->mode && !strncmp(params->mode, "xts", 3))
return TCRYPT_get_data_offset(cd, hdr, params);
else if (params->mode && !strncmp(params->mode, "lrw", 3))
return 0;
uint64_t iv_offset;
return hdr->d.mk_offset / hdr->d.sector_size;
if (params->mode && !strncmp(params->mode, "xts", 3))
iv_offset = TCRYPT_get_data_offset(cd, hdr, params);
else if (params->mode && !strncmp(params->mode, "lrw", 3))
iv_offset = 0;
else
iv_offset = hdr->d.mk_offset / hdr->d.sector_size;
if (params->flags & CRYPT_TCRYPT_SYSTEM_HEADER)
iv_offset += crypt_dev_partition_offset(device_path(crypt_metadata_device(cd)));
return iv_offset;
}
int TCRYPT_get_volume_key(struct crypt_device *cd,
@@ -952,11 +1042,13 @@ int TCRYPT_dump(struct crypt_device *cd,
struct tcrypt_phdr *hdr,
struct crypt_params_tcrypt *params)
{
log_std(cd, "TCRYPT header information for %s\n",
log_std(cd, "%s header information for %s\n",
hdr->d.magic[0] == 'T' ? "TCRYPT" : "VERACRYPT",
device_path(crypt_metadata_device(cd)));
if (hdr->d.version) {
log_std(cd, "Version: \t%d\n", hdr->d.version);
log_std(cd, "Driver req.:\t%d\n", hdr->d.version_tc);
log_std(cd, "Driver req.:\t%x.%x\n", hdr->d.version_tc >> 8,
hdr->d.version_tc & 0xFF);
log_std(cd, "Sector size:\t%" PRIu32 "\n", hdr->d.sector_size);
log_std(cd, "MK offset:\t%" PRIu64 "\n", hdr->d.mk_offset);
@@ -964,6 +1056,6 @@ int TCRYPT_dump(struct crypt_device *cd,
}
log_std(cd, "Cipher chain:\t%s\n", params->cipher);
log_std(cd, "Cipher mode:\t%s\n", params->mode);
log_std(cd, "MK bits: \t%d\n", params->key_size * 8);
log_std(cd, "MK bits: \t%zu\n", params->key_size * 8);
return 0;
}

View File

@@ -2,7 +2,7 @@
* TCRYPT (TrueCrypt-compatible) header defitinion
*
* Copyright (C) 2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2013, Milan Broz
* Copyright (C) 2012-2014, Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -29,6 +29,7 @@
#define TCRYPT_HDR_LEN 448
#define TCRYPT_HDR_KEY_LEN 192
#define TCRYPT_HDR_MAGIC "TRUE"
#define VCRYPT_HDR_MAGIC "VERA"
#define TCRYPT_HDR_MAGIC_LEN 4
#define TCRYPT_HDR_HIDDEN_OFFSET_OLD -1536

View File

@@ -1,7 +1,7 @@
/*
* utils - miscellaneous device utilities for cryptsetup
*
* Copyright (C) 2004, Christophe Saout <christophe@saout.de>
* Copyright (C) 2004, Jana Saout <jana@saout.de>
* Copyright (C) 2004-2007, Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2012, Milan Broz

View File

@@ -2,7 +2,7 @@
* libcryptsetup - cryptsetup library, cipher bechmark
*
* Copyright (C) 2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2012, Milan Broz
* Copyright (C) 2012-2013, Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -21,8 +21,7 @@
#include <stdlib.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <time.h>
#include "internal.h"
@@ -32,6 +31,12 @@
*/
#define CIPHER_BLOCK_BYTES 65536
/*
* If the measured value is lower, encrypted buffer is probably too small
* and calculated values are not reliable.
*/
#define CIPHER_TIME_MIN_MS 0.001
/*
* The whole test depends on Linux kernel usermode crypto API for now.
* (The same implementations are used in dm-crypt though.)
@@ -47,19 +52,15 @@ struct cipher_perf {
size_t buffer_size;
};
static long time_ms(struct rusage *start, struct rusage *end)
static int time_ms(struct timespec *start, struct timespec *end, double *ms)
{
long ms = 0;
double start_ms, end_ms;
/* For kernel backend, we need to measure only tim in kernel.
ms = (end->ru_utime.tv_sec - start->ru_utime.tv_sec) * 1000;
ms += (end->ru_utime.tv_usec - start->ru_utime.tv_usec) / 1000;
*/
start_ms = start->tv_sec * 1000.0 + start->tv_nsec / (1000.0 * 1000);
end_ms = end->tv_sec * 1000.0 + end->tv_nsec / (1000.0 * 1000);
ms += (end->ru_stime.tv_sec - start->ru_stime.tv_sec) * 1000;
ms += (end->ru_stime.tv_usec - start->ru_stime.tv_usec) / 1000;
return ms;
*ms = end_ms - start_ms;
return 0;
}
static int cipher_perf_one(struct cipher_perf *cp, char *buf,
@@ -98,26 +99,39 @@ static int cipher_perf_one(struct cipher_perf *cp, char *buf,
return r;
}
static long cipher_measure(struct cipher_perf *cp, char *buf,
size_t buf_size, int encrypt)
static int cipher_measure(struct cipher_perf *cp, char *buf,
size_t buf_size, int encrypt, double *ms)
{
struct rusage rstart, rend;
struct timespec start, end;
int r;
if (getrusage(RUSAGE_SELF, &rstart) < 0)
/*
* Using getrusage would be better here but the precision
* is not adequate, so better stick with CLOCK_MONOTONIC
*/
if (clock_gettime(CLOCK_MONOTONIC, &start) < 0)
return -EINVAL;
r = cipher_perf_one(cp, buf, buf_size, encrypt);
if (r < 0)
return r;
if (getrusage(RUSAGE_SELF, &rend) < 0)
if (clock_gettime(CLOCK_MONOTONIC, &end) < 0)
return -EINVAL;
return time_ms(&rstart, &rend);
r = time_ms(&start, &end, ms);
if (r < 0)
return r;
if (*ms < CIPHER_TIME_MIN_MS) {
log_dbg("Measured cipher runtime (%1.6f) is too low.", *ms);
return -ERANGE;
}
return 0;
}
static double speed_mbs(unsigned long bytes, unsigned long ms)
static double speed_mbs(unsigned long bytes, double ms)
{
double speed = bytes, s = ms / 1000.;
@@ -127,32 +141,32 @@ static double speed_mbs(unsigned long bytes, unsigned long ms)
static int cipher_perf(struct cipher_perf *cp,
double *encryption_mbs, double *decryption_mbs)
{
long ms_enc, ms_dec, ms;
int repeat_enc, repeat_dec;
double ms_enc, ms_dec, ms;
int r, repeat_enc, repeat_dec;
void *buf = NULL;
if (posix_memalign(&buf, crypt_getpagesize(), cp->buffer_size))
return -ENOMEM;
ms_enc = 0;
ms_enc = 0.0;
repeat_enc = 1;
while (ms_enc < 1000) {
ms = cipher_measure(cp, buf, cp->buffer_size, 1);
if (ms < 0) {
while (ms_enc < 1000.0) {
r = cipher_measure(cp, buf, cp->buffer_size, 1, &ms);
if (r < 0) {
free(buf);
return (int)ms;
return r;
}
ms_enc += ms;
repeat_enc++;
}
ms_dec = 0;
ms_dec = 0.0;
repeat_dec = 1;
while (ms_dec < 1000) {
ms = cipher_measure(cp, buf, cp->buffer_size, 0);
if (ms < 0) {
while (ms_dec < 1000.0) {
r = cipher_measure(cp, buf, cp->buffer_size, 0, &ms);
if (r < 0) {
free(buf);
return (int)ms;
return r;
}
ms_dec += ms;
repeat_dec++;

View File

@@ -81,6 +81,18 @@ int crypt_parse_name_and_mode(const char *s, char *cipher, int *key_nums,
return -EINVAL;
}
/*
* Replacement for memset(s, 0, n) on stack that can be optimized out
* Also used in safe allocations for explicit memory wipe.
*/
void crypt_memzero(void *s, size_t n)
{
volatile uint8_t *p = (volatile uint8_t *)s;
while(n--)
*p++ = 0;
}
/* safe allocations */
void *crypt_safe_alloc(size_t size)
{
@@ -94,7 +106,7 @@ void *crypt_safe_alloc(size_t size)
return NULL;
alloc->size = size;
memset(&alloc->data, 0, size);
crypt_memzero(&alloc->data, size);
/* coverity[leaked_storage] */
return &alloc->data;
@@ -110,7 +122,7 @@ void crypt_safe_free(void *data)
alloc = (struct safe_allocation *)
((char *)data - offsetof(struct safe_allocation, data));
memset(data, 0, alloc->size);
crypt_memzero(data, alloc->size);
alloc->size = 0x55aa55aa;
free(alloc);
@@ -157,7 +169,7 @@ static int untimed_read(int fd, char *pass, size_t maxlen)
static int timed_read(int fd, char *pass, size_t maxlen, long timeout)
{
struct timeval t;
fd_set fds;
fd_set fds = {}; /* Just to avoid scan-build false report for FD_SET */
int failed = -1;
FD_ZERO(&fds);
@@ -176,16 +188,18 @@ static int interactive_pass(const char *prompt, char *pass, size_t maxlen,
{
struct termios orig, tmp;
int failed = -1;
int infd = STDIN_FILENO, outfd;
int infd, outfd;
if (maxlen < 1)
goto out_err;
return failed;
/* Read and write to /dev/tty if available */
if ((infd = outfd = open("/dev/tty", O_RDWR)) == -1) {
infd = open("/dev/tty", O_RDWR);
if (infd == -1) {
infd = STDIN_FILENO;
outfd = STDERR_FILENO;
}
} else
outfd = infd;
if (tcgetattr(infd, &orig))
goto out_err;

View File

@@ -24,10 +24,9 @@
#define _UTILS_CRYPT_H
#include <unistd.h>
#include "config.h"
#define MAX_CIPHER_LEN 32
#define MAX_CIPHER_LEN_STR "32"
#define MAX_CIPHER_LEN_STR "31"
#define MAX_KEYFILES 32
struct crypt_device;
@@ -46,6 +45,8 @@ void *crypt_safe_alloc(size_t size);
void crypt_safe_free(void *data);
void *crypt_safe_realloc(void *data, size_t size);
void crypt_memzero(void *s, size_t n);
ssize_t crypt_hex_to_bytes(const char *hex, char **result, int safe_alloc);
int crypt_string_to_size(struct crypt_device *cd, const char *s, uint64_t *size);

View File

@@ -1,10 +1,10 @@
/*
* device backend utilities
*
* Copyright (C) 2004, Christophe Saout <christophe@saout.de>
* Copyright (C) 2004, Jana Saout <jana@saout.de>
* Copyright (C) 2004-2007, Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2012, Milan Broz
* Copyright (C) 2009-2015, Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2015, Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -38,20 +38,106 @@ struct device {
char *file_path;
int loop_fd;
int o_direct:1;
int init_done:1;
};
static int device_ready(const char *device)
static int device_block_size_fd(int fd, size_t *min_size)
{
int devfd, r = 0;
struct stat st;
int bsize = 0, r = -EINVAL;
if (fstat(fd, &st) < 0)
return -EINVAL;
if (S_ISREG(st.st_mode))
r = (int)crypt_getpagesize();
else if (ioctl(fd, BLKSSZGET, &bsize) >= 0)
r = bsize;
else
r = -EINVAL;
if (r < 0 || !min_size)
return r;
if (S_ISREG(st.st_mode)) {
/* file can be empty as well */
if (st.st_size > bsize)
*min_size = bsize;
else
*min_size = st.st_size;
} else {
/* block device must have at least one block */
*min_size = bsize;
}
return bsize;
}
static int device_read_test(int devfd)
{
char buffer[512];
int blocksize, r = -EIO;
size_t minsize = 0;
blocksize = device_block_size_fd(devfd, &minsize);
if (blocksize < 0)
return -EINVAL;
if (minsize == 0)
return 0;
if (minsize > sizeof(buffer))
minsize = sizeof(buffer);
if (read_blockwise(devfd, blocksize, buffer, minsize) == (ssize_t)minsize)
r = 0;
crypt_memzero(buffer, sizeof(buffer));
return r;
}
/*
* The direct-io is always preferred. The header is usually mapped to the same
* device and can be accessed when the rest of device is mapped to data device.
* Using dirct-io encsures that we do not mess with data in cache.
* (But proper alignment should prevent this in the first place.)
* The read test is needed to detect broken configurations (seen with remote
* block devices) that allow open with direct-io but then fails on read.
*/
static int device_ready(struct device *device, int check_directio)
{
int devfd = -1, r = 0;
struct stat st;
log_dbg("Trying to open and read device %s.", device);
devfd = open(device, O_RDONLY);
device->o_direct = 0;
if (check_directio) {
log_dbg("Trying to open and read device %s with direct-io.",
device_path(device));
devfd = open(device_path(device), O_RDONLY | O_DIRECT);
if (devfd >= 0) {
if (device_read_test(devfd) == 0) {
device->o_direct = 1;
} else {
close(devfd);
devfd = -1;
}
}
}
if (devfd < 0) {
log_err(NULL, _("Device %s doesn't exist or access denied.\n"), device);
log_dbg("Trying to open device %s without direct-io.",
device_path(device));
devfd = open(device_path(device), O_RDONLY);
}
if (devfd < 0) {
log_err(NULL, _("Device %s doesn't exist or access denied.\n"),
device_path(device));
return -EINVAL;
}
if (fstat(devfd, &st) < 0)
r = -EINVAL;
else if (!S_ISBLK(st.st_mode))
@@ -65,12 +151,14 @@ int device_open(struct device *device, int flags)
{
int devfd;
devfd = open(device_path(device), flags | O_DIRECT | O_SYNC);
if (devfd < 0 && errno == EINVAL) {
log_dbg("Trying to open device %s without direct-io.",
device_path(device));
devfd = open(device_path(device), flags | O_SYNC);
}
flags |= O_SYNC;
if (device->o_direct)
flags |= O_DIRECT;
devfd = open(device_path(device), flags);
if (devfd < 0)
log_dbg("Cannot open device %s.", device_path(device));
return devfd;
}
@@ -90,24 +178,24 @@ int device_alloc(struct device **device, const char *path)
return -ENOMEM;
memset(dev, 0, sizeof(struct device));
dev->path = strdup(path);
if (!dev->path) {
free(dev);
return -ENOMEM;
}
dev->loop_fd = -1;
r = device_ready(path);
r = device_ready(dev, 1);
if (!r) {
dev->init_done = 1;
} else if (r == -ENOTBLK) {
/* alloc loop later */
} else if (r < 0) {
free(dev->path);
free(dev);
return -ENOTBLK;
}
dev->path = strdup(path);
if (!dev->path) {
free(dev);
return -ENOMEM;
}
*device = dev;
return 0;
}
@@ -208,27 +296,23 @@ out:
int device_block_size(struct device *device)
{
struct stat st;
int fd, bsize = 0, r = -EINVAL;
int fd, r = -EINVAL;
if (!device)
return 0;
if (device->file_path)
return (int)crypt_getpagesize();
fd = open(device->path, O_RDONLY);
if(fd < 0)
return -EINVAL;
if (fstat(fd, &st) < 0)
goto out;
r = device_block_size_fd(fd, NULL);
if (S_ISREG(st.st_mode)) {
r = (int)crypt_getpagesize();
goto out;
}
if (r <= 0)
log_dbg("Cannot get block size for device %s.", device_path(device));
if (ioctl(fd, BLKSSZGET, &bsize) >= 0)
r = bsize;
out:
close(fd);
return r;
}
@@ -333,7 +417,7 @@ out:
static int device_internal_prepare(struct crypt_device *cd, struct device *device)
{
char *loop_device;
char *loop_device, *file_path = NULL;
int r, loop_fd, readonly = 0;
if (device->init_done)
@@ -359,15 +443,19 @@ static int device_internal_prepare(struct crypt_device *cd, struct device *devic
return -EINVAL;
}
r = device_ready(loop_device);
file_path = device->path;
device->path = loop_device;
r = device_ready(device, device->o_direct);
if (r < 0) {
device->path = file_path;
crypt_loop_detach(loop_device);
free(loop_device);
return r;
}
device->loop_fd = loop_fd;
device->file_path = device->path;
device->path = loop_device;
device->file_path = file_path;
device->init_done = 1;
return 0;

View File

@@ -1,7 +1,7 @@
/*
* devname - search for device name
*
* Copyright (C) 2004, Christophe Saout <christophe@saout.de>
* Copyright (C) 2004, Jana Saout <jana@saout.de>
* Copyright (C) 2004-2007, Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2013, Milan Broz
@@ -31,10 +31,7 @@
#include <limits.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "utils_dm.h"
char *crypt_lookup_dev(const char *dev_id);
int crypt_sysfs_get_rotational(int major, int minor, int *rotational);
#include "internal.h"
static char *__lookup_dev(char *path, dev_t dev, int dir_level, const int max_level)
{
@@ -170,16 +167,12 @@ char *crypt_lookup_dev(const char *dev_id)
return devpath;
}
int crypt_sysfs_get_rotational(int major, int minor, int *rotational)
static int _read_uint64(const char *sysfs_path, uint64_t *value)
{
char path[PATH_MAX], tmp[64] = {0};
char tmp[64] = {0};
int fd, r;
if (snprintf(path, sizeof(path), "/sys/dev/block/%d:%d/queue/rotational",
major, minor) < 0)
return 0;
if ((fd = open(path, O_RDONLY)) < 0)
if ((fd = open(sysfs_path, O_RDONLY)) < 0)
return 0;
r = read(fd, tmp, sizeof(tmp));
close(fd);
@@ -187,8 +180,185 @@ int crypt_sysfs_get_rotational(int major, int minor, int *rotational)
if (r <= 0)
return 0;
if (sscanf(tmp, "%d", rotational) != 1)
if (sscanf(tmp, "%" PRIu64, value) != 1)
return 0;
return 1;
}
static int _sysfs_get_uint64(int major, int minor, uint64_t *value, const char *attr)
{
char path[PATH_MAX];
if (snprintf(path, sizeof(path), "/sys/dev/block/%d:%d/%s",
major, minor, attr) < 0)
return 0;
return _read_uint64(path, value);
}
static int _path_get_uint64(const char *sysfs_path, uint64_t *value, const char *attr)
{
char path[PATH_MAX];
if (snprintf(path, sizeof(path), "%s/%s",
sysfs_path, attr) < 0)
return 0;
return _read_uint64(path, value);
}
int crypt_dev_is_rotational(int major, int minor)
{
uint64_t val;
if (!_sysfs_get_uint64(major, minor, &val, "queue/rotational"))
return 1; /* if failed, expect rotational disk */
return val ? 1 : 0;
}
int crypt_dev_is_partition(const char *dev_path)
{
uint64_t val;
struct stat st;
if (stat(dev_path, &st) < 0)
return 0;
if (!S_ISBLK(st.st_mode))
return 0;
if (!_sysfs_get_uint64(major(st.st_rdev), minor(st.st_rdev),
&val, "partition"))
return 0;
return val ? 1 : 0;
}
uint64_t crypt_dev_partition_offset(const char *dev_path)
{
uint64_t val;
struct stat st;
if (!crypt_dev_is_partition(dev_path))
return 0;
if (stat(dev_path, &st) < 0)
return 0;
if (!_sysfs_get_uint64(major(st.st_rdev), minor(st.st_rdev),
&val, "start"))
return 0;
return val;
}
/* Try to find partition which match offset and size on top level device */
char *crypt_get_partition_device(const char *dev_path, uint64_t offset, uint64_t size)
{
char link[PATH_MAX], path[PATH_MAX], part_path[PATH_MAX], *devname;
char *result = NULL;
struct stat st;
size_t devname_len;
ssize_t len;
struct dirent *entry;
DIR *dir;
uint64_t part_offset, part_size;
if (stat(dev_path, &st) < 0)
return NULL;
if (!S_ISBLK(st.st_mode))
return NULL;
if (snprintf(path, sizeof(path), "/sys/dev/block/%d:%d",
major(st.st_rdev), minor(st.st_rdev)) < 0)
return NULL;
len = readlink(path, link, sizeof(link) - 1);
if (len < 0)
return NULL;
/* Get top level disk name for sysfs search */
link[len] = '\0';
devname = strrchr(link, '/');
if (!devname)
return NULL;
devname++;
/* DM devices do not use kernel partitions. */
if (dm_is_dm_kernel_name(devname))
return NULL;
dir = opendir(path);
if (!dir)
return NULL;
devname_len = strlen(devname);
while((entry = readdir(dir))) {
if (strncmp(entry->d_name, devname, devname_len))
continue;
if (snprintf(part_path, sizeof(part_path), "%s/%s",
path, entry->d_name) < 0)
continue;
if (stat(part_path, &st) < 0)
continue;
if (S_ISDIR(st.st_mode)) {
if (!_path_get_uint64(part_path, &part_offset, "start") ||
!_path_get_uint64(part_path, &part_size, "size"))
continue;
if (part_offset == offset && part_size == size &&
snprintf(part_path, sizeof(part_path), "/dev/%s",
entry->d_name) > 0) {
result = strdup(part_path);
break;
}
}
}
closedir(dir);
return result;
}
/* Try to find base device from partition */
char *crypt_get_base_device(const char *dev_path)
{
char link[PATH_MAX], path[PATH_MAX], part_path[PATH_MAX], *devname;
struct stat st;
ssize_t len;
if (!crypt_dev_is_partition(dev_path))
return NULL;
if (stat(dev_path, &st) < 0)
return NULL;
if (snprintf(path, sizeof(path), "/sys/dev/block/%d:%d",
major(st.st_rdev), minor(st.st_rdev)) < 0)
return NULL;
len = readlink(path, link, sizeof(link) - 1);
if (len < 0)
return NULL;
/* Get top level disk name for sysfs search */
link[len] = '\0';
devname = strrchr(link, '/');
if (!devname)
return NULL;
*devname = '\0';
devname = strrchr(link, '/');
if (!devname)
return NULL;
devname++;
if (dm_is_dm_kernel_name(devname))
return NULL;
snprintf(part_path, sizeof(part_path), "/dev/%s", devname);
return strdup(part_path);
}

View File

@@ -1,10 +1,10 @@
/*
* libdevmapper - device-mapper backend for cryptsetup
*
* Copyright (C) 2004, Christophe Saout <christophe@saout.de>
* Copyright (C) 2004, Jana Saout <jana@saout.de>
* Copyright (C) 2004-2007, Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2012, Milan Broz
* Copyright (C) 2009-2015, Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2015, Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -39,6 +39,10 @@ struct device;
#define DM_PLAIN64_SUPPORTED (1 << 3) /* plain64 IV */
#define DM_DISCARDS_SUPPORTED (1 << 4) /* discards/TRIM option is supported */
#define DM_VERITY_SUPPORTED (1 << 5) /* dm-verity target supported */
#define DM_TCW_SUPPORTED (1 << 6) /* tcw (TCRYPT CBC with whitening) */
#define DM_SAME_CPU_CRYPT_SUPPORTED (1 << 7) /* same_cpu_crypt */
#define DM_SUBMIT_FROM_CRYPT_CPUS_SUPPORTED (1 << 8) /* submit_from_crypt_cpus */
uint32_t dm_flags(void);
#define DM_ACTIVE_DEVICE (1 << 0)

View File

@@ -1,7 +1,7 @@
/*
* FIPS mode utilities
*
* Copyright (C) 2011-2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2011-2015, 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
@@ -18,46 +18,29 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdlib.h>
#include <unistd.h>
#include "libcryptsetup.h"
#include "nls.h"
#include <fcntl.h>
#include <errno.h>
#include "utils_fips.h"
#include "config.h"
#if !ENABLE_FIPS
int crypt_fips_mode(void) { return 0; }
void crypt_fips_libcryptsetup_check(struct crypt_device *cd) {}
void crypt_fips_self_check(struct crypt_device *cd) {}
#else
#include <fipscheck.h>
static int kernel_fips_mode(void)
{
int fd;
char buf[1] = "";
if ((fd = open("/proc/sys/crypto/fips_enabled", O_RDONLY)) >= 0) {
while (read(fd, buf, sizeof(buf)) < 0 && errno == EINTR);
close(fd);
}
return (buf[0] == '1') ? 1 : 0;
}
int crypt_fips_mode(void)
{
return FIPSCHECK_kernel_fips_mode();
}
static void crypt_fips_verify(struct crypt_device *cd,
const char *name, const char *function)
{
if (!crypt_fips_mode())
return;
if (!FIPSCHECK_verify(name, function)) {
crypt_log(cd, CRYPT_LOG_ERROR, _("FIPS checksum verification failed.\n"));
_exit(EXIT_FAILURE);
}
crypt_log(cd, CRYPT_LOG_VERBOSE, _("Running in FIPS mode.\n"));
}
void crypt_fips_libcryptsetup_check(struct crypt_device *cd)
{
crypt_fips_verify(cd, LIBCRYPTSETUP_VERSION_FIPS, "crypt_init");
}
void crypt_fips_self_check(struct crypt_device *cd)
{
crypt_fips_verify(cd, NULL, NULL);
return kernel_fips_mode() && !access("/etc/system-fips", F_OK);
}
#endif /* ENABLE_FIPS */

View File

@@ -1,7 +1,7 @@
/*
* FIPS mode utilities
*
* Copyright (C) 2011-2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2011-2015, 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,10 +21,6 @@
#ifndef _UTILS_FIPS_H
#define _UTILS_FIPS_H
struct crypt_device;
int crypt_fips_mode(void);
void crypt_fips_libcryptsetup_check(struct crypt_device *cd);
void crypt_fips_self_check(struct crypt_device *cd);
#endif /* _UTILS_FIPS_H */

View File

@@ -124,7 +124,7 @@ int crypt_wipe(struct device *device,
{
struct stat st;
char *buffer;
int devfd, flags, rotational, bsize;
int devfd, flags, bsize;
ssize_t written;
if (!size || size % SECTOR_SIZE || (size > MAXIMUM_WIPE_BYTES)) {
@@ -139,14 +139,12 @@ int crypt_wipe(struct device *device,
}
if (type == CRYPT_WIPE_DISK && S_ISBLK(st.st_mode)) {
rotational = 0;
if (!crypt_sysfs_get_rotational(major(st.st_rdev),
minor(st.st_rdev),
&rotational))
rotational = 1;
log_dbg("Rotational flag is %d.", rotational);
if (!rotational)
if (!crypt_dev_is_rotational(major(st.st_rdev),
minor(st.st_rdev))) {
type = CRYPT_WIPE_SSD;
log_dbg("Non-rotational device, using SSD wipe mode.");
} else
log_dbg("Rotational device, using normal wipe mode.");
}
bsize = device_block_size(device);

View File

@@ -2,15 +2,13 @@ moduledir = $(libdir)/cryptsetup
noinst_LTLIBRARIES = libverity.la
libverity_la_CFLAGS = -Wall @CRYPTO_CFLAGS@
libverity_la_CFLAGS = -Wall $(AM_CFLAGS) @CRYPTO_CFLAGS@
libverity_la_SOURCES = \
verity_hash.c \
verity.c \
verity.h
AM_CPPFLAGS = -D_GNU_SOURCE \
-D_LARGEFILE64_SOURCE \
-D_FILE_OFFSET_BITS=64 \
AM_CPPFLAGS = -include config.h \
-I$(top_srcdir)/lib \
-I$(top_srcdir)/lib/crypto_backend

View File

@@ -35,7 +35,7 @@
#define VERITY_SIGNATURE "verity\0\0"
/* http://code.google.com/p/cryptsetup/wiki/DMVerity#Verity_superblock_format */
/* https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity#verity-superblock-format */
struct verity_sb {
uint8_t signature[8]; /* "verity\0\0" */
uint32_t version; /* superblock version */
@@ -63,11 +63,11 @@ int VERITY_read_sb(struct crypt_device *cd,
ssize_t hdr_size = sizeof(struct verity_sb);
int devfd = 0, sb_version;
log_dbg("Reading VERITY header of size %u on device %s, offset %" PRIu64 ".",
log_dbg("Reading VERITY header of size %zu on device %s, offset %" PRIu64 ".",
sizeof(struct verity_sb), device_path(device), sb_offset);
if (params->flags & CRYPT_VERITY_NO_HEADER) {
log_err(cd, _("Verity device doesn't use on-disk header.\n"),
log_err(cd, _("Verity device %s doesn't use on-disk header.\n"),
device_path(device));
return -EINVAL;
}
@@ -159,17 +159,17 @@ int VERITY_write_sb(struct crypt_device *cd,
uuid_t uuid;
int r, devfd = 0;
log_dbg("Updating VERITY header of size %u on device %s, offset %" PRIu64 ".",
log_dbg("Updating VERITY header of size %zu on device %s, offset %" PRIu64 ".",
sizeof(struct verity_sb), device_path(device), sb_offset);
if (!uuid_string || uuid_parse(uuid_string, uuid) == -1) {
log_err(cd, _("Wrong VERITY UUID format provided.\n"),
log_err(cd, _("Wrong VERITY UUID format provided on device %s.\n"),
device_path(device));
return -EINVAL;
}
if (params->flags & CRYPT_VERITY_NO_HEADER) {
log_err(cd, _("Verity device doesn't use on-disk header.\n"),
log_err(cd, _("Verity device %s doesn't use on-disk header.\n"),
device_path(device));
return -EINVAL;
}

View File

@@ -22,7 +22,6 @@
#define _VERITY_H
#include <unistd.h>
#include "config.h"
#define VERITY_MAX_HASH_TYPE 1
#define VERITY_BLOCK_SIZE_OK(x) ((x) % 512 || (x) < 512 || \

View File

@@ -220,7 +220,7 @@ static int VERITY_create_or_verify_hash(struct crypt_device *cd,
off_t hash_level_block[VERITY_MAX_LEVELS];
off_t hash_level_size[VERITY_MAX_LEVELS];
off_t data_file_blocks, s;
size_t hash_per_block, hash_per_block_bits;
size_t hash_per_block_bits;
off_t data_device_size = 0, hash_device_size = 0;
uint64_t dev_size;
int levels, i, r;
@@ -251,7 +251,6 @@ static int VERITY_create_or_verify_hash(struct crypt_device *cd,
}
hash_per_block_bits = get_bits_down(hash_block_size / digest_size);
hash_per_block = 1 << hash_per_block_bits;
if (!hash_per_block_bits)
return -EINVAL;
@@ -271,8 +270,7 @@ static int VERITY_create_or_verify_hash(struct crypt_device *cd,
for (i = levels - 1; i >= 0; i--) {
hash_level_block[i] = hash_position;
// verity position of block data_file_blocks at level i
s = data_file_blocks >> (i * hash_per_block_bits);
s = (s + hash_per_block - 1) / hash_per_block;
s = (data_file_blocks + ((off_t)1 << ((i + 1) * hash_per_block_bits)) - 1) >> ((i + 1) * hash_per_block_bits);
hash_level_size[i] = s;
if ((hash_position + s) < hash_position ||
(hash_position + s) < 0) {

View File

@@ -35,7 +35,7 @@ struct volume_key *crypt_alloc_volume_key(unsigned keylength, const char *key)
if (key)
memcpy(&vk->key, key, keylength);
else
memset(&vk->key, 0, keylength);
crypt_memzero(&vk->key, keylength);
return vk;
}
@@ -43,7 +43,7 @@ struct volume_key *crypt_alloc_volume_key(unsigned keylength, const char *key)
void crypt_free_volume_key(struct volume_key *vk)
{
if (vk) {
memset(vk->key, 0, vk->keylength);
crypt_memzero(vk->key, vk->keylength);
vk->keylength = 0;
free(vk);
}

View File

@@ -1,4 +1,4 @@
.TH CRYPTSETUP-REENCRYPT "8" "June 2012" "cryptsetup-reencrypt" "Maintenance Commands"
.TH CRYPTSETUP-REENCRYPT "8" "January 2015" "cryptsetup-reencrypt" "Maintenance Commands"
.SH NAME
cryptsetup-reencrypt - tool for offline LUKS device re-encryption
.SH SYNOPSIS
@@ -36,9 +36,15 @@ To start (or continue) re-encryption for <device> use:
.PP
\fIcryptsetup-reencrypt\fR <device>
\fB<options>\fR can be [\-\-block-size, \-\-cipher, \-\-hash, \-\-iter-time,
\-\-use-random | \-\-use-urandom, \-\-key-file, \-\-key-slot, \-\-keyfile-offset,
\-\-keyfile-size, \-\-tries, \-\-use-directio, \-\-use-fsync, \-\-write-log]
\fB<options>\fR can be [\-\-batch-mode, \-\-block-size, \-\-cipher, \-\-debug,
\-\-device-size, \-\-hash, \-\-iter-time, \-\-use-random | \-\-use-urandom,
\-\-keep-key, \-\-key-size, \-\-key-file, \-\-key-slot, \-\-keyfile-offset,
\-\-keyfile-size, \-\-tries, \-\-use-directio, \-\-use-fsync, \-\-verbose, \-\-write-log]
To encrypt data on (not yet encrypted) device, use \fI\-\-new\fR with combination
with \fI\-\-reduce-device-size\fR.
To remove encryption from device, use \fI\-\-decrypt\fR.
For detailed description of encryption and key file options see \fIcryptsetup(8)\fR
man page.
@@ -56,7 +62,7 @@ Set the cipher specification string.
.B "\-\-key-size, \-s \fI<bits>\fR"
Set key size in bits. The argument has to be a multiple of 8.
The possible key-sizes are limited by the cipher and mode used.
The possible key-sizes are limited by the cipher and mode used.
If you are increasing key size, there must be enough space in the LUKS header
for enlarged keyslots (data offset must be large enough) or reencryption
@@ -67,6 +73,9 @@ you can destructively shrink device with \-\-reduce-device-size option.
.TP
.B "\-\-hash, \-h \fI<hash-spec>\fR"
Specifies the hash used in the LUKS key setup scheme and volume key digest.
\fBNOTE:\fR if this parameter is not specified, default hash algorithm is always used
for new device header.
.TP
.B "\-\-iter-time, \-i \fI<milliseconds>\fR"
The number of milliseconds to spend with PBKDF2 passphrase processing for the
@@ -80,7 +89,7 @@ Define which kernel random number generator will be used to create the volume ke
.B "\-\-key-file, \-d \fIname\fR"
Read the passphrase from file.
WARNING: \-\-key-file option can be used only if there only one active keyslot,
\fBWARNING:\fR \-\-key-file option can be used only if there only one active keyslot,
or alternatively, also if \-\-key-slot option is specified (then all other keyslots
will be disabled in new LUKS device).
@@ -90,7 +99,7 @@ passphrases.
.B "\-\-key-slot, \-S <0-7>"
Specify which key slot is used.
WARNING: All other keyslots will be disabled if this option is used.
\fBWARNING:\fR All other keyslots will be disabled if this option is used.
.TP
.B "\-\-keyfile-offset \fIvalue\fR"
Skip \fIvalue\fR bytes at the beginning of the key file.
@@ -100,6 +109,12 @@ Read a maximum of \fIvalue\fR bytes from the key file.
Default is to read the whole file up to the compiled-in
maximum.
.TP
.B "\-\-keep-key"
Do not change encryption key, just reencrypt the LUKS header and keyslots.
This option can be combined only with \fI\-\-hash\fR or \fI\-\-iter-time\fR
options.
.TP
.B "\-\-tries, \-T"
Number of retries for invalid passphrase entry.
.TP
@@ -114,14 +129,14 @@ Instead of real device size, use specified value.
It means that only specified area (from the start of the device
to the specified size) will be reencrypted.
WARNING: This is destructive operation.
\fBWARNING:\fR This is destructive operation.
If no unit suffix is specified, the size is in bytes.
Unit suffix can be S for 512 byte sectors, K/M/G/T (or KiB,MiB,GiB,TiB)
for units with 1024 base or KB/MB/GB/TB for 1000 base (SI scale).
WARNING: This is destructive operation.
\fBWARNING:\fR This is destructive operation.
.TP
.B "\-\-reduce-device-size \fIsize[units]\fR"
Enlarge data offset to specified value by shrinking device size.
@@ -130,12 +145,12 @@ This means that last sectors on the original device will be lost,
ciphertext data will be effectively shifted by specified
number of sectors.
It can be usefull if you e.g. added some space to underlying
It can be useful if you e.g. added some space to underlying
partition (so last sectors contains no data).
For units suffix see \-\-device-size parameter description.
WARNING: This is destructive operation and cannot be reverted.
\fBWARNING:\fR This is destructive operation and cannot be reverted.
Use with extreme care - shrinked filesystems are usually unrecoverable.
You cannot shrink device more than by 64 MiB (131072 sectors).
@@ -145,17 +160,23 @@ Create new header (encrypt not yet encrypted device).
This option must be used together with \-\-reduce-device-size.
WARNING: This is destructive operation and cannot be reverted.
\fBWARNING:\fR This is destructive operation and cannot be reverted.
.TP
.B "\-\-decrypt"
Remove encryption (decrypt already encrypted device and remove LUKS header).
\fBWARNING:\fR This is destructive operation and cannot be reverted.
.TP
.B "\-\-use-directio"
Use direct-io (O_DIRECT) for all read/write data operations.
Use direct-io (O_DIRECT) for all read/write data operations related
to block device undergoing reencryption.
Usefull if direct-io operations perform better than normal buffered
Useful if direct-io operations perform better than normal buffered
operations (e.g. in virtual environments).
.TP
.B "\-\-use-fsync"
Use fsync call after every written block.
Use fsync call after every written block. This applies for reencryption
log files as well.
.TP
.B "\-\-write-log"
Update log file after every block write. This can slow down reencryption
@@ -178,18 +199,24 @@ Reencrypt /dev/sdb1 (change volume key)
cryptsetup-reencrypt /dev/sdb1
.TP
Reencrypt and also change cipher and cipher mode
cryptsetup-reencrypt /dev/sdb1 -c aes-xts-plain64
cryptsetup-reencrypt /dev/sdb1 \-c aes-xts-plain64
.TP
Add LUKS encryption to not yet encrypted device
First, be sure you have space added to disk.
Or alternatively shrink filesystem in advance.
.br
Here we need 4096 512-bytes sectors (enough for 2x128 bit key).
fdisk -u /dev/sdb # move sdb1 partition end + 4096 sectors
fdisk \-u /dev/sdb # move sdb1 partition end + 4096 sectors
(or use resize2fs or tool for your filesystem and shrink it)
cryptsetup-reencrypt /dev/sdb1 --new --reduce-device-size 4096
cryptsetup-reencrypt /dev/sdb1 \-\-new \-\-reduce-device-size 4096S
.TP
Remove LUKS encryption completely
cryptsetup-reencrypt /dev/sdb1 \-\-decrypt
.SH REPORTING BUGS
Report bugs, including ones in the documentation, on
@@ -200,11 +227,11 @@ Please attach the output of the failed command with the
.SH AUTHORS
Cryptsetup-reencrypt was written by Milan Broz <gmazyland@gmail.com>.
.SH COPYRIGHT
Copyright \(co 2012 Milan Broz
Copyright \(co 2012-2015 Milan Broz
.br
Copyright \(co 2012 Red Hat, Inc.
Copyright \(co 2012-2013 Red Hat, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH SEE ALSO
The project website at \fBhttp://code.google.com/p/cryptsetup/\fR
The project website at \fBhttps://gitlab.com/cryptsetup/cryptsetup\fR

View File

@@ -1,4 +1,4 @@
.TH CRYPTSETUP "8" "May 2012" "cryptsetup" "Maintenance Commands"
.TH CRYPTSETUP "8" "December 2013" "cryptsetup" "Maintenance Commands"
.SH NAME
cryptsetup - manage plain dm-crypt and LUKS encrypted volumes
.SH SYNOPSIS
@@ -10,6 +10,10 @@ device-mapper mappings. These include plain dm-crypt volumes and
LUKS volumes. The difference is that LUKS uses a metadata header
and can hence offer more features than plain dm-crypt. On the other
hand, the header is visible and vulnerable to damage.
In addition, cryptsetup provides limited support for the use of
historic loopaes volumes and for TrueCrypt compatible volumes.
.SH PLAIN DM-CRYPT OR LUKS?
.PP
Unless you understand the cryptographic background well, use LUKS.
@@ -51,27 +55,27 @@ secure wiping by just overwriting header and key-slot area.
\fBPreviously used partitions:\fR If a partition was previously used,
it is a very good idea to wipe filesystem signatures, data, etc. before
creating a LUKS or plain dm-crypt container on it.
For a quick removal of filesystem signatures, use "wipefs". Take care
though that this may not remove everything. In particular md (RAID)
signatures at the end of a device may survive. It also does not
remove data. For a full wipe, overwrite the whole partition before
creating a LUKS or plain dm-crypt container on it.
For a quick removal of filesystem signatures, use "wipefs". Take care
though that this may not remove everything. In particular md (RAID)
signatures at the end of a device may survive. It also does not
remove data. For a full wipe, overwrite the whole partition before
container creation. If you do not know how to to that, the
cryptsetup FAQ describes several options.
.SH BASIC COMMANDS
The following are valid actions for all supported device types.
\fIopen\fR <name> <device> \-\-type <device_type>
\fIopen\fR <device> <name> \-\-type <device_type>
.IP
Opens (creates a mapping) with <name> backed by device <device>.
Opens (creates a mapping with) <name> backed by device <device>.
Device type can be \fIplain\fR, \fIluks\fR (default), \fIloopaes\fR
or \fItcrypt\fR.
For backward compatibility there are \fBopen\fR command aliases:
\fBcreate\fR: open \-\-type plain <device> <name>\fR switched arguments)
\fBcreate\fR (argument-order <name> <device>): open \-\-type plain
.br
\fBplainOpen\fR: open \-\-type plain
.br
@@ -82,7 +86,9 @@ For backward compatibility there are \fBopen\fR command aliases:
\fBtcryptOpen\fR: open \-\-type tcrypt
\fB<options>\fR are type specific and are described below
for individual device types.
for individual device types. For \fBcreate\fR, the order of the <name>
and <device> options is inverted for historical reasons, all other
aliases use the standard \fB<device> <name>\fR order.
.PP
\fIclose\fR <name>
.IP
@@ -109,7 +115,7 @@ sectors of the raw device are represented in the mapped device.
Plain dm-crypt encrypts the device sector-by-sector with a
single, non-salted hash of the passphrase. No checks
are performed, no metadata is used. There is no formatting operation.
When the raw device is mapped (created), the usual device operations
When the raw device is mapped (opened), the usual device operations
can be used on the mapped device, including filesystem creation.
Mapped devices usually reside in /dev/mapper/<name>.
@@ -119,13 +125,13 @@ The following are valid plain device type actions:
.br
\fIcreate\fR <name> <device> (\fBOBSOLETE syntax\fR)
.IP
Creates a mapping with <name> backed by device <device>.
Opens (creates a mapping with) <name> backed by device <device>.
\fB<options>\fR can be [\-\-hash, \-\-cipher, \-\-verify-passphrase,
\-\-key-file, \-\-keyfile-offset, \-\-key-size, \-\-offset, \-\-skip, \-\-size,
\-\-readonly, \-\-shared, \-\-allow-discards]
Example: 'cryptsetup open --type plain /dev/sda10 e1' maps the raw
Example: 'cryptsetup open \-\-type plain /dev/sda10 e1' maps the raw
encrypted device /dev/sda10 to the mapped (decrypted) device
/dev/mapper/e1, which can then be mounted, fsck-ed or have a
filesystem created on it.
@@ -154,12 +160,20 @@ Key operations that do not specify a slot affect the first slot
that matches the supplied passphrase or the first empty slot if
a new passphrase is added.
The \fB<device>\fR parameter can be also specified by a LUKS UUID in the
format UUID=<uuid>. Translation to real device name uses symlinks
in /dev/disk/by-uuid directory.
To specify a detached header, the \fB\-\-header\fR parameter can be used
in all LUKS commands and always takes precedence over positional \fB<device>\fR
parameter.
The following are valid LUKS actions:
\fIluksFormat\fR <device> [<key file>]
.IP
Initializes a LUKS partition and sets the initial passphrase
(for key-slot 0),
(for key-slot 0),
either via prompting or via <key file>. Note that
if the second argument is present, then the passphrase
is taken from the file given there, without the need
@@ -170,10 +184,12 @@ from stdin and the safety-question being skipped.
You can only call luksFormat on a LUKS device that is not mapped.
\fB<options>\fR can be [\-\-cipher, \-\-verify-passphrase, \-\-key-size,
\-\-key-slot, \-\-key-file (takes precedence over optional second argument),
\-\-keyfile-offset, \-\-keyfile-size, \-\-use-random | \-\-use-urandom,
\-\-uuid, \-\-master-key-file].
\fB<options>\fR can be [\-\-hash, \-\-cipher, \-\-verify\-passphrase,
\-\-key\-size, \-\-key\-slot,
\-\-key\-file (takes precedence over optional second argument),
\-\-keyfile\-offset, \-\-keyfile\-size, \-\-use\-random | \-\-use\-urandom,
\-\-uuid, \-\-master\-key\-file, \-\-iter\-time, \-\-header,
\-\-force\-password].
\fBWARNING:\fR Doing a luksFormat on an existing LUKS container will
make all data the old container permanently irretrievable, unless
@@ -188,12 +204,9 @@ successful verification of the supplied passphrase.
If the passphrase is not supplied via \-\-key-file, the command
prompts for it interactively.
The <device> parameter can be also specified by LUKS UUID in the
format UUID=<uuid>, which uses the symlinks in /dev/disk/by-uuid.
\fB<options>\fR can be [\-\-key-file, \-\-keyfile-offset,
\-\-keyfile-size, \-\-readonly, \-\-test-passphrase,
\-\-allow-discards, \-\-header, \-\-key-slot, \-\-master-key-file].
\fB<options>\fR can be [\-\-key\-file, \-\-keyfile\-offset,
\-\-keyfile\-size, \-\-readonly, \-\-test\-passphrase,
\-\-allow\-discards, \-\-header, \-\-key-slot, \-\-master\-key\-file].
.PP
\fIluksSuspend\fR <name>
.IP
@@ -215,7 +228,7 @@ the mapped device.
Resumes a suspended device and reinstates the encryption key.
Prompts interactively for a passphrase if \-\-key-file is not given.
\fB<options>\fR can be [\-\-key-file, \-\-keyfile-size, \-\-header]
\fB<options>\fR can be [\-\-key\-file, \-\-keyfile\-size, \-\-header]
.PP
\fIluksAddKey\fR <device> [<key file with new key>]
.IP
@@ -224,9 +237,10 @@ interactively or via \-\-key-file.
The new passphrase to be added can be specified interactively
or read from the file given as positional argument.
\fB<options>\fR can be [\-\-key-file, \-\-keyfile-offset,
\-\-keyfile-size, \-\-new-keyfile-offset,
\-\-new-keyfile-size, \-\-key-slot, \-\-master-key-file].
\fB<options>\fR can be [\-\-key\-file, \-\-keyfile\-offset,
\-\-keyfile\-size, \-\-new\-keyfile\-offset,
\-\-new\-keyfile\-size, \-\-key\-slot, \-\-master\-key\-file,
\-\-iter\-time, \-\-force\-password, \-\-header].
.PP
\fIluksRemoveKey\fR <device> [<key file with passphrase to be removed>]
.IP
@@ -234,12 +248,12 @@ Removes the supplied passphrase from the LUKS device. The
passphrase to be removed can be specified interactively,
as positional argument or via \-\-key-file.
\fB<options>\fR can be [\-\-key-file, \-\-keyfile-offset,
\-\-keyfile-size]
\fB<options>\fR can be [\-\-key\-file, \-\-keyfile\-offset,
\-\-keyfile\-size, \-\-header]
\fBWARNING:\fR If you read the passphrase from stdin
(without further argument or with '-' as argument
to \-\-key-file), batch-mode (-q) will be implicitely
(without further argument or with '-' as argument
to \-\-key\-file), batch-mode (\-q) will be implicitely
switched on and no warning will be given when you remove the
last remaining passphrase from a LUKS container. Removing
the last passphrase makes the LUKS container permanently
@@ -248,7 +262,7 @@ inaccessible.
\fIluksChangeKey\fR <device> [<new key file>]
.IP
Changes an existing passphrase. The passphrase
to be changed must be supplied interactively or via \-\-key-file.
to be changed must be supplied interactively or via \-\-key\-file.
The new passphrase can be supplied interactively or in
a file given as positional argument.
@@ -266,9 +280,9 @@ during this operation can cause the overwrite to fail after
the old passphrase has been wiped and make the LUKS container
inaccessible.
\fB<options>\fR can be [\-\-key-file, \-\-keyfile-offset,
\-\-keyfile-size, \-\-new-keyfile-offset,
\-\-new-keyfile-size, \-\-key-slot].
\fB<options>\fR can be [\-\-key\-file, \-\-keyfile\-offset,
\-\-keyfile\-size, \-\-new\-keyfile\-offset,
\-\-new\-keyfile\-size, \-\-key\-slot, \-\-force\-password, \-\-header].
.PP
\fIluksKillSlot\fR <device> <key slot number>
.IP
@@ -278,16 +292,26 @@ This command can remove the last remaining key-slot, but requires
an interactive confirmation when doing so. Removing the last
passphrase makes a LUKS container permanently inaccessible.
\fB<options>\fR can be [\-\-key-file, \-\-keyfile-offset, \-\-keyfile-size].
\fB<options>\fR can be [\-\-key\-file, \-\-keyfile\-offset,
\-\-keyfile\-size, \-\-header].
\fBWARNING:\fR If you read the passphrase from stdin
(without further argument or with '-' as argument
to \-\-key-file), batch-mode (-q) will be implicitely
to \-\-key-file), batch-mode (\-q) will be implicitely
switched on and no warning will be given when you remove the
last remaining passphrase from a LUKS container. Removing
the last passphrase makes the LUKS container permanently
inaccessible.
.PP
\fIerase\fR <device>
.br
\fIluksErase\fR <device>
.IP
Erase all keyslots and make the LUKS container permanently inaccessible.
You do not need to provide any password for this operation.
\fBWARNING:\fR This operation is irreversible.
.PP
\fIluksUUID\fR <device>
.IP
Print the UUID of a LUKS device.
@@ -304,7 +328,7 @@ means the device is a LUKS device.
.IP
Dump the header information of a LUKS device.
If the \-\-dump-master-key option is used, the LUKS device master key is
If the \-\-dump\-master\-key option is used, the LUKS device master key is
dumped instead of the keyslot info. Beware that the master key cannot be
changed and can be used to decrypt the data stored in the LUKS container
without a passphrase and even without the LUKS header. This means
@@ -312,16 +336,16 @@ that if the master key is compromised, the whole device has to be
erased to prevent further access. Use this option carefully.
In order to dump the master key, a passphrase has to be supplied,
either interactively or via \-\-key-file.
either interactively or via \-\-key\-file.
\fB<options>\fR can be [\-\-dump-master-key, \-\-key-file,
\-\-keyfile-offset, \-\-keyfile-size].
\fB<options>\fR can be [\-\-dump\-master\-key, \-\-key\-file,
\-\-keyfile\-offset, \-\-keyfile\-size, \-\-header].
\fBWARNING:\fR If \-\-dump-master-key is used with \-\-key-file
and the argument to \-\-key-file is '-', no validation question
\fBWARNING:\fR If \-\-dump\-master\-key is used with \-\-key\-file
and the argument to \-\-key\-file is '-', no validation question
will be asked and no warning given.
.PP
\fIluksHeaderBackup\fR <device> \-\-header-backup-file <file>
\fIluksHeaderBackup\fR <device> \-\-header\-backup\-file <file>
.IP
Stores a binary backup of the LUKS header and keyslot area.
.br
@@ -338,7 +362,7 @@ addition or overwrite the encrypted data area as well.
The second option is less secure, as some sectors
can survive, e.g. due to defect management.
.PP
\fIluksHeaderRestore\fR <device> \-\-header-backup-file <file>
\fIluksHeaderRestore\fR <device> \-\-header\-backup\-file <file>
.IP
Restores a binary backup of the LUKS header and keyslot area
from the specified file.
@@ -356,18 +380,27 @@ the backup will also be written to it.
cryptsetup supports mapping loop-AES encrypted partition using
a compatibility mode.
.PP
\fIopen\fR \-\-type loopaes <device> <name> \-\-key-file <keyfile>
\fIopen\fR \-\-type loopaes <device> <name> \-\-key\-file <keyfile>
.br
\fIloopaesOpen\fR <device> <name> \-\-key-file <keyfile> (\fBold syntax\fR)
\fIloopaesOpen\fR <device> <name> \-\-key\-file <keyfile> (\fBold syntax\fR)
.IP
Opens the loop-AES <device> and sets up a mapping <name>.
If the key file is encrypted with GnuPG, then you have to use
\-\-key-file=- and decrypt it before use, e.g. like this:
\-\-key\-file=\- and decrypt it before use, e.g. like this:
.br
gpg \-\-decrypt <keyfile> | cryptsetup loopaesOpen \-\-key-file=- <device> <name>
gpg \-\-decrypt <keyfile> | cryptsetup loopaesOpen \-\-key\-file=\-
<device> <name>
Use \fB\-\-keyfile-size\fR to specify the proper key length if needed.
\fBWARNING:\fR The loop-AES extension cannot use direct input of key file
on real terminal because the keys are separated by end-of-line and only part
of the multi-key file would be read.
.br
If you need it in script, just use the pipe redirection:
.br
echo $keyfile | cryptsetup loopaesOpen \-\-key\-file=\- <device> <name>
Use \fB\-\-keyfile\-size\fR to specify the proper key length if needed.
Use \fB\-\-offset\fR to specify device offset. Note that the units
need to be specified in number of 512 byte sectors.
@@ -381,13 +414,14 @@ Use \fB\-\-hash\fR to override the default hash function for
passphrase hashing (otherwise it is detected according to key
size).
\fB<options>\fR can be [\-\-key-file, \-\-key-size, \-\-offset, \-\-skip,
\-\-hash, \-\-readonly, \-\-allow-discards].
\fB<options>\fR can be [\-\-key\-file, \-\-key\-size, \-\-offset, \-\-skip,
\-\-hash, \-\-readonly, \-\-allow\-discards].
.PP
See also section 7 of the FAQ and \fBhttp://loop-aes.sourceforge.net\fR
for more information regarding loop-AES.
.SH TCRYPT (TrueCrypt-compatible) EXTENSION
cryptsetup supports mapping of TrueCrypt or tcplay encrypted partition
.SH TCRYPT (TrueCrypt-compatible and VeraCrypt) EXTENSION
cryptsetup supports mapping of TrueCrypt, tcplay or VeraCrypt
(with \fB\-\-veracrypt\fR option) encrypted partition
using a native Linux kernel API.
Header formatting and TCRYPT header change is not supported, cryptsetup
never changes TCRYPT header on-device.
@@ -405,6 +439,11 @@ Cryptsetup should recognize all header variants, except legacy cipher chains
using LRW encryption mode with 64 bits encryption block (namely Blowfish
in LRW mode is not recognized, this is limitation of kernel crypto API).
To recognize VeraCrypt device use \fB\-\-veracrypt\fR option.
VeraCrypt is just extension of TrueCrypt header with increased
iteration count so unlocking can take quite a lot of time (in comparison
with TCRYPT device).
\fBNOTE:\fR Activation with \fBtcryptOpen\fR is supported only for cipher chains
using LRW or XTS encryption modes.
@@ -412,39 +451,68 @@ The \fBtcryptDump\fR command should work for all recognized TCRYPT devices
and doesn't require superuser privilege.
To map system device (device with boot loader where the whole encrypted
system resides) use \fB\-\-tcrypt-system\fR option. Use the whole
device not the system partition as the device parameter.
system resides) use \fB\-\-tcrypt\-system\fR option.
You can use partition device as the parameter (parameter must be real partition
device, not image in file), then only this partition is mapped.
If you have whole TCRYPT device as a file image and you want to map multiple
partition encrypted with system encryption, please create loopback mapping
with partitions first (\fBlosetup \-P\fR, see \fPlosetup(8)\fR man page for more info),
and use loop partition as the device parameter.
If you use whole base device as parameter, one device for the whole system
encryption is mapped. This mode is available only for backward compatibility
with older cryptsetup versions which mapped TCRYPT system encryption
using whole device.
To use hidden header (and map hidden device, if available),
use \fB\-\-tcrypt-hidden\fR option.
use \fB\-\-tcrypt\-hidden\fR option.
To explicitly use backup (secondary) header, use \fB\-\-tcrypt\-backup\fR
option.
\fBNOTE:\fR There is no protection for a hidden volume if
the outer volume is mounted. The reason is that if there
were any protection, it would require some metadata describing
what to protect in the outer volume and the hidden volume would
become detectable.
.PP
\fIopen\fR \-\-type tcrypt <device> <name>
.br
\fItcryptOpen\fR <device> <name> (\fBold syntax\fR)
.IP
Opens the TCRYPT (a TrueCrypt-compatible) <device> and sets up a mapping <name>.
Opens the TCRYPT (a TrueCrypt-compatible) <device> and sets up
a mapping <name>.
\fB<options>\fR can be [\-\-key-file, \-\-tcrypt-hidden, \-\-tcrypt-system,
\-\-readonly, \-\-test-passphrase].
\fB<options>\fR can be [\-\-key\-file, \-\-tcrypt\-hidden,
\-\-tcrypt\-system, \-\-tcrypt\-backup, \-\-readonly, \-\-test\-passphrase,
\-\-allow-discards].
The keyfile parameter allows combination of file content with the
passphrase and can be repeated. Note that using keyfiles is compatible
with TCRYPT and is different from LUKS keyfile logic.
\fBWARNING:\fR Option \fB\-\-allow\-discards\fR cannot be combined with
option \fB\-\-tcrypt\-hidden\fR. For normal mapping it can cause
\fBdestruction of hidden volume\fR (hidden volume appears as unused space
for outer volume so this space can be discarded).
.PP
\fItcryptDump\fR <device>
.IP
Dump the header information of a TCRYPT device.
If the \-\-dump-master-key option is used, the TCRYPT device master key is
dumped instead of TCRYPT header info. Beware that the master key
If the \-\-dump\-master\-key option is used, the TCRYPT device master key
is dumped instead of TCRYPT header info. Beware that the master key
(or concatenated master keys if cipher chain is used)
can be used to decrypt the data stored in the TCRYPT container without
a passphrase.
This means that if the master key is compromised, the whole device has
to be erased to prevent further access. Use this option carefully.
\fB<options>\fR can be [\-\-dump-master-key, \-\-key-file, \-\-tcrypt-hidden,
\-\-tcrypt-system].
\fB<options>\fR can be [\-\-dump\-master\-key, \-\-key\-file,
\-\-tcrypt\-hidden, \-\-tcrypt\-system, \-\-tcrypt\-backup].
The keyfile parameter allows combination of file content with the
passphrase and can be repeated.
@@ -475,7 +543,7 @@ Benchmarks ciphers and KDF (key derivation function).
Without parameters it tries to measure few common configurations.
To benchmark other ciphers or modes, you need to specify \fB\-\-cipher\fR
and \fB\-\-key-size\fR options or \fB\-\-hash\fR for KDF test.
and \fB\-\-key\-size\fR options or \fB\-\-hash\fR for KDF test.
\fBNOTE:\fR This benchmark is using memory only and is only informative.
You cannot directly predict real storage encryption speed from it.
@@ -486,7 +554,7 @@ If you are configuring kernel yourself, enable
"User-space interface for symmetric key cipher algorithms" in
"Cryptographic API" section (CRYPTO_USER_API_SKCIPHER .config option).
\fB<options>\fR can be [\-\-cipher, \-\-key-size, \-\-hash].
\fB<options>\fR can be [\-\-cipher, \-\-key\-size, \-\-hash].
.SH OPTIONS
.TP
.B "\-\-verbose, \-v"
@@ -496,15 +564,17 @@ Print more information on command execution.
Run in debug mode with full diagnostic logs. Debug output
lines are always prefixed by '#'.
.TP
.B "\-\-hash, \-h \fI<hash-spec>\fR"
Specifies the passphrase hash for \fIopen\fR (for plain and loopaes device types).
.B "\-\-hash, \-h \fI<hash\-spec>\fR"
Specifies the passphrase hash for \fIopen\fR (for plain and
loopaes device types).
Specifies the hash used in the LUKS key setup scheme and volume key digest
for \fIluksFormat\fR.
for \fIluksFormat\fR. The specified hash is used as hash-parameter
for PBKDF2 and for the AF splitter.
The specified hash name is passed to the compiled-in crypto backend.
Different backends may support different hashes.
For \fIluksFormat\fR, the hash
For \fIluksFormat\fR, the hash
algorithm must provide at least 160 bits of output, which
excludes, e.g., MD5. Do not use a non-crypto hash like
\fB"crc32"\fR as this breaks security.
@@ -515,16 +585,20 @@ Values compatible with old version of cryptsetup are
Use \fIcryptsetup \-\-help\fR to show the defaults.
.TP
.B "\-\-cipher, \-c \fI<cipher-spec>\fR"
.B "\-\-cipher, \-c \fI<cipher\-spec>\fR"
Set the cipher specification string.
\fIcryptsetup \-\-help\fR shows the compiled-in defaults.
The current default in the distributed sources is
"aes-cbc-essiv:sha256" for both plain dm-crypt and LUKS.
"aes-cbc-essiv:sha256" for plain dm-crypt and
"aes-xts-plain64" for LUKS.
For XTS mode (a possible future default), use "aes-xts-plain"
or better "aes-xts-plain64"
as cipher specification and optionally set a key size of
If a hash is part of the cipher spefification, then it is
used as part of the IV generation. For example, ESSIV
needs a hash function, while "plain64" does not and
hence none is specified.
For XTS mode you can optionally set a key size of
512 bits with the \-s option. Key size for XTS
mode is twice that for other modes for the same
security level.
@@ -536,7 +610,7 @@ kernel 2.6.33 or later. More information can be found in the FAQ.
When interactively asking for a passphrase, ask for it twice
and complain if both inputs do not match. Advised when creating
a regular mapping for the first time, or when running
\fIluksFormat\fR. Ignores on input from file or stdin.
\fIluksFormat\fR. Ignored on input from file or stdin.
.TP
.B "\-\-key-file, \-d \fIname\fR"
Read the passphrase from file.
@@ -544,9 +618,9 @@ Read the passphrase from file.
If the name given is "-", then the passphrase will be read from stdin.
In this case, reading will not stop at newline characters.
With LUKS, passphrases supplied via \-\-key-file are always
With LUKS, passphrases supplied via \-\-key\-file are always
the existing passphrases requested by a command, except in
the case of \fIluksFormat\fR where \-\-key-file is equivalent
the case of \fIluksFormat\fR where \-\-key\-file is equivalent
to the positional key file argument.
If you want to set a new passphrase via key file, you have to
@@ -554,37 +628,37 @@ use a positional argument to \fIluksAddKey\fR.
See section \fBNOTES ON PASSPHRASE PROCESSING\fR for more information.
.TP
.B "\-\-keyfile-offset \fIvalue\fR"
.B "\-\-keyfile\-offset \fIvalue\fR"
Skip \fIvalue\fR bytes at the beginning of the key file.
Works with all commands that accepts key files.
.TP
.B "\-\-keyfile-size, \-l \fIvalue\fR"
.B "\-\-keyfile\-size, \-l \fIvalue\fR"
Read a maximum of \fIvalue\fR bytes from the key file.
Default is to read the whole file up to the compiled-in
maximum that can be queried with \-\-help. Supplying more
data than the compiled-in maximum aborts the operation.
This option is useful
to cut trailing newlines, for example. If \-\-keyfile-offset
to cut trailing newlines, for example. If \-\-keyfile\-offset
is also given, the size count starts after the offset.
Works with all commands that accepts key files.
.TP
.B "\-\-new-keyfile-offset \fIvalue\fR"
.B "\-\-new\-keyfile\-offset \fIvalue\fR"
Skip \fIvalue\fR bytes at the start when
adding a new passphrase from key file with
\fIluksAddKey\fR.
.TP
.B "\-\-new-keyfile-size \fIvalue\fR"
.B "\-\-new\-keyfile\-size \fIvalue\fR"
Read a maximum of \fIvalue\fR bytes when adding
a new passphrase from key file with \fIluksAddKey\fR.
Default is to read the whole file up to the compiled-in
maximum length that can be queried with \-\-help.
Supplying more than the compiled in maximum aborts the
operation.
When \-\-new-keyfile-offset is also given, reading starts
When \-\-new\-keyfile\-offset is also given, reading starts
after the offset.
.TP
.B "\-\-master-key-file"
.B "\-\-master\-key\-file"
Use a master key stored in a file.
For \fIluksFormat\fR this
@@ -594,20 +668,25 @@ LUKS header and all other parameters are the same,
then the new header decrypts the data encrypted with the
header the master key was taken from.
\fBWARNING:\fR If you create your own master key, you
need to make sure to do it right. Otherwise you can end
up with a low-entropy or otherwise partially predictable
master key which will compromise security.
For \fIluksAddKey\fR this allows adding a new passphrase
without having to know an exiting one.
For \fIopen\fR this allows to open the LUKS device
For \fIopen\fR this allows one to open the LUKS device
without giving a passphrase.
.TP
.B "\-\-dump-master-key"
.B "\-\-dump\-master\-key"
For \fIluksDump\fR this option includes the master key in the displayed
information. Use with care, as the master key can be used to
bypass the passphrases, see also option \-\-master-key-file.
bypass the passphrases, see also option \-\-master\-key\-file.
.TP
.B "\-\-use-random"
.B "\-\-use\-random"
.TP
.B "\-\-use-urandom"
.B "\-\-use\-urandom"
For \fIluksFormat\fR these options define which kernel random number
generator will be used to create the master key (which is a
long-term key).
@@ -623,7 +702,7 @@ Using /dev/random can block a long time, potentially
forever, if not enough entropy can be harvested by
the kernel.
.TP
.B "\-\-key-slot, \-S <0-7>"
.B "\-\-key\-slot, \-S <0\-7>"
For LUKS operations that add key material, this options allows you
to specify which key slot is selected for the new key.
This option can be used for \fIluksFormat\fR,
@@ -634,7 +713,7 @@ specific key-slot to compare the passphrase against.
If the given passphrase would only match a different key-slot,
the operation fails.
.TP
.B "\-\-key-size, \-s <bits>"
.B "\-\-key\-size, \-s <bits>"
Sets key size in bits. The argument has to be a multiple of
8. The possible key-sizes are limited by the cipher and
mode used.
@@ -657,17 +736,14 @@ This option is only relevant for the \fIopen\fR action with plain
or loopaes device types.
.TP
.B "\-\-skip, \-p <number of 512 byte sectors>"
How many sectors of the encrypted data to skip at the beginning.
Start offset used in IV calculation in 512-byte sectors
(how many sectors of the encrypted data to skip at the beginning).
This option is only relevant for the \fIopen\fR action with plain
or loopaes device types.
This is different from the \-\-offset options with respect to
the sector numbers used in IV calculation.
Using \-\-offset will shift the IV calculation by the same negative amount.
Hence, if \-\-offset \fIn\fR, sector \fIn\fR will get a sector
number of \fI0\fR for the IV calculation.
Using \-\-skip causes sector \fIn\fR to also be the first sector
of the mapped device, but with its number for IV generation is \fIn\fR.
Hence, if \-\-offset \fIn\fR, and \-\-skip \fIs\fR, sector \fIn\fR
(the first sector of encrypted device) will get a sector number
of \fIs\fR for the IV calculation.
.TP
.B "\-\-readonly, \-r"
set up a read-only mapping.
@@ -675,17 +751,17 @@ set up a read-only mapping.
.B "\-\-shared"
Creates an additional mapping for one common
ciphertext device. Arbitrary mappings are supported.
This option is only relevant for the
This option is only relevant for the
\fIopen \-\-type plain\fR action. Use \-\-offset, \-\-size and \-\-skip to
specify the mapped area.
.TP
.B "\-\-iter-time, \-i <number of milliseconds>"
.B "\-\-iter\-time, \-i <number of milliseconds>"
The number of milliseconds to spend with PBKDF2 passphrase processing.
This option is only relevant for LUKS operations that set or change
passphrases, such as \fIluksFormat\fR or \fIluksAddKey\fR.
Specifying 0 as parameter selects the compiled-in default.
.TP
.B "\-\-batch-mode, \-q"
.B "\-\-batch\-mode, \-q"
Suppresses all confirmation questions. Use with care!
If the \-y option is not specified, this option also switches off
@@ -697,7 +773,7 @@ via terminal. It is relevant every time a passphrase is asked,
for example for \fIopen\fR, \fIluksFormat\fR or \fIluksAddKey\fR.
It has no effect if used in conjunction with \-\-key-file.
.br
This option is useful when the system
This option is useful when the system
should not stall if the user does not input a passphrase,
e.g. during boot. The default is a value of 0 seconds,
which means to wait forever.
@@ -709,7 +785,7 @@ every time a passphrase is asked, for example for
\fIopen\fR, \fIluksFormat\fR or \fIluksAddKey\fR.
The default is 3 tries.
.TP
.B "\-\-align-payload <number of 512 byte sectors>"
.B "\-\-align\-payload <number of 512 byte sectors>"
Align payload at a boundary of \fIvalue\fR 512-byte sectors.
This option is relevant for \fIluksFormat\fR.
@@ -729,7 +805,7 @@ used with the \fIluksUUID\fR command.
The UUID must be provided in the standard UUID format,
e.g. 12345678-1234-1234-1234-123456789abc.
.TP
.B "\-\-allow-discards\fR"
.B "\-\-allow\-discards\fR"
Allow the use of discard (TRIM) requests for device.
This option is only relevant for \fIopen\fR action.
@@ -738,22 +814,44 @@ because it can make filesystem-level operations visible on
the physical device. For example, information leaking
filesystem type, used space, etc. may be extractable from
the physical device if the discarded blocks can be located
later. If in doubt, do no use it.
later. If in doubt, do not use it.
A kernel version of 3.1 or later is needed. For earlier kernels
this option is ignored.
.TP
.B "\-\-test-passphrase\fR"
.B "\-\-perf\-same_cpu_crypt\fR"
Perform encryption using the same cpu that IO was submitted on.
The default is to use an unbound workqueue so that encryption work
is automatically balanced between available CPUs.
This option is only relevant for \fIopen\fR action.
\fBNOTE:\fR This option is available only for low-level dm-crypt
performance tuning, use only if you need a change to default dm-crypt
behaviour. Needs kernel 4.0 or later.
.TP
.B "\-\-perf\-submit_from_crypt_cpus\fR"
Disable offloading writes to a separate thread after encryption.
There are some situations where offloading write bios from the
encryption threads to a single thread degrades performance
significantly. The default is to offload write bios to the same
thread.
This option is only relevant for \fIopen\fR action.
\fBNOTE:\fR This option is available only for low-level dm-crypt
performance tuning, use only if you need a change to default dm-crypt
behaviour. Needs kernel 4.0 or later.
.TP
.B "\-\-test\-passphrase\fR"
Do not activate device, just verify passphrase.
This option is only relevant for \fIopen\fR action (the device
mapping name is not mandatory if this option is used).
.TP
.B "\-\-header\fR <device or file storing the LUKS header>"
Use a detached (separated) metadata device or file where the
LUKS header is stored. This options allows to store ciphertext
LUKS header is stored. This options allows one to store ciphertext
and LUKS header on different devices.
This option is only relevant for LUKS devices and can be
This option is only relevant for LUKS devices and can be
used with the \fIluksFormat\fR, \fIopen\fR, \fIluksSuspend\fR,
\fIluksResume\fR, \fIstatus\fR and \fIresize\fR commands.
@@ -765,7 +863,7 @@ For other commands that change the LUKS header (e.g. \fIluksAddKey\fR),
specify the device or file with the LUKS header directly as the
LUKS device.
If used with \fIluksFormat\fR, the \-\-align-payload option is taken
If used with \fIluksFormat\fR, the \-\-align\-payload option is taken
as absolute sector alignment on ciphertext device and can be zero.
\fBWARNING:\fR There is no check whether the ciphertext device specified
@@ -773,7 +871,7 @@ actually belongs to the header given. In fact you can specify an
arbitrary device as the ciphertext device for \fIopen\fR
with the \-\-header option. Use with care.
.TP
.B "\-\-force-password\fR"
.B "\-\-force\-password\fR"
Do not use password quality checking for new LUKS passwords.
This option applies only to \fIluksFormat\fR, \fIluksAddKey\fR and
@@ -806,18 +904,18 @@ low-entropy passphrases are easy to attack in plain mode.
first newline, i.e. '\\n'.
The input without the newline character is processed with
the default hash or the hash specified with \-\-hash.
The has result will be truncated to the key size
The hash result will be truncated to the key size
of the used cipher, or the size specified with \-s.
\fBFrom stdin\fR: Reading will continue until a newline (or until
the maximum input size is reached), with the trailing newline
stripped. The maximum input size is defined by the same
compiled-in default as for the maximum key file size and can
compiled-in default as for the maximum key file size and can
be overwritten using \-\-keyfile-size option.
The data read will be hashed with the default hash
or the hash specified with \-\-hash.
The has result will be truncated to the key size
The hash result will be truncated to the key size
of the used cipher, or the size specified with \-s.
Note that if \-\-key-file=- is used for reading the key
@@ -831,11 +929,19 @@ directly specifying a binary key.
No warning will be given if the amount of data read from stdin is
less than the key size.
\fBFrom a key file\fR: It will be truncated to the
\fBFrom a key file\fR: It will be truncated to the
key size of the used cipher or the size given by \-s
and directly used as binary key.
if the key file is shorter than the key, cryptsetup
\fBWARNING\fR: The \-\-hash argument is being ignored.
The \-\-hash option is usable only for stdin input in plain mode.
If the key file is shorter than the key, cryptsetup
will quit with an error.
The maximum input size is defined by the same
compiled-in default as for the maximum key file size and can
be overwritten using \-\-keyfile-size option.
.SH NOTES ON PASSPHRASE PROCESSING FOR LUKS
LUKS uses PBKDF2 to protect against dictionary attacks
@@ -849,13 +955,13 @@ the newline character.
\fBFrom stdin\fR:
LUKS will read passphrases from stdin up to the
first newline character or the compiled-in
maximum key file length. If \-\-keyfile-size is
maximum key file length. If \-\-keyfile\-size is
given, it is ignored.
\fBFrom key file\fR:
The complete keyfile is read up to the compiled-in
maximum size. Newline characters do not terminate the
input. The \-\-keyfile-size option can be used to limit
input. The \-\-keyfile\-size option can be used to limit
what is read.
\fBPassphrase processing\fR:
@@ -869,7 +975,12 @@ used key length, higher iteration times will not increase security.
The default setting of one second is sufficient for most
practical cases. The only exception is a low-entropy
passphrase used on a slow device.
passphrase used on a device with a slow CPU, as this will
result in a low iteration count. On a slow device it may
be advisable to increase the iteration time using the
\-\-iter\-time option in order to obtain a higher
iteration count. This does slow down all later luksOpen
operations accordingly.
.SH INCOHERENT BEHAVIOR FOR INVALID PASSPHRASES/KEYS
LUKS checks for a valid passphrase when an encrypted partition
is unlocked. The behavior of plain dm-crypt is different.
@@ -905,12 +1016,12 @@ and for wiping deleted keyslots.
The second type is used for the volume (master) key. You can switch
between using /dev/random and /dev/urandom here, see
\fP\-\-use-random\fR and \fP\-\-use-urandom\fR
\fP\-\-use\-random\fR and \fP\-\-use\-urandom\fR
options. Using /dev/random on a system without enough entropy sources
can cause \fPluksFormat\fR to block until the requested amount of
random data is gathered. In a low-entropy situation (embedded system),
this can take a very long time and potentially forever. At the same
time, using /dev/urandom in a low-entropy situation will
time, using /dev/urandom in a low-entropy situation will
produce low-quality keys. This is a serious problem, but solving
it is out of scope for a mere man-page.
See \fPurandom(4)\fR for more information.
@@ -941,7 +1052,7 @@ or in the 'Issues' section on LUKS website.
Please attach the output of the failed command with the
\-\-debug option added.
.SH AUTHORS
cryptsetup originally written by Christophe Saout <christophe@saout.de>
cryptsetup originally written by Jana Saout <jana@saout.de>
.br
The LUKS extensions and original man page were written by
Clemens Fruhwirth <clemens@endorphin.org>.
@@ -950,26 +1061,26 @@ Man page extensions by Milan Broz <gmazyland@gmail.com>.
.br
Man page rewrite and extension by Arno Wagner <arno@wagner.name>.
.SH COPYRIGHT
Copyright \(co 2004 Christophe Saout
Copyright \(co 2004 Jana Saout
.br
Copyright \(co 2004-2006 Clemens Fruhwirth
.br
Copyright \(co 2009-2012 Red Hat, Inc.
Copyright \(co 2009-2015 Red Hat, Inc.
.br
Copyright \(co 2009-2012 Milan Broz
Copyright \(co 2009-2015 Milan Broz
.br
Copyright \(co 2012 Arno Wagner
Copyright \(co 2012-2014 Arno Wagner
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH SEE ALSO
The LUKS website at \fBhttp://code.google.com/p/cryptsetup/\fR
The LUKS website at \fBhttps://gitlab.com/cryptsetup/cryptsetup/\fR
The cryptsetup FAQ, contained in the distribution package and
online at
\fBhttp://code.google.com/p/cryptsetup/wiki/FrequentlyAskedQuestions\fR
\fBhttps://gitlab.com/cryptsetup/cryptsetup/wikis/FrequentlyAskedQuestions\fR
The cryptsetup mailing list and list archive, see FAQ entry 1.6.
The LUKS on-disk format specification available at
\fBhttp://code.google.com/p/cryptsetup/wiki/Specification\fR
\fBhttps://gitlab.com/cryptsetup/cryptsetup/wikis/Specification\fR

View File

@@ -1,4 +1,4 @@
.TH VERITYSETUP "8" "June 2012" "veritysetup" "Maintenance Commands"
.TH VERITYSETUP "8" "December 2013" "veritysetup" "Maintenance Commands"
.SH NAME
veritysetup - manage dm-verity (block level verification) volumes
.SH SYNOPSIS
@@ -130,12 +130,14 @@ The first implementation of veritysetup was written by Chrome OS authors.
This version is based on verification code written by Mikulas Patocka <mpatocka@redhat.com>
and rewritten for libcryptsetup by Milan Broz <gmazyland@gmail.com>.
.SH COPYRIGHT
Copyright \(co 2012 Red Hat, Inc.
Copyright \(co 2012-2013 Red Hat, Inc.
.br
Copyright \(co 2012-2014 Milan Broz
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH SEE ALSO
The project website at \fBhttp://code.google.com/p/cryptsetup/\fR
The project website at \fBhttps://gitlab.com/cryptsetup/cryptsetup\fR
The verity on-disk format specification available at
\fBhttp://code.google.com/p/cryptsetup/wiki/DMVerity\fR
\fBhttps://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity\fR

17
misc/11-dm-crypt.rules Normal file
View File

@@ -0,0 +1,17 @@
# Old udev rules historically used in device-mapper.
# No need to install these until you have some weird configuration.
# (Code internally set the same flags.)
ACTION!="add|change", GOTO="crypt_end"
ENV{DM_UDEV_RULES_VSN}!="?*", GOTO="crypt_end"
ENV{DM_UUID}=="CRYPT-TEMP-?*", GOTO="crypt_disable"
ENV{DM_UUID}!="?*", ENV{DM_NAME}=="temporary-cryptsetup-?*", GOTO="crypt_disable"
GOTO="crypt_end"
LABEL="crypt_disable"
ENV{DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG}="1"
ENV{DM_UDEV_DISABLE_DISK_RULES_FLAG}="1"
ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="1"
LABEL="crypt_end"

View File

@@ -2,13 +2,28 @@ Example of simple dracut module for reencryption of system
LUKS drive on-the-fly.
Install in /usr/[share|lib]/dracut/modules.d/90reencrypt, then
rebuild intramfs "with dracut -f -a reencrypt".
build special intramfs "with dracut -a reencrypt -o crypt".
Reencrypt module doesn't work (has a conflict) with crypt module as
of now. After successfull reencryption reboot using original initramfs.
Dracut then recognize argument rd_REENCRYPT=name:size,
e.g. rd_REENCRYPT=sda2:52G means only 52G of device
Dracut then recognize argument rd.luks.reencrypt=name:size,
e.g. rd.luks.reencrypt=sda2:52G means only 52G of device
will be reencrypted (default is whole device).
(Name is kernel name of device.)
Also, you may specify keyslot which you want to use for reencryption,
rd.luks.reencrypt_keyslot=<keyslot_number>. Bear in mind that if you
use this option, all other keyslots will be deactivated.
Another argument, rd.luks.reencrypt_key=/dev/sda:/path/to/keyfile
can be used to read password for specific keyslot from device containing
filesystem with a keyfile (file with a password). If you omit reencrypt_key
argument, reencryption would work only in case a LUKS container has
exactly one keyslot activated.
Arguments rd.luks.reencrypt_keyslot and rd.luks.reencrypt_key are not
mandatory.
Note that reencryption context is stored in ramdisk, any
fail can mean complete lost of data!

View File

@@ -7,16 +7,23 @@ check() {
depends() {
echo dm rootfs-block
return 0
}
installkernel() {
instmods dm_crypt =crypto
# requires hostonly='' override so that loop module is pulled in initramfs
# even if not loaded in actual kernel. dracut bug?
hostonly='' instmods dm_crypt =crypto loop
}
install() {
if dracut_module_included crypt; then
derror "'reencrypt' can't be installed together with 'crypt'."
derror "Add '-o crypt' option to install reencrypt module."
return 1
fi
dracut_install cryptsetup-reencrypt
inst_hook cmdline 30 "$moddir/parse-reencrypt.sh"
inst_simple "$moddir"/reencrypt.sh /sbin/reencrypt
}
}

View File

@@ -1,14 +1,19 @@
#!/bin/sh
REENC=$(getargs rd_REENCRYPT=)
REENC=$(getargs rd.luks.reencrypt=)
REENC_DEV=$(echo $REENC | sed 's/:.*//')
REENC_SIZE=$(echo $REENC | sed -n 's/.*://p')
REENC_KEY=$(getargs rd_REENCRYPT_KEY=)
REENC_KEY=$(getargs rd.luks.reencrypt_key=)
if [ -z "$REENC_KEY" ] ; then
REENC_KEY=none
fi
REENC_SLOT=$(getargs rd.luks.reencrypt_keyslot=)
if [ -z "$REENC_SLOT" ] ; then
REENC_SLOT=any
fi
if [ -n "$REENC_DEV" ] ; then
{
printf 'SUBSYSTEM!="block", GOTO="reenc_end"\n'
@@ -16,7 +21,7 @@ if [ -n "$REENC_DEV" ] ; then
printf 'KERNEL!="%s", GOTO="reenc_end"\n' $REENC_DEV
printf 'ENV{ID_FS_TYPE}=="crypto_LUKS", RUN+="/sbin/initqueue \
--unique --onetime --name crypt-reencrypt-%%k \
/sbin/reencrypt $env{DEVNAME} %s"\n' "$REENC_KEY $REENC_SIZE"
/sbin/reencrypt $env{DEVNAME} %s"\n' "$REENC_KEY $REENC_SLOT $REENC_SIZE"
printf 'LABEL="reenc_end"\n'
} > /etc/udev/rules.d/69-reencryption.rules
fi

View File

@@ -1,10 +1,12 @@
#!/bin/sh
#
# $1=$device [$2=keyfile|none [$3=size]]
# $1=$device [$2=keyfile|none [$3=keyslot|any [$4=size]]]
#
[ -d /sys/module/dm_crypt ] || modprobe dm_crypt
[ -d /sys/module/loop ] || modprobe loop
[ -f /tmp/reencrypted ] && exit 0
. /lib/dracut-lib.sh
@@ -17,8 +19,12 @@ else
fi
PARAMS="$device -T 1 --use-fsync -B 32"
if [ -n "$3" ]; then
PARAMS="$PARAMS --device-size $3"
if [ "$3" != "any" ]; then
PARAMS="$PARAMS -S $3"
fi
if [ -n "$4" ]; then
PARAMS="$PARAMS --device-size $4"
fi
reenc_readkey() {
@@ -34,25 +40,40 @@ reenc_readkey() {
reenc_run() {
local cwd=$(pwd)
local _prompt="LUKS password for REENCRYPTING $device"
cd /tmp
if [ "$1" = "none" ] ; then
if [ "$2" != "any" ]; then
_prompt="$_prompt, using keyslot $2"
fi
/bin/plymouth ask-for-password \
--prompt "LUKS password for REENCRYPTING $device" \
--prompt "$_prompt" \
--command="/sbin/cryptsetup-reencrypt $PARAMS"
else
info "REENCRYPT using key $1"
reenc_readkey "$1" | /sbin/cryptsetup-reencrypt -d - $PARAMS
fi
_ret=$?
cd $cwd
}
info "REENCRYPT $device requested"
# flock against other interactive activities
{ flock -s 9;
reenc_run $2
} 9>/.console.lock
reenc_run $2 $3
} 9>/.console_lock
# do not ask again
>> /tmp/reencrypted
if [ $_ret -eq 0 ]; then
# do not ask again
>> /tmp/reencrypted
warn "Reencryption of device $device has finished successfully. Use previous"
warn "initramfs image (without reencrypt module) to boot the system. When"
warn "you leave the emergency shell, the system will reboot."
exit 0
emergency_shell -n "(reboot)"
[ -x /usr/bin/systemctl ] && /usr/bin/systemctl reboot
[ -x /sbin/shutdown ] && /sbin/shutdown -r now
fi
# panic the kernel otherwise
exit 1

View File

@@ -1,5 +1,6 @@
cs
de
es
fi
fr
id

879
po/cs.po

File diff suppressed because it is too large Load Diff

1422
po/de.po

File diff suppressed because it is too large Load Diff

1846
po/es.po Normal file

File diff suppressed because it is too large Load Diff

884
po/fi.po

File diff suppressed because it is too large Load Diff

885
po/fr.po

File diff suppressed because it is too large Load Diff

1715
po/it.po

File diff suppressed because it is too large Load Diff

876
po/nl.po

File diff suppressed because it is too large Load Diff

1561
po/pl.po

File diff suppressed because it is too large Load Diff

878
po/uk.po

File diff suppressed because it is too large Load Diff

1174
po/vi.po

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
AM_CPPFLAGS = -I$(top_srcdir)/lib $(PYTHON_INCLUDES)
AM_CPPFLAGS = -include $(top_srcdir)/config.h -I$(top_srcdir)/lib $(PYTHON_INCLUDES)
EXTRA_DIST = pycryptsetup-test.py
CLEANFILES = *.img
@@ -9,8 +9,8 @@ pyexec_LTLIBRARIES = pycryptsetup.la
pycryptsetup_la_SOURCES = pycryptsetup.c
pycryptsetup_la_CPPFLAGS = $(AM_CPPFLAGS) $(PYTHON_CPPFLAGS) -fno-strict-aliasing
pycryptsetup_la_LDFLAGS = -avoid-version -module
pycryptsetup_la_LIBADD = $(top_builddir)/lib/libcryptsetup.la -lpython$(PYTHON_VERSION)
pycryptsetup_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
pycryptsetup_la_LIBADD = $(top_builddir)/lib/libcryptsetup.la $(PYTHON_LIBS)
else
all:
endif

View File

@@ -2,7 +2,7 @@
#
# Python bindings to libcryptsetup test
#
# Copyright (C) 2011, Red Hat, Inc. All rights reserved.
# Copyright (C) 2011-2014, 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
@@ -18,6 +18,8 @@
# License along with this file; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
from __future__ import print_function
import sys
import os
@@ -31,11 +33,11 @@ DEVICE = "pycryptsetup_test_dev"
def log(level, txt):
if level == pycryptsetup.CRYPT_LOG_ERROR:
print txt,
print(txt,end="")
return
def askyes(txt):
print "Question:", txt
print("Question:", txt)
return 1
def askpassword(txt):
@@ -43,17 +45,17 @@ def askpassword(txt):
def print_status(c):
r = c.status()
print "status :",
print("status :",end="")
if r == pycryptsetup.CRYPT_ACTIVE:
print "ACTIVE"
print("ACTIVE")
elif r == pycryptsetup.CRYPT_INACTIVE:
print "INACTIVE"
print("INACTIVE")
else:
print "ERROR"
print("ERROR")
return
if os.geteuid() != 0:
print "WARNING: You must be root to run this test, test skipped."
print("WARNING: You must be root to run this test, test skipped.")
sys.exit(0)
os.system("dd if=/dev/zero of=" + IMG + " bs=1M count=32 >/dev/null 2>&1")
@@ -69,36 +71,36 @@ c = pycryptsetup.CryptSetup(
c.debugLevel(pycryptsetup.CRYPT_DEBUG_NONE);
c.iterationTime(1)
r = c.isLuks()
print "isLuks :", r
print("isLuks :", r)
c.askyes(message = "Is there anybody out there?")
c.log(priority = pycryptsetup.CRYPT_LOG_ERROR, message = "Nobody there...\n")
c.luksFormat(cipher = "aes", cipherMode= "xts-plain64", keysize = 512)
print "isLuks :", c.isLuks()
print "luksUUID:", c.luksUUID()
print "addKeyVK:", c.addKeyByVolumeKey(newPassphrase = PASSWORD, slot = 2)
print "addKeyP :", c.addKeyByPassphrase(passphrase = PASSWORD,
newPassphrase = PASSWORD2, slot = 3)
print "removeP :", c.removePassphrase(passphrase = PASSWORD2)
print "addKeyP :", c.addKeyByPassphrase(PASSWORD, PASSWORD2)
print("isLuks :", c.isLuks())
print("luksUUID:", c.luksUUID())
print("addKeyVK:", c.addKeyByVolumeKey(newPassphrase = PASSWORD, slot = 2))
print("addKeyP :", c.addKeyByPassphrase(passphrase = PASSWORD,
newPassphrase = PASSWORD2, slot = 3))
print("removeP :", c.removePassphrase(passphrase = PASSWORD2))
print("addKeyP :", c.addKeyByPassphrase(PASSWORD, PASSWORD2))
# original api required wrong passphrase parameter here
# print "killSlot:", c.killSlot(passphrase = "xxx", slot = 0)
print "killSlot:", c.killSlot(slot = 0)
print "activate:", c.activate(name = DEVICE, passphrase = PASSWORD)
print "suspend :", c.suspend()
print("killSlot:", c.killSlot(slot = 0))
print("activate:", c.activate(name = DEVICE, passphrase = PASSWORD))
print("suspend :", c.suspend())
# os.system("dmsetup info -c " + DEVICE)
print "resume :", c.resume(passphrase = PASSWORD)
print("resume :", c.resume(passphrase = PASSWORD))
print_status(c)
info = c.info()
print "cipher :", info["cipher"]
print "cmode :", info["cipher_mode"]
print "keysize :", info["keysize"]
print "dir :", info["dir"]
print "device :", info["device"]
print "offset :", info["offset"]
print "name :", info["name"]
print "uuid :", info["uuid"]
print("cipher :", info["cipher"])
print("cmode :", info["cipher_mode"])
print("keysize :", info["keysize"])
print("dir :", info["dir"])
print("device :", info["device"])
print("offset :", info["offset"])
print("name :", info["name"])
print("uuid :", info["uuid"])
# os.system("cryptsetup luksDump " + info["device"])
print "deact. :", c.deactivate()
print("deact. :", c.deactivate())
del c
@@ -109,7 +111,7 @@ c = pycryptsetup.CryptSetup(
logFunc = log,
passwordDialog = askpassword)
print "activate:", c.activate(name = DEVICE, passphrase = PASSWORD)
print("activate:", c.activate(name = DEVICE, passphrase = PASSWORD))
c2 = pycryptsetup.CryptSetup(
name = DEVICE,
@@ -118,13 +120,13 @@ c2 = pycryptsetup.CryptSetup(
passwordDialog = askpassword)
info = c2.info()
print "cipher :", info["cipher"]
print "cmode :", info["cipher_mode"]
print "keysize :", info["keysize"]
print("cipher :", info["cipher"])
print("cmode :", info["cipher_mode"])
print("keysize :", info["keysize"])
print "deact. :", c.deactivate()
print("deact. :", c.deactivate())
r = c2.deactivate()
print "deact. :", r
print("deact. :", r)
del c
del c2

View File

@@ -1,7 +1,7 @@
/*
* Python bindings to libcryptsetup
*
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2014, Red Hat, Inc. All rights reserved.
* Written by Martin Sivak
*
* This file is free software; you can redistribute it and/or
@@ -25,6 +25,29 @@
#include "libcryptsetup.h"
/* Python API use char* where const char* should be used... */
#define CONST_CAST(x) (x)(uintptr_t)
#if PY_MAJOR_VERSION < 3
#define MOD_ERROR_VAL
#define MOD_SUCCESS_VAL(val)
#define MOD_INIT(name) void init##name(void)
#define MOD_DEF(ob, name, doc, methods) \
ob = Py_InitModule3(name, methods, doc);
#else
#define PyInt_AsLong PyLong_AsLong
#define PyInt_Check PyLong_Check
#define MOD_ERROR_VAL NULL
#define MOD_SUCCESS_VAL(val) val
#define MOD_INIT(name) PyMODINIT_FUNC PyInit_##name(void)
#define MOD_DEF(ob, name, doc, methods) \
static struct PyModuleDef moduledef = { \
PyModuleDef_HEAD_INIT, name, doc, -1, methods, }; \
ob = PyModule_Create(&moduledef);
#endif
MOD_INIT(pycryptsetup);
typedef struct {
PyObject_HEAD
@@ -128,7 +151,7 @@ static void CryptSetup_dealloc(CryptSetupObject* self)
crypt_free(self->device);
/* free self */
self->ob_type->tp_free((PyObject*)self);
Py_TYPE(self)->tp_free((PyObject*)self);
}
static PyObject *CryptSetup_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
@@ -155,17 +178,19 @@ static PyObject *PyObjectResult(int is)
return result;
}
#define CryptSetup_HELP "CryptSetup object\n\n\
static char
CryptSetup_HELP[] =
"CryptSetup object\n\n\
constructor takes one to five arguments:\n\
__init__(device, name, yesDialog, passwordDialog, logFunc)\n\n\
yesDialog - python function with func(text) signature, \n\
which asks the user question text and returns 1\n\
of the answer was positive or 0 if not\n\
logFunc - python function with func(level, text) signature to log stuff somewhere"
logFunc - python function with func(level, text) signature to log stuff somewhere";
static int CryptSetup_init(CryptSetupObject* self, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"device", "name", "yesDialog", "passwordDialog", "logFunc", NULL};
static const char *kwlist[] = {"device", "name", "yesDialog", "passwordDialog", "logFunc", NULL};
PyObject *yesDialogCB = NULL,
*passwordDialogCB = NULL,
*cmdLineLogCB = NULL,
@@ -173,7 +198,7 @@ static int CryptSetup_init(CryptSetupObject* self, PyObject *args, PyObject *kwd
char *device = NULL, *deviceName = NULL;
int r;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|zzOOO", kwlist, &device, &deviceName,
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|zzOOO", CONST_CAST(char**)kwlist, &device, &deviceName,
&yesDialogCB, &passwordDialogCB, &cmdLineLogCB))
return -1;
@@ -229,16 +254,18 @@ static int CryptSetup_init(CryptSetupObject* self, PyObject *args, PyObject *kwd
return 0;
}
#define CryptSetup_activate_HELP "Activate LUKS device\n\n\
activate(name)"
static char
CryptSetup_activate_HELP[] =
"Activate LUKS device\n\n\
activate(name)";
static PyObject *CryptSetup_activate(CryptSetupObject* self, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"name", "passphrase", NULL};
static const char *kwlist[] = {"name", "passphrase", NULL};
char *name = NULL, *passphrase = NULL;
int is;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|s", kwlist, &name, &passphrase))
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|s", CONST_CAST(char**)kwlist, &name, &passphrase))
return NULL;
// FIXME: allow keyfile and \0 in passphrase
@@ -253,8 +280,10 @@ static PyObject *CryptSetup_activate(CryptSetupObject* self, PyObject *args, PyO
return PyObjectResult(is);
}
#define CryptSetup_deactivate_HELP "Dectivate LUKS device\n\n\
deactivate()"
static char
CryptSetup_deactivate_HELP[] =
"Dectivate LUKS device\n\n\
deactivate()";
static PyObject *CryptSetup_deactivate(CryptSetupObject* self, PyObject *args, PyObject *kwds)
{
@@ -268,15 +297,17 @@ static PyObject *CryptSetup_deactivate(CryptSetupObject* self, PyObject *args, P
return PyObjectResult(is);
}
#define CryptSetup_askyes_HELP "Asks a question using the configured dialog CB\n\n\
int askyes(message)"
static char
CryptSetup_askyes_HELP[] =
"Asks a question using the configured dialog CB\n\n\
int askyes(message)";
static PyObject *CryptSetup_askyes(CryptSetupObject* self, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"message", NULL};
static const char *kwlist[] = {"message", NULL};
PyObject *message = NULL, *result, *arglist;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &message))
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", CONST_CAST(char**)kwlist, &message))
return NULL;
Py_INCREF(message);
@@ -294,15 +325,17 @@ static PyObject *CryptSetup_askyes(CryptSetupObject* self, PyObject *args, PyObj
return result;
}
#define CryptSetup_log_HELP "Logs a string using the configured log CB\n\n\
log(int level, message)"
static char
CryptSetup_log_HELP[] =
"Logs a string using the configured log CB\n\n\
log(int level, message)";
static PyObject *CryptSetup_log(CryptSetupObject* self, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"priority", "message", NULL};
static const char *kwlist[] = {"priority", "message", NULL};
PyObject *message = NULL, *priority = NULL, *result, *arglist;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist, &message, &priority))
if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO", CONST_CAST(char**)kwlist, &message, &priority))
return NULL;
Py_INCREF(message);
@@ -322,8 +355,10 @@ static PyObject *CryptSetup_log(CryptSetupObject* self, PyObject *args, PyObject
return result;
}
#define CryptSetup_luksUUID_HELP "Get UUID of the LUKS device\n\n\
luksUUID()"
static char
CryptSetup_luksUUID_HELP[] =
"Get UUID of the LUKS device\n\n\
luksUUID()";
static PyObject *CryptSetup_luksUUID(CryptSetupObject* self, PyObject *args, PyObject *kwds)
{
@@ -336,17 +371,21 @@ static PyObject *CryptSetup_luksUUID(CryptSetupObject* self, PyObject *args, PyO
return result;
}
#define CryptSetup_isLuks_HELP "Is the device LUKS?\n\n\
isLuks()"
static char
CryptSetup_isLuks_HELP[] =
"Is the device LUKS?\n\n\
isLuks()";
static PyObject *CryptSetup_isLuks(CryptSetupObject* self, PyObject *args, PyObject *kwds)
{
return PyObjectResult(crypt_load(self->device, CRYPT_LUKS1, NULL));
}
#define CryptSetup_Info_HELP "Returns dictionary with info about opened device\nKeys:\n\
static char
CryptSetup_Info_HELP[] =
"Returns dictionary with info about opened device\nKeys:\n\
dir\n name\n uuid\n cipher\n cipher_mode\n keysize\n device\n\
offset\n size\n skip\n mode\n"
offset\n size\n skip\n mode\n";
static PyObject *CryptSetup_Info(CryptSetupObject* self, PyObject *args, PyObject *kwds)
{
@@ -371,20 +410,22 @@ static PyObject *CryptSetup_Info(CryptSetupObject* self, PyObject *args, PyObjec
return result;
}
#define CryptSetup_luksFormat_HELP "Format device to enable LUKS\n\n\
static char
CryptSetup_luksFormat_HELP[] =
"Format device to enable LUKS\n\n\
luksFormat(cipher = 'aes', cipherMode = 'cbc-essiv:sha256', keysize = 256)\n\n\
cipher - cipher specification, e.g. aes, serpent\n\
cipherMode - cipher mode specification, e.g. cbc-essiv:sha256, xts-plain64\n\
keysize - key size in bits"
keysize - key size in bits";
static PyObject *CryptSetup_luksFormat(CryptSetupObject* self, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"cipher", "cipherMode", "keysize", NULL};
static const char *kwlist[] = {"cipher", "cipherMode", "keysize", NULL};
char *cipher_mode = NULL, *cipher = NULL;
int keysize = 256;
PyObject *keysize_object = NULL;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|zzO", kwlist,
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|zzO", CONST_CAST(char**)kwlist,
&cipher, &cipher_mode, &keysize_object))
return NULL;
@@ -408,20 +449,22 @@ static PyObject *CryptSetup_luksFormat(CryptSetupObject* self, PyObject *args, P
NULL, NULL, keysize / 8, NULL));
}
#define CryptSetup_addKeyByPassphrase_HELP "Initialize keyslot using passphrase\n\n\
static char
CryptSetup_addKeyByPassphrase_HELP[] =
"Initialize keyslot using passphrase\n\n\
addKeyByPassphrase(passphrase, newPassphrase, slot)\n\n\
passphrase - string or none to ask the user\n\
newPassphrase - passphrase to add\n\
slot - which slot to use (optional)"
slot - which slot to use (optional)";
static PyObject *CryptSetup_addKeyByPassphrase(CryptSetupObject* self, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"passphrase", "newPassphrase", "slot", NULL};
static const char *kwlist[] = {"passphrase", "newPassphrase", "slot", NULL};
char *passphrase = NULL, *newpassphrase = NULL;
size_t passphrase_len = 0, newpassphrase_len = 0;
int slot = CRYPT_ANY_SLOT;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss|i", kwlist, &passphrase, &newpassphrase, &slot))
if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss|i", CONST_CAST(char**)kwlist, &passphrase, &newpassphrase, &slot))
return NULL;
if(passphrase)
@@ -435,19 +478,21 @@ static PyObject *CryptSetup_addKeyByPassphrase(CryptSetupObject* self, PyObject
newpassphrase, newpassphrase_len));
}
#define CryptSetup_addKeyByVolumeKey_HELP "Initialize keyslot using cached volume key\n\n\
static char
CryptSetup_addKeyByVolumeKey_HELP[] =
"Initialize keyslot using cached volume key\n\n\
addKeyByVolumeKey(passphrase, newPassphrase, slot)\n\n\
newPassphrase - passphrase to add\n\
slot - which slot to use (optional)"
slot - which slot to use (optional)";
static PyObject *CryptSetup_addKeyByVolumeKey(CryptSetupObject* self, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"newPassphrase", "slot", NULL};
static const char *kwlist[] = {"newPassphrase", "slot", NULL};
char *newpassphrase = NULL;
size_t newpassphrase_len = 0;
int slot = CRYPT_ANY_SLOT;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|i", kwlist, &newpassphrase, &slot))
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|i", CONST_CAST(char**)kwlist, &newpassphrase, &slot))
return NULL;
if (newpassphrase)
@@ -457,18 +502,20 @@ static PyObject *CryptSetup_addKeyByVolumeKey(CryptSetupObject* self, PyObject *
NULL, 0, newpassphrase, newpassphrase_len));
}
#define CryptSetup_removePassphrase_HELP "Destroy keyslot using passphrase\n\n\
static char
CryptSetup_removePassphrase_HELP[] =
"Destroy keyslot using passphrase\n\n\
removePassphrase(passphrase)\n\n\
passphrase - string or none to ask the user"
passphrase - string or none to ask the user";
static PyObject *CryptSetup_removePassphrase(CryptSetupObject* self, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"passphrase", NULL};
static const char *kwlist[] = {"passphrase", NULL};
char *passphrase = NULL;
size_t passphrase_len = 0;
int is;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &passphrase))
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", CONST_CAST(char**)kwlist, &passphrase))
return NULL;
if (passphrase)
@@ -482,16 +529,18 @@ static PyObject *CryptSetup_removePassphrase(CryptSetupObject* self, PyObject *a
return PyObjectResult(crypt_keyslot_destroy(self->device, is));
}
#define CryptSetup_killSlot_HELP "Destroy keyslot\n\n\
static char
CryptSetup_killSlot_HELP[] =
"Destroy keyslot\n\n\
killSlot(slot)\n\n\
slot - the slot to remove"
slot - the slot to remove";
static PyObject *CryptSetup_killSlot(CryptSetupObject* self, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"slot", NULL};
static const char *kwlist[] = {"slot", NULL};
int slot = CRYPT_ANY_SLOT;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &slot))
if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", CONST_CAST(char**)kwlist, &slot))
return NULL;
switch (crypt_keyslot_status(self->device, slot)) {
@@ -511,8 +560,10 @@ static PyObject *CryptSetup_killSlot(CryptSetupObject* self, PyObject *args, PyO
return NULL;
}
#define CryptSetup_Status_HELP "Status of LUKS device\n\n\
luksStatus()"
static char
CryptSetup_Status_HELP[] =
"Status of LUKS device\n\n\
luksStatus()";
static PyObject *CryptSetup_Status(CryptSetupObject* self, PyObject *args, PyObject *kwds)
{
@@ -524,13 +575,15 @@ static PyObject *CryptSetup_Status(CryptSetupObject* self, PyObject *args, PyObj
return PyObjectResult(crypt_status(self->device, self->activated_as));
}
#define CryptSetup_Resume_HELP "Resume LUKS device\n\n\
static char
CryptSetup_Resume_HELP[] =
"Resume LUKS device\n\n\
luksOpen(passphrase)\n\n\
passphrase - string or none to ask the user"
passphrase - string or none to ask the user";
static PyObject *CryptSetup_Resume(CryptSetupObject* self, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"passphrase", NULL};
static const char *kwlist[] = {"passphrase", NULL};
char* passphrase = NULL;
size_t passphrase_len = 0;
@@ -539,7 +592,7 @@ static PyObject *CryptSetup_Resume(CryptSetupObject* self, PyObject *args, PyObj
return NULL;
}
if (! PyArg_ParseTupleAndKeywords(args, kwds, "|s", kwlist, &passphrase))
if (! PyArg_ParseTupleAndKeywords(args, kwds, "|s", CONST_CAST(char**)kwlist, &passphrase))
return NULL;
if (passphrase)
@@ -549,8 +602,10 @@ static PyObject *CryptSetup_Resume(CryptSetupObject* self, PyObject *args, PyObj
CRYPT_ANY_SLOT, passphrase, passphrase_len));
}
#define CryptSetup_Suspend_HELP "Suspend LUKS device\n\n\
luksSupsend()"
static char
CryptSetup_Suspend_HELP[] =
"Suspend LUKS device\n\n\
luksSupsend()";
static PyObject *CryptSetup_Suspend(CryptSetupObject* self, PyObject *args, PyObject *kwds)
{
@@ -562,16 +617,18 @@ static PyObject *CryptSetup_Suspend(CryptSetupObject* self, PyObject *args, PyOb
return PyObjectResult(crypt_suspend(self->device, self->activated_as));
}
#define CryptSetup_debugLevel_HELP "Set debug level\n\n\
static char
CryptSetup_debugLevel_HELP[] =
"Set debug level\n\n\
debugLevel(level)\n\n\
level - debug level"
level - debug level";
static PyObject *CryptSetup_debugLevel(CryptSetupObject* self, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"level", NULL};
static const char *kwlist[] = {"level", NULL};
int level = 0;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &level))
if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", CONST_CAST(char**)kwlist, &level))
return NULL;
crypt_set_debug_level(level);
@@ -579,16 +636,18 @@ static PyObject *CryptSetup_debugLevel(CryptSetupObject* self, PyObject *args, P
Py_RETURN_NONE;
}
#define CryptSetup_iterationTime_HELP "Set iteration time\n\n\
static char
CryptSetup_iterationTime_HELP[] =
"Set iteration time\n\n\
iterationTime(time_ms)\n\n\
time_ms - time in miliseconds"
time_ms - time in miliseconds";
static PyObject *CryptSetup_iterationTime(CryptSetupObject* self, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"time_ms", NULL};
static const char *kwlist[] = {"time_ms", NULL};
uint64_t time_ms = 0;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "K", kwlist, &time_ms))
if (!PyArg_ParseTupleAndKeywords(args, kwds, "K", CONST_CAST(char**)kwlist, &time_ms))
return NULL;
crypt_set_iteration_time(self->device, time_ms);
@@ -597,9 +656,9 @@ static PyObject *CryptSetup_iterationTime(CryptSetupObject* self, PyObject *args
}
static PyMemberDef CryptSetup_members[] = {
{"yesDialogCB", T_OBJECT_EX, offsetof(CryptSetupObject, yesDialogCB), 0, "confirmation dialog callback"},
{"cmdLineLogCB", T_OBJECT_EX, offsetof(CryptSetupObject, cmdLineLogCB), 0, "logging callback"},
{"passwordDialogCB", T_OBJECT_EX, offsetof(CryptSetupObject, passwordDialogCB), 0, "password dialog callback"},
{CONST_CAST(char*)"yesDialogCB", T_OBJECT_EX, offsetof(CryptSetupObject, yesDialogCB), 0, CONST_CAST(char*)"confirmation dialog callback"},
{CONST_CAST(char*)"cmdLineLogCB", T_OBJECT_EX, offsetof(CryptSetupObject, cmdLineLogCB), 0, CONST_CAST(char*)"logging callback"},
{CONST_CAST(char*)"passwordDialogCB", T_OBJECT_EX, offsetof(CryptSetupObject, passwordDialogCB), 0, CONST_CAST(char*)"password dialog callback"},
{NULL}
};
@@ -615,7 +674,7 @@ static PyMethodDef CryptSetup_methods[] = {
/* cryptsetup info entrypoints */
{"luksUUID", (PyCFunction)CryptSetup_luksUUID, METH_NOARGS, CryptSetup_luksUUID_HELP},
{"isLuks", (PyCFunction)CryptSetup_isLuks, METH_NOARGS, CryptSetup_isLuks_HELP},
{"info", (PyCFunction)CryptSetup_Info, METH_NOARGS, CryptSetup_Info_HELP},
{"info", (PyCFunction)CryptSetup_Info, METH_NOARGS, CryptSetup_Info_HELP},
{"status", (PyCFunction)CryptSetup_Status, METH_NOARGS, CryptSetup_Status_HELP},
/* cryptsetup mgmt entrypoints */
@@ -637,8 +696,7 @@ static PyMethodDef CryptSetup_methods[] = {
};
static PyTypeObject CryptSetupType = {
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
PyVarObject_HEAD_INIT(NULL, 0)
"pycryptsetup.CryptSetup", /*tp_name*/
sizeof(CryptSetupObject), /*tp_basicsize*/
0, /*tp_itemsize*/
@@ -682,15 +740,14 @@ static PyMethodDef pycryptsetup_methods[] = {
{NULL} /* Sentinel */
};
PyMODINIT_FUNC initpycryptsetup(void);
PyMODINIT_FUNC initpycryptsetup(void)
MOD_INIT(pycryptsetup)
{
PyObject *m;
if (PyType_Ready(&CryptSetupType) < 0)
return;
return MOD_ERROR_VAL;
m = Py_InitModule3("pycryptsetup", pycryptsetup_methods, "CryptSetup pythonized API.");
MOD_DEF(m, "pycryptsetup", "CryptSetup pythonized API.", pycryptsetup_methods);
Py_INCREF(&CryptSetupType);
PyModule_AddObject(m, "CryptSetup", (PyObject *)&CryptSetupType);
@@ -710,4 +767,6 @@ PyMODINIT_FUNC initpycryptsetup(void)
PyModule_AddIntConstant(m, "CRYPT_INACTIVE", CRYPT_INACTIVE);
PyModule_AddIntConstant(m, "CRYPT_ACTIVE", CRYPT_ACTIVE);
PyModule_AddIntConstant(m, "CRYPT_BUSY", CRYPT_BUSY);
return MOD_SUCCESS_VAL(m);
}

View File

@@ -1,4 +1,4 @@
AM_CPPFLAGS = \
AM_CPPFLAGS = -include config.h \
-I$(top_srcdir) \
-I$(top_srcdir)/lib \
-DDATADIR=\""$(datadir)"\" \
@@ -6,8 +6,7 @@ AM_CPPFLAGS = \
-DLIBDIR=\""$(libdir)"\" \
-DPREFIX=\""$(prefix)"\" \
-DSYSCONFDIR=\""$(sysconfdir)"\" \
-DVERSION=\""$(VERSION)"\" \
-D_GNU_SOURCE
-DVERSION=\""$(VERSION)"\"
# cryptsetup
cryptsetup_SOURCES = \
@@ -22,10 +21,9 @@ cryptsetup_SOURCES = \
cryptsetup_LDADD = \
$(top_builddir)/lib/libcryptsetup.la \
@POPT_LIBS@ \
@FIPSCHECK_LIBS@ \
@PWQUALITY_LIBS@
cryptsetup_CFLAGS = -Wall
cryptsetup_CFLAGS = $(AM_CFLAGS) -Wall
sbin_PROGRAMS=cryptsetup
@@ -33,7 +31,7 @@ if STATIC_TOOLS
sbin_PROGRAMS += cryptsetup.static
cryptsetup_static_SOURCES = $(cryptsetup_SOURCES)
cryptsetup_static_CFLAGS = $(cryptsetup_CFLAGS)
cryptsetup_static_LDFLAGS = -all-static
cryptsetup_static_LDFLAGS = $(AM_LDFLAGS) -all-static
cryptsetup_static_LDADD = $(cryptsetup_LDADD) \
@CRYPTO_STATIC_LIBS@ \
@PWQUALITY_STATIC_LIBS@ \
@@ -63,7 +61,7 @@ if STATIC_TOOLS
sbin_PROGRAMS += veritysetup.static
veritysetup_static_SOURCES = $(veritysetup_SOURCES)
veritysetup_static_CFLAGS = $(veritysetup_CFLAGS)
veritysetup_static_LDFLAGS = -all-static
veritysetup_static_LDFLAGS = $(AM_LDFLAGS) -all-static
veritysetup_static_LDADD = $(veritysetup_LDADD) \
@CRYPTO_STATIC_LIBS@ \
@DEVMAPPER_STATIC_LIBS@ \
@@ -88,7 +86,7 @@ if STATIC_TOOLS
sbin_PROGRAMS += cryptsetup-reencrypt.static
cryptsetup_reencrypt_static_SOURCES = $(cryptsetup_reencrypt_SOURCES)
cryptsetup_reencrypt_static_CFLAGS = $(cryptsetup_reencrypt_CFLAGS)
cryptsetup_reencrypt_static_LDFLAGS = -all-static
cryptsetup_reencrypt_static_LDFLAGS = $(AM_LDFLAGS) -all-static
cryptsetup_reencrypt_static_LDADD = $(cryptsetup_reencrypt_LDADD) \
@CRYPTO_STATIC_LIBS@ \
@DEVMAPPER_STATIC_LIBS@ \

View File

@@ -1,10 +1,10 @@
/*
* cryptsetup - setup cryptographic volumes for dm-crypt
*
* Copyright (C) 2004, Christophe Saout <christophe@saout.de>
* Copyright (C) 2004, Jana Saout <jana@saout.de>
* Copyright (C) 2004-2007, Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2013, Milan Broz
* Copyright (C) 2009-2015, Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2015, Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -57,14 +57,26 @@ static int opt_urandom = 0;
static int opt_dump_master_key = 0;
static int opt_shared = 0;
static int opt_allow_discards = 0;
static int opt_perf_same_cpu_crypt = 0;
static int opt_perf_submit_from_crypt_cpus = 0;
static int opt_test_passphrase = 0;
static int opt_tcrypt_hidden = 0;
static int opt_tcrypt_system = 0;
static int opt_tcrypt_backup = 0;
static int opt_veracrypt = 0;
static const char **action_argv;
static int action_argc;
static const char *null_action_argv[] = {NULL, NULL};
static const char *uuid_or_device_header(const char **data_device)
{
if (data_device)
*data_device = opt_header_device ? action_argv[0] : NULL;
return uuid_or_device(opt_header_device ?: action_argv[0]);
}
static int _verify_passphrase(int def)
{
/* Batch mode switch off verify - if not overrided by -y */
@@ -83,6 +95,21 @@ static int _verify_passphrase(int def)
return def;
}
static void _set_activation_flags(uint32_t *flags)
{
if (opt_readonly)
*flags |= CRYPT_ACTIVATE_READONLY;
if (opt_allow_discards)
*flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS;
if (opt_perf_same_cpu_crypt)
*flags |= CRYPT_ACTIVATE_SAME_CPU_CRYPT;
if (opt_perf_submit_from_crypt_cpus)
*flags |= CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS;
}
static int action_open_plain(void)
{
struct crypt_device *cd = NULL;
@@ -97,19 +124,9 @@ static int action_open_plain(void)
size_t passwordLen;
size_t key_size = (opt_key_size ?: DEFAULT_PLAIN_KEYBITS) / 8;
uint32_t activate_flags = 0;
int keyfile_limited = 0;
int r;
if (params.hash && !strcmp(params.hash, "plain"))
params.hash = NULL;
/* FIXME: temporary hack */
if (opt_key_file && strcmp(opt_key_file, "-"))
params.hash = NULL;
if ((opt_keyfile_offset || opt_keyfile_size) && opt_key_file)
log_std(_("Ignoring keyfile offset and size options, keyfile read "
"size is always the same as encryption key size.\n"));
r = crypt_parse_name_and_mode(opt_cipher ?: DEFAULT_CIPHER(PLAIN),
cipher, NULL, cipher_mode);
if (r < 0) {
@@ -117,6 +134,24 @@ static int action_open_plain(void)
goto out;
}
if (opt_key_file && strcmp(opt_key_file, "-") != 0)
keyfile_limited = 1;
/* FIXME: temporary hack, no hashing for keyfiles in plain mode */
if (opt_key_file && keyfile_limited) {
params.hash = NULL;
if (!opt_batch_mode && opt_hash)
log_std(_("WARNING: The --hash parameter is being ignored "
"in plain mode with keyfile specified.\n"));
}
if (params.hash && !strcmp(params.hash, "plain"))
params.hash = NULL;
if (!opt_batch_mode && !params.hash && opt_key_file && keyfile_limited && opt_keyfile_size)
log_std(_("WARNING: The --keyfile-size option is being ignored, "
"the read size is the same as the encryption key size.\n"));
if ((r = crypt_init(&cd, action_argv[0])))
goto out;
@@ -132,22 +167,22 @@ static int action_open_plain(void)
if (r < 0)
goto out;
if (opt_readonly)
activate_flags |= CRYPT_ACTIVATE_READONLY;
if (opt_shared)
activate_flags |= CRYPT_ACTIVATE_SHARED;
if (opt_allow_discards)
activate_flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS;
_set_activation_flags(&activate_flags);
if (opt_key_file)
/* With hashing, read the whole keyfile */
if (opt_key_file) {
/* If no hash, key is read directly, read size is always key_size
* (possible opt_keyfile_size is ignored.
* If hash is specified, opt_keyfile_size is applied.
* The opt_keyfile_offset is applied always.
*/
r = crypt_activate_by_keyfile_offset(cd, action_argv[1],
CRYPT_ANY_SLOT, opt_key_file,
params.hash ? 0 : key_size, 0,
params.hash ? opt_keyfile_size : key_size, opt_keyfile_offset,
activate_flags);
else {
} else {
r = tools_get_key(_("Enter passphrase: "),
&password, &passwordLen,
opt_keyfile_offset, opt_keyfile_size,
@@ -184,11 +219,7 @@ static int action_open_loopaes(void)
return -EINVAL;
}
if (opt_readonly)
activate_flags |= CRYPT_ACTIVATE_READONLY;
if (opt_allow_discards)
activate_flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS;
_set_activation_flags(&activate_flags);
if ((r = crypt_init(&cd, action_argv[0])))
goto out;
@@ -201,23 +232,68 @@ static int action_open_loopaes(void)
r = crypt_activate_by_keyfile_offset(cd, action_argv[1], CRYPT_ANY_SLOT,
opt_key_file, opt_keyfile_size,
opt_keyfile_size, activate_flags);
opt_keyfile_offset, activate_flags);
out:
crypt_free(cd);
return r;
}
static int tcrypt_load(struct crypt_device *cd, struct crypt_params_tcrypt *params)
{
int r, tries = opt_tries, eperm = 0;
do {
/* TCRYPT header is encrypted, get passphrase now */
r = tools_get_key(_("Enter passphrase: "),
CONST_CAST(char**)&params->passphrase,
&params->passphrase_size, 0, 0, NULL, opt_timeout,
_verify_passphrase(0), 0, cd);
if (r < 0)
continue;
if (opt_tcrypt_hidden)
params->flags |= CRYPT_TCRYPT_HIDDEN_HEADER;
if (opt_tcrypt_system)
params->flags |= CRYPT_TCRYPT_SYSTEM_HEADER;
if (opt_tcrypt_backup)
params->flags |= CRYPT_TCRYPT_BACKUP_HEADER;
r = crypt_load(cd, CRYPT_TCRYPT, params);
if (r == -EPERM) {
log_err(_("No device header detected with this passphrase.\n"));
eperm = 1;
}
if (r < 0) {
crypt_safe_free(CONST_CAST(char*)params->passphrase);
params->passphrase = NULL;
params->passphrase_size = 0;
}
check_signal(&r);
} while (r == -EPERM && (--tries > 0));
/* Report wrong passphrase if at least one try failed */
if (eperm && r == -EPIPE)
r = -EPERM;
return r;
}
static int action_open_tcrypt(void)
{
struct crypt_device *cd = NULL;
struct crypt_params_tcrypt params = {
.keyfiles = opt_keyfiles,
.keyfiles_count = opt_keyfiles_count,
.flags = CRYPT_TCRYPT_LEGACY_MODES,
.flags = CRYPT_TCRYPT_LEGACY_MODES |
(opt_veracrypt ? CRYPT_TCRYPT_VERA_MODES : 0),
};
const char *activated_name;
uint32_t flags = 0;
uint32_t activate_flags = 0;
int r;
activated_name = opt_test_passphrase ? NULL : action_argv[1];
@@ -225,33 +301,15 @@ static int action_open_tcrypt(void)
if ((r = crypt_init(&cd, action_argv[0])))
goto out;
/* TCRYPT header is encrypted, get passphrase now */
r = tools_get_key(_("Enter passphrase: "),
CONST_CAST(char**)&params.passphrase,
&params.passphrase_size, 0, 0, NULL, opt_timeout,
_verify_passphrase(0), 0, cd);
r = tcrypt_load(cd, &params);
if (r < 0)
goto out;
if (opt_tcrypt_hidden)
params.flags |= CRYPT_TCRYPT_HIDDEN_HEADER;
if (opt_tcrypt_system)
params.flags |= CRYPT_TCRYPT_SYSTEM_HEADER;
r = crypt_load(cd, CRYPT_TCRYPT, &params);
check_signal(&r);
if (r < 0)
goto out;
if (opt_readonly)
flags |= CRYPT_ACTIVATE_READONLY;
_set_activation_flags(&activate_flags);
if (activated_name)
r = crypt_activate_by_volume_key(cd, activated_name, NULL, 0, flags);
r = crypt_activate_by_volume_key(cd, activated_name, NULL, 0, activate_flags);
out:
if (r == -EPERM)
log_err(_("No device header detected with this passphrase.\n"));
crypt_free(cd);
crypt_safe_free(CONST_CAST(char*)params.passphrase);
return r;
@@ -305,29 +363,15 @@ static int action_tcryptDump(void)
struct crypt_params_tcrypt params = {
.keyfiles = opt_keyfiles,
.keyfiles_count = opt_keyfiles_count,
.flags = CRYPT_TCRYPT_LEGACY_MODES,
.flags = CRYPT_TCRYPT_LEGACY_MODES |
(opt_veracrypt ? CRYPT_TCRYPT_VERA_MODES : 0),
};
int r;
if ((r = crypt_init(&cd, action_argv[0])))
goto out;
/* TCRYPT header is encrypted, get passphrase now */
r = tools_get_key(_("Enter passphrase: "),
CONST_CAST(char**)&params.passphrase,
&params.passphrase_size, 0, 0, NULL, opt_timeout,
_verify_passphrase(0), 0, cd);
if (r < 0)
goto out;
if (opt_tcrypt_hidden)
params.flags |= CRYPT_TCRYPT_HIDDEN_HEADER;
if (opt_tcrypt_system)
params.flags |= CRYPT_TCRYPT_SYSTEM_HEADER;
r = crypt_load(cd, CRYPT_TCRYPT, &params);
check_signal(&r);
r = tcrypt_load(cd, &params);
if (r < 0)
goto out;
@@ -336,8 +380,6 @@ static int action_tcryptDump(void)
else
r = crypt_dump(cd);
out:
if (r == -EPERM)
log_err(_("No device header detected with this passphrase.\n"));
crypt_free(cd);
crypt_safe_free(CONST_CAST(char*)params.passphrase);
return r;
@@ -404,10 +446,10 @@ static int action_status(void)
ci == CRYPT_BUSY ? " and is in use" : "");
r = crypt_init_by_name_and_header(&cd, action_argv[0], opt_header_device);
if (r < 0 || !crypt_get_type(cd))
if (r < 0)
goto out;
log_std(" type: %s\n", crypt_get_type(cd));
log_std(" type: %s\n", crypt_get_type(cd) ?: "n/a");
r = crypt_get_active_device(cd, action_argv[0], &cad);
if (r < 0)
@@ -428,8 +470,13 @@ static int action_status(void)
log_std(" skipped: %" PRIu64 " sectors\n", cad.iv_offset);
log_std(" mode: %s\n", cad.flags & CRYPT_ACTIVATE_READONLY ?
"readonly" : "read/write");
if (cad.flags & CRYPT_ACTIVATE_ALLOW_DISCARDS)
log_std(" flags: discards\n");
if (cad.flags & (CRYPT_ACTIVATE_ALLOW_DISCARDS|
CRYPT_ACTIVATE_ALLOW_DISCARDS|
CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS))
log_std(" flags: %s%s%s\n",
(cad.flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) ? "discards " : "",
(cad.flags & CRYPT_ACTIVATE_SAME_CPU_CRYPT) ? "same_cpu_crypt " : "",
(cad.flags & CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS) ? "submit_from_crypt_cpus" : "");
}
out:
crypt_free(cd);
@@ -453,6 +500,29 @@ static int action_benchmark_kdf(const char *hash)
return r;
}
static int benchmark_cipher_loop(const char *cipher, const char *cipher_mode,
size_t volume_key_size, size_t iv_size,
double *encryption_mbs, double *decryption_mbs)
{
int r, buffer_size = 1024 * 1024;
do {
r = crypt_benchmark(NULL, cipher, cipher_mode,
volume_key_size, iv_size, buffer_size,
encryption_mbs, decryption_mbs);
if (r == -ERANGE) {
if (buffer_size < 1024 * 1024 * 65)
buffer_size *= 2;
else {
log_err(_("Result of benchmark is not reliable.\n"));
r = -ENOENT;
}
}
} while (r == -ERANGE);
return r;
}
static int action_benchmark(void)
{
static struct {
@@ -482,7 +552,6 @@ static int action_benchmark(void)
double enc_mbr = 0, dec_mbr = 0;
int key_size = (opt_key_size ?: DEFAULT_PLAIN_KEYBITS);
int iv_size = 16, skipped = 0;
int buffer_size = 1024 * 1024;
char *c;
int i, r;
@@ -504,9 +573,12 @@ static int action_benchmark(void)
strstr(cipher, "cast5"))
iv_size = 8;
r = crypt_benchmark(NULL, cipher, cipher_mode,
key_size / 8, iv_size, buffer_size,
&enc_mbr, &dec_mbr);
if (!strcmp(cipher_mode, "ecb"))
iv_size = 0;
r = benchmark_cipher_loop(cipher, cipher_mode,
key_size / 8, iv_size,
&enc_mbr, &dec_mbr);
if (!r) {
log_std(N_("# Algorithm | Key | Encryption | Decryption\n"));
log_std("%8s-%s %4db %6.1f MiB/s %6.1f MiB/s\n",
@@ -521,9 +593,9 @@ static int action_benchmark(void)
break;
}
for (i = 0; bciphers[i].cipher; i++) {
r = crypt_benchmark(NULL, bciphers[i].cipher, bciphers[i].mode,
r = benchmark_cipher_loop(bciphers[i].cipher, bciphers[i].mode,
bciphers[i].key_size, bciphers[i].iv_size,
buffer_size, &enc_mbr, &dec_mbr);
&enc_mbr, &dec_mbr);
check_signal(&r);
if (r == -ENOTSUP || r == -EINTR)
break;
@@ -535,10 +607,10 @@ static int action_benchmark(void)
snprintf(cipher, MAX_CIPHER_LEN, "%s-%s",
bciphers[i].cipher, bciphers[i].mode);
if (!r)
log_std("%12s %4db %6.1f MiB/s %6.1f MiB/s\n",
log_std("%12s %4zub %6.1f MiB/s %6.1f MiB/s\n",
cipher, bciphers[i].key_size*8, enc_mbr, dec_mbr);
else
log_std("%12s %4db %13s %13s\n", cipher,
log_std("%12s %4zub %13s %13s\n", cipher,
bciphers[i].key_size*8, _("N/A"), _("N/A"));
}
if (skipped && skipped == i)
@@ -691,16 +763,10 @@ static int action_open_luks(void)
struct crypt_device *cd = NULL;
const char *data_device, *header_device, *activated_name;
char *key = NULL;
uint32_t flags = 0;
uint32_t activate_flags = 0;
int r, keysize;
if (opt_header_device) {
header_device = uuid_or_device(opt_header_device);
data_device = action_argv[0];
} else {
header_device = uuid_or_device(action_argv[0]);
data_device = NULL;
}
header_device = uuid_or_device_header(&data_device);
activated_name = opt_test_passphrase ? NULL : action_argv[1];
@@ -727,11 +793,7 @@ static int action_open_luks(void)
if (opt_iteration_time)
crypt_set_iteration_time(cd, opt_iteration_time);
if (opt_readonly)
flags |= CRYPT_ACTIVATE_READONLY;
if (opt_allow_discards)
flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS;
_set_activation_flags(&activate_flags);
if (opt_master_key_file) {
keysize = crypt_get_volume_key_size(cd);
@@ -739,15 +801,15 @@ static int action_open_luks(void)
if (r < 0)
goto out;
r = crypt_activate_by_volume_key(cd, activated_name,
key, keysize, flags);
key, keysize, activate_flags);
} else if (opt_key_file) {
crypt_set_password_retry(cd, 1);
r = crypt_activate_by_keyfile_offset(cd, activated_name,
opt_key_slot, opt_key_file, opt_keyfile_size,
opt_keyfile_offset, flags);
opt_keyfile_offset, activate_flags);
} else
r = crypt_activate_by_passphrase(cd, activated_name,
opt_key_slot, NULL, 0, flags);
opt_key_slot, NULL, 0, activate_flags);
out:
crypt_safe_free(key);
crypt_free(cd);
@@ -804,7 +866,7 @@ static int action_luksKillSlot(void)
struct crypt_device *cd = NULL;
int r;
if ((r = crypt_init(&cd, uuid_or_device(action_argv[0]))))
if ((r = crypt_init(&cd, uuid_or_device_header(NULL))))
goto out;
crypt_set_confirm_callback(cd, yesDialog, NULL);
@@ -847,7 +909,7 @@ static int action_luksRemoveKey(void)
size_t passwordLen;
int r;
if ((r = crypt_init(&cd, uuid_or_device(action_argv[0]))))
if ((r = crypt_init(&cd, uuid_or_device_header(NULL))))
goto out;
crypt_set_confirm_callback(cd, yesDialog, NULL);
@@ -898,7 +960,7 @@ static int action_luksAddKey(void)
size_t password_size = 0, password_new_size = 0;
struct crypt_device *cd = NULL;
if ((r = crypt_init(&cd, uuid_or_device(action_argv[0]))))
if ((r = crypt_init(&cd, uuid_or_device_header(NULL))))
goto out;
crypt_set_confirm_callback(cd, yesDialog, NULL);
@@ -917,9 +979,22 @@ static int action_luksAddKey(void)
r = _read_mk(opt_master_key_file, &key, keysize);
if (r < 0)
goto out;
//FIXME: process keyfile arg
r = crypt_keyslot_add_by_volume_key(cd, opt_key_slot,
key, keysize, NULL, 0);
r = crypt_volume_key_verify(cd, key, keysize);
check_signal(&r);
if (r < 0)
goto out;
r = tools_get_key(_("Enter new passphrase for key slot: "),
&password_new, &password_new_size,
opt_new_keyfile_offset, opt_new_keyfile_size,
opt_new_key_file, opt_timeout,
_verify_passphrase(1), 1, cd);
if (r < 0)
goto out;
r = crypt_keyslot_add_by_volume_key(cd, opt_key_slot, key, keysize,
password_new, password_new_size);
} else if (opt_key_file || opt_new_key_file) {
r = crypt_keyslot_add_by_keyfile_offset(cd, opt_key_slot,
opt_key_file, opt_keyfile_size, opt_keyfile_offset,
@@ -941,7 +1016,7 @@ static int action_luksAddKey(void)
r = tools_get_key(_("Enter new passphrase for key slot: "),
&password_new, &password_new_size, 0, 0, NULL,
opt_timeout, _verify_passphrase(0), 1, cd);
opt_timeout, _verify_passphrase(1), 1, cd);
if (r < 0)
goto out;
@@ -965,7 +1040,7 @@ static int action_luksChangeKey(void)
size_t password_size = 0, password_new_size = 0;
int r;
if ((r = crypt_init(&cd, uuid_or_device(action_argv[0]))))
if ((r = crypt_init(&cd, uuid_or_device_header(NULL))))
goto out;
if ((r = crypt_load(cd, CRYPT_LUKS1, NULL)))
@@ -992,7 +1067,7 @@ static int action_luksChangeKey(void)
&password_new, &password_new_size,
opt_new_keyfile_offset, opt_new_keyfile_size,
opt_new_key_file,
opt_timeout, _verify_passphrase(0), 1, cd);
opt_timeout, _verify_passphrase(1), 1, cd);
if (r < 0)
goto out;
@@ -1010,7 +1085,13 @@ static int action_isLuks(void)
struct crypt_device *cd = NULL;
int r;
if ((r = crypt_init(&cd, action_argv[0])))
/* FIXME: argc > max should be checked for other operations as well */
if (action_argc > 1) {
log_err(_("Only one device argument for isLuks operation is supported.\n"));
return -ENODEV;
}
if ((r = crypt_init(&cd, uuid_or_device_header(NULL))))
goto out;
crypt_set_log_callback(cd, quiet_log, NULL);
@@ -1026,7 +1107,7 @@ static int action_luksUUID(void)
const char *existing_uuid = NULL;
int r;
if ((r = crypt_init(&cd, action_argv[0])))
if ((r = crypt_init(&cd, uuid_or_device_header(NULL))))
goto out;
crypt_set_confirm_callback(cd, yesDialog, NULL);
@@ -1105,7 +1186,7 @@ static int action_luksDump(void)
struct crypt_device *cd = NULL;
int r;
if ((r = crypt_init(&cd, uuid_or_device(action_argv[0]))))
if ((r = crypt_init(&cd, uuid_or_device_header(NULL))))
goto out;
if ((r = crypt_load(cd, CRYPT_LUKS1, NULL)))
@@ -1125,7 +1206,7 @@ static int action_luksSuspend(void)
struct crypt_device *cd = NULL;
int r;
r = crypt_init_by_name_and_header(&cd, action_argv[0], opt_header_device);
r = crypt_init_by_name_and_header(&cd, action_argv[0], uuid_or_device(opt_header_device));
if (!r)
r = crypt_suspend(cd, action_argv[0]);
@@ -1138,7 +1219,7 @@ static int action_luksResume(void)
struct crypt_device *cd = NULL;
int r;
if ((r = crypt_init_by_name_and_header(&cd, action_argv[0], opt_header_device)))
if ((r = crypt_init_by_name_and_header(&cd, action_argv[0], uuid_or_device(opt_header_device))))
goto out;
crypt_set_timeout(cd, opt_timeout);
@@ -1166,7 +1247,7 @@ static int action_luksBackup(void)
return -EINVAL;
}
if ((r = crypt_init(&cd, uuid_or_device(action_argv[0]))))
if ((r = crypt_init(&cd, uuid_or_device_header(NULL))))
goto out;
crypt_set_confirm_callback(cd, yesDialog, NULL);
@@ -1187,7 +1268,7 @@ static int action_luksRestore(void)
return -EINVAL;
}
if ((r = crypt_init(&cd, action_argv[0])))
if ((r = crypt_init(&cd, uuid_or_device_header(NULL))))
goto out;
crypt_set_confirm_callback(cd, yesDialog, NULL);
@@ -1227,6 +1308,47 @@ args:
return -EINVAL;
}
static int action_luksErase(void)
{
struct crypt_device *cd = NULL;
crypt_keyslot_info ki;
char *msg = NULL;
int i, r;
if ((r = crypt_init(&cd, uuid_or_device_header(NULL))))
goto out;
crypt_set_confirm_callback(cd, yesDialog, NULL);
if ((r = crypt_load(cd, CRYPT_LUKS1, NULL)))
goto out;
if(asprintf(&msg, _("This operation will erase all keyslots on device %s.\n"
"Device will become unusable after this operation."),
uuid_or_device_header(NULL)) == -1) {
r = -ENOMEM;
goto out;
}
if (!yesDialog(msg, NULL)) {
r = -EPERM;
goto out;
}
for (i = 0; i < crypt_keyslot_max(CRYPT_LUKS1); i++) {
ki = crypt_keyslot_status(cd, i);
if (ki == CRYPT_SLOT_ACTIVE || ki == CRYPT_SLOT_ACTIVE_LAST) {
r = crypt_keyslot_destroy(cd, i);
if (r < 0)
goto out;
}
}
out:
free(msg);
crypt_free(cd);
return r;
}
static struct action_type {
const char *type;
int (*handler)(void);
@@ -1241,6 +1363,7 @@ static struct action_type {
{ "status", action_status, 1, 0, N_("<name>"), N_("show device status") },
{ "benchmark", action_benchmark, 0, 0, N_("<name>"), N_("benchmark cipher") },
{ "repair", action_luksRepair, 1, 1, N_("<device>"), N_("try to repair on-disk metadata") },
{ "erase", action_luksErase , 1, 1, N_("<device>"), N_("erase all keyslots (remove encryption key)") },
{ "luksFormat", action_luksFormat, 1, 1, N_("<device> [<new key file>]"), N_("formats a LUKS device") },
{ "luksAddKey", action_luksAddKey, 1, 1, N_("<device> [<new key file>]"), N_("add key to LUKS device") },
{ "luksRemoveKey",action_luksRemoveKey,1, 1, N_("<device> [<key file>]"), N_("removes supplied key or key file from LUKS device") },
@@ -1384,8 +1507,12 @@ int main(int argc, const char **argv)
{ "test-passphrase", '\0', POPT_ARG_NONE, &opt_test_passphrase, 0, N_("Do not activate device, just check passphrase."), NULL },
{ "tcrypt-hidden", '\0', POPT_ARG_NONE, &opt_tcrypt_hidden, 0, N_("Use hidden header (hidden TCRYPT device)."), NULL },
{ "tcrypt-system", '\0', POPT_ARG_NONE, &opt_tcrypt_system, 0, N_("Device is system TCRYPT drive (with bootloader)."), NULL },
{ "tcrypt-backup", '\0', POPT_ARG_NONE, &opt_tcrypt_backup, 0, N_("Use backup (secondary) TCRYPT header."), NULL },
{ "veracrypt", '\0', POPT_ARG_NONE, &opt_veracrypt, 0, N_("Scan also for VeraCrypt compatible device."), NULL },
{ "type", 'M', POPT_ARG_STRING, &opt_type, 0, N_("Type of device metadata: luks, plain, loopaes, tcrypt."), NULL },
{ "force-password", '\0', POPT_ARG_NONE, &opt_force_password, 0, N_("Disable password quality check (if enabled)."), NULL },
{ "perf-same_cpu_crypt",'\0', POPT_ARG_NONE, &opt_perf_same_cpu_crypt, 0, N_("Use dm-crypt same_cpu_crypt performance compatibility option."), NULL },
{ "perf-submit_from_crypt_cpus",'\0', POPT_ARG_NONE, &opt_perf_submit_from_crypt_cpus,0,N_("Use dm-crypt submit_from_crypt_cpus performance compatibility option."), NULL },
POPT_TABLEEND
};
poptContext popt_context;
@@ -1399,8 +1526,6 @@ int main(int argc, const char **argv)
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
crypt_fips_self_check(NULL);
popt_context = poptGetContext(PACKAGE, argc, argv, popt_options, 0);
poptSetOtherOptionHelp(popt_context,
_("[OPTION...] <action> <action-specific>"));
@@ -1442,6 +1567,10 @@ int main(int argc, const char **argv)
if (r < -1)
usage(popt_context, EXIT_FAILURE, poptStrerror(r),
poptBadOption(popt_context, POPT_BADOPTION_NOALIAS));
if (crypt_fips_mode())
crypt_log(NULL, CRYPT_LOG_VERBOSE, _("Running in FIPS mode.\n"));
if (opt_version_mode) {
log_std("%s %s\n", PACKAGE_NAME, PACKAGE_VERSION);
poptFreeContext(popt_context);
@@ -1484,12 +1613,17 @@ int main(int argc, const char **argv)
} else if (!strcmp(aname, "tcryptOpen")) {
aname = "open";
opt_type = "tcrypt";
} else if (!strcmp(aname, "tcryptDump")) {
opt_type = "tcrypt";
} else if (!strcmp(aname, "remove") ||
!strcmp(aname, "plainClose") ||
!strcmp(aname, "luksClose") ||
!strcmp(aname, "loopaesClose") ||
!strcmp(aname, "tcryptClose")) {
aname = "close";
} else if (!strcmp(aname, "luksErase")) {
aname = "erase";
opt_type = "luks";
}
for(action = action_types; action->type; action++)
@@ -1500,7 +1634,7 @@ int main(int argc, const char **argv)
usage(popt_context, EXIT_FAILURE, _("Unknown action."),
poptGetInvocationName(popt_context));
if(action_argc < action->required_action_argc)
if (action_argc < action->required_action_argc)
help_args(action, popt_context);
/* FIXME: rewrite this from scratch */
@@ -1585,10 +1719,20 @@ int main(int argc, const char **argv)
_("Option --offset is supported only for open of plain and loopaes devices.\n"),
poptGetInvocationName(popt_context));
if ((opt_tcrypt_hidden || opt_tcrypt_system) && strcmp(aname, "tcryptDump") &&
if ((opt_tcrypt_hidden || opt_tcrypt_system || opt_tcrypt_backup) && strcmp(aname, "tcryptDump") &&
(strcmp(aname, "open") || strcmp(opt_type, "tcrypt")))
usage(popt_context, EXIT_FAILURE,
_("Option --tcrypt-hidden or --tcrypt-system is supported only for TCRYPT device.\n"),
_("Option --tcrypt-hidden, --tcrypt-system or --tcrypt-backup is supported only for TCRYPT device.\n"),
poptGetInvocationName(popt_context));
if (opt_tcrypt_hidden && opt_allow_discards)
usage(popt_context, EXIT_FAILURE,
_("Option --tcrypt-hidden cannot be combined with --allow-discards.\n"),
poptGetInvocationName(popt_context));
if (opt_veracrypt && strcmp(opt_type, "tcrypt"))
usage(popt_context, EXIT_FAILURE,
_("Option --veracrypt is supported only for TCRYPT device type.\n"),
poptGetInvocationName(popt_context));
if (opt_debug) {

View File

@@ -1,10 +1,10 @@
/*
* cryptsetup - setup cryptographic volumes for dm-crypt
*
* Copyright (C) 2004, Christophe Saout <christophe@saout.de>
* Copyright (C) 2004, Jana Saout <jana@saout.de>
* Copyright (C) 2004-2007, Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2013, Milan Broz
* Copyright (C) 2009-2014, 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,11 +24,6 @@
#ifndef CRYPTSETUP_H
#define CRYPTSETUP_H
#define _LARGEFILE64_SOURCE
#define _FILE_OFFSET_BITS 64
#include <config.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
@@ -62,7 +57,7 @@ extern int opt_force_password;
/* Common tools */
void clogger(struct crypt_device *cd, int level, const char *file, int line,
const char *format, ...);
const char *format, ...) __attribute__ ((format (printf, 5, 6)));
void tool_log(int level, const char *msg, void *usrptr __attribute__((unused)));
void quiet_log(int level, const char *msg, void *usrptr);

View File

@@ -2,7 +2,7 @@
* cryptsetup-reencrypt - crypt utility for offline re-encryption
*
* Copyright (C) 2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2013, Milan Broz All rights reserved.
* Copyright (C) 2012-2015, Milan Broz 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
@@ -47,6 +47,8 @@ static int opt_tries = 3;
static int opt_key_slot = CRYPT_ANY_SLOT;
static int opt_key_size = 0;
static int opt_new = 0;
static int opt_keep_key = 0;
static int opt_decrypt = 0;
static const char *opt_reduce_size_str = NULL;
static uint64_t opt_reduce_size = 0;
@@ -61,12 +63,14 @@ struct reenc_ctx {
char *device;
char *device_uuid;
uint64_t device_size; /* overrided by parameter */
uint64_t device_size_real;
uint64_t device_size_new_real;
uint64_t device_size_org_real;
uint64_t device_offset;
uint64_t device_shift;
int in_progress:1;
enum { FORWARD = 0, BACKWARD = 1 } reencrypt_direction;
enum { REENCRYPT = 0, ENCRYPT = 1, DECRYPT = 2 } reencrypt_mode;
char header_file_org[PATH_MAX];
char header_file_new[PATH_MAX];
@@ -75,7 +79,7 @@ struct reenc_ctx {
char crypt_path_org[PATH_MAX];
char crypt_path_new[PATH_MAX];
int log_fd;
char *log_buf;
char log_buf[SECTOR_SIZE];
struct {
char *password;
@@ -122,6 +126,12 @@ static int alignment(int fd)
return alignment;
}
static size_t pagesize(void)
{
long r = sysconf(_SC_PAGESIZE);
return r < 0 ? 4096 : (size_t)r;
}
/* Depends on the first two fields of LUKS1 header format, magic and version */
static int device_check(struct reenc_ctx *rc, header_magic set_magic)
{
@@ -129,6 +139,7 @@ static int device_check(struct reenc_ctx *rc, header_magic set_magic)
int r, devfd;
ssize_t s;
uint16_t version;
size_t buf_size = pagesize();
devfd = open(rc->device, O_RDWR | O_EXCL | O_DIRECT);
if (devfd == -1) {
@@ -146,14 +157,14 @@ static int device_check(struct reenc_ctx *rc, header_magic set_magic)
goto out;
}
if (posix_memalign((void *)&buf, alignment(devfd), SECTOR_SIZE)) {
if (posix_memalign((void *)&buf, alignment(devfd), buf_size)) {
log_err(_("Allocation of aligned memory failed.\n"));
r = -ENOMEM;
goto out;
}
s = read(devfd, buf, SECTOR_SIZE);
if (s < 0 || s != SECTOR_SIZE) {
s = read(devfd, buf, buf_size);
if (s < 0 || s != (ssize_t)buf_size) {
log_err(_("Cannot read device %s.\n"), rc->device);
r = -EIO;
goto out;
@@ -184,8 +195,8 @@ static int device_check(struct reenc_ctx *rc, header_magic set_magic)
if (!r) {
if (lseek(devfd, 0, SEEK_SET) == -1)
goto out;
s = write(devfd, buf, SECTOR_SIZE);
if (s < 0 || s != SECTOR_SIZE) {
s = write(devfd, buf, buf_size);
if (s < 0 || s != (ssize_t)buf_size) {
log_err(_("Cannot write device %s.\n"), rc->device);
r = -EIO;
}
@@ -193,7 +204,7 @@ static int device_check(struct reenc_ctx *rc, header_magic set_magic)
log_dbg("LUKS signature check failed for %s.", rc->device);
out:
if (buf)
memset(buf, 0, SECTOR_SIZE);
memset(buf, 0, buf_size);
free(buf);
close(devfd);
return r;
@@ -257,9 +268,9 @@ static int write_log(struct reenc_ctx *rc)
memset(rc->log_buf, 0, SECTOR_SIZE);
snprintf(rc->log_buf, SECTOR_SIZE, "# LUKS reencryption log, DO NOT EDIT OR DELETE.\n"
"version = %d\nUUID = %s\ndirection = %d\n"
"version = %d\nUUID = %s\ndirection = %d\nmode = %d\n"
"offset = %" PRIu64 "\nshift = %" PRIu64 "\n# EOF\n",
1, rc->device_uuid, rc->reencrypt_direction,
2, rc->device_uuid, rc->reencrypt_direction, rc->reencrypt_mode,
rc->device_offset, rc->device_shift);
if (lseek(rc->log_fd, 0, SEEK_SET) == -1)
@@ -285,7 +296,7 @@ static int parse_line_log(struct reenc_ctx *rc, const char *line)
return 0;
if (sscanf(line, "version = %d", &i) == 1) {
if (i != 1) {
if (i < 1 || i > 2) {
log_dbg("Log: Unexpected version = %i", i);
return -EINVAL;
}
@@ -303,6 +314,13 @@ static int parse_line_log(struct reenc_ctx *rc, const char *line)
} else if (sscanf(line, "shift = %" PRIu64, &u64) == 1) {
log_dbg("Log: shift = %" PRIu64, u64);
rc->device_shift = u64;
} else if (sscanf(line, "mode = %d", &i) == 1) { /* added in v2 */
log_dbg("Log: mode = %i", i);
rc->reencrypt_mode = i;
if (rc->reencrypt_mode != REENCRYPT &&
rc->reencrypt_mode != ENCRYPT &&
rc->reencrypt_mode != DECRYPT)
return -EINVAL;
} else
return -EINVAL;
@@ -343,13 +361,11 @@ static void close_log(struct reenc_ctx *rc)
log_dbg("Closing LUKS reencryption log file %s.", rc->log_file);
if (rc->log_fd != -1)
close(rc->log_fd);
free(rc->log_buf);
rc->log_buf = NULL;
}
static int open_log(struct reenc_ctx *rc)
{
int flags = opt_directio ? O_DIRECT : 0;
int flags = opt_fsync ? O_SYNC : 0;
rc->log_fd = open(rc->log_file, O_RDWR|O_EXCL|O_CREAT|flags, S_IRUSR|S_IWUSR);
if (rc->log_fd != -1) {
@@ -363,12 +379,6 @@ static int open_log(struct reenc_ctx *rc)
if (rc->log_fd == -1)
return -EINVAL;
if (posix_memalign((void *)&rc->log_buf, alignment(rc->log_fd), SECTOR_SIZE)) {
log_err(_("Allocation of aligned memory failed.\n"));
close_log(rc);
return -ENOMEM;
}
if (!rc->in_progress && write_log(rc) < 0) {
close_log(rc);
return -EIO;
@@ -417,7 +427,8 @@ out:
static int create_new_header(struct reenc_ctx *rc, const char *cipher,
const char *cipher_mode, const char *uuid,
int key_size, struct crypt_params_luks1 *params)
const char *key, int key_size,
struct crypt_params_luks1 *params)
{
struct crypt_device *cd_new = NULL;
int i, r;
@@ -434,7 +445,7 @@ static int create_new_header(struct reenc_ctx *rc, const char *cipher,
crypt_set_iteration_time(cd_new, opt_iteration_time);
if ((r = crypt_format(cd_new, CRYPT_LUKS1, cipher, cipher_mode,
uuid, NULL, key_size, params)))
uuid, key, key_size, params)))
goto out;
log_verbose(_("New LUKS header for device %s created.\n"), rc->device);
@@ -457,6 +468,8 @@ static int backup_luks_headers(struct reenc_ctx *rc)
struct crypt_device *cd = NULL;
struct crypt_params_luks1 params = {0};
char cipher [MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN];
char *old_key = NULL;
size_t old_key_size;
int r;
log_dbg("Creating LUKS header backup for device %s.", rc->device);
@@ -470,6 +483,10 @@ static int backup_luks_headers(struct reenc_ctx *rc)
goto out;
log_verbose(_("LUKS header backup of device %s created.\n"), rc->device);
/* For decrypt, new header will be fake one, so we are done here. */
if (rc->reencrypt_mode == DECRYPT)
goto out;
if ((r = create_empty_header(rc->header_file_new, rc->header_file_org,
crypt_get_data_offset(cd))))
goto out;
@@ -487,14 +504,30 @@ static int backup_luks_headers(struct reenc_ctx *rc)
}
}
if (opt_keep_key) {
log_dbg("Keeping key from old header.");
old_key_size = crypt_get_volume_key_size(cd);
old_key = crypt_safe_alloc(old_key_size);
if (!old_key) {
r = -ENOMEM;
goto out;
}
r = crypt_volume_key_get(cd, CRYPT_ANY_SLOT, old_key, &old_key_size,
rc->p[rc->keyslot].password, rc->p[rc->keyslot].passwordLen);
if (r < 0)
goto out;
}
r = create_new_header(rc,
opt_cipher ? cipher : crypt_get_cipher(cd),
opt_cipher ? cipher_mode : crypt_get_cipher_mode(cd),
crypt_get_uuid(cd),
old_key,
opt_key_size ? opt_key_size / 8 : crypt_get_volume_key_size(cd),
&params);
out:
crypt_free(cd);
crypt_safe_free(old_key);
if (r)
log_err(_("Creation of LUKS backup headers failed.\n"));
return r;
@@ -506,10 +539,13 @@ static int backup_fake_header(struct reenc_ctx *rc)
struct crypt_device *cd_new = NULL;
struct crypt_params_luks1 params = {0};
char cipher [MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN];
const char *header_file_fake;
int r;
log_dbg("Creating fake (cipher_null) header for original device.");
log_dbg("Creating fake (cipher_null) header for %s device.",
(rc->reencrypt_mode == DECRYPT) ? "new" : "original");
header_file_fake = (rc->reencrypt_mode == DECRYPT) ? rc->header_file_new : rc->header_file_org;
if (!opt_key_size)
opt_key_size = DEFAULT_LUKS1_KEYBITS;
@@ -522,7 +558,7 @@ static int backup_fake_header(struct reenc_ctx *rc)
}
}
r = create_empty_header(rc->header_file_org, NULL, 0);
r = create_empty_header(header_file_fake, NULL, MAX_BCK_SECTORS);
if (r < 0)
return r;
@@ -530,7 +566,7 @@ static int backup_fake_header(struct reenc_ctx *rc)
params.data_alignment = 0;
params.data_device = rc->device;
r = crypt_init(&cd_new, rc->header_file_org);
r = crypt_init(&cd_new, header_file_fake);
if (r < 0)
return r;
@@ -539,11 +575,15 @@ static int backup_fake_header(struct reenc_ctx *rc)
if (r < 0)
goto out;
r = crypt_keyslot_add_by_volume_key(cd_new, 0, NULL, 0,
rc->p[0].password, rc->p[0].passwordLen);
r = crypt_keyslot_add_by_volume_key(cd_new, rc->keyslot, NULL, 0,
rc->p[rc->keyslot].password, rc->p[rc->keyslot].passwordLen);
if (r < 0)
goto out;
/* The real header is backup header created in backup_luks_headers() */
if (rc->reencrypt_mode == DECRYPT)
goto out;
r = create_empty_header(rc->header_file_new, rc->header_file_org, 0);
if (r < 0)
goto out;
@@ -552,7 +592,7 @@ static int backup_fake_header(struct reenc_ctx *rc)
r = create_new_header(rc,
opt_cipher ? cipher : DEFAULT_LUKS1_CIPHER,
opt_cipher ? cipher_mode : DEFAULT_LUKS1_MODE,
NULL,
NULL, NULL,
(opt_key_size ? opt_key_size : DEFAULT_LUKS1_KEYBITS) / 8,
&params);
out:
@@ -633,6 +673,29 @@ static void print_progress(struct reenc_ctx *rc, uint64_t bytes, int final)
final ? "\n" :"");
}
static ssize_t read_buf(int fd, void *buf, size_t count)
{
size_t read_size = 0;
ssize_t s;
do {
/* This expects that partial read is aligned in buffer */
s = read(fd, buf, count - read_size);
if (s == -1 && errno != EINTR)
return s;
if (s == 0)
return (ssize_t)read_size;
if (s > 0) {
if (s != (ssize_t)count)
log_dbg("Partial read %zd / %zu.", s, count);
read_size += (size_t)s;
buf = (uint8_t*)buf + s;
}
} while (read_size != count);
return (ssize_t)count;
}
static int copy_data_forward(struct reenc_ctx *rc, int fd_old, int fd_new,
size_t block_size, void *buf, uint64_t *bytes)
{
@@ -652,11 +715,11 @@ static int copy_data_forward(struct reenc_ctx *rc, int fd_old, int fd_new,
return -EIO;
while (!quit && rc->device_offset < rc->device_size) {
s1 = read(fd_old, buf, block_size);
s1 = read_buf(fd_old, buf, block_size);
if (s1 < 0 || ((size_t)s1 != block_size &&
(rc->device_offset + s1) != rc->device_size)) {
log_dbg("Read error, expecting %d, got %d.",
(int)block_size, (int)s1);
log_dbg("Read error, expecting %zu, got %zd.",
block_size, s1);
return -EIO;
}
@@ -666,8 +729,8 @@ static int copy_data_forward(struct reenc_ctx *rc, int fd_old, int fd_new,
s2 = write(fd_new, buf, s1);
if (s2 < 0) {
log_dbg("Write error, expecting %d, got %d.",
(int)block_size, (int)s2);
log_dbg("Write error, expecting %zu, got %zd.",
block_size, s2);
return -EIO;
}
@@ -722,17 +785,17 @@ static int copy_data_backward(struct reenc_ctx *rc, int fd_old, int fd_new,
return -EIO;
}
s1 = read(fd_old, buf, working_block);
s1 = read_buf(fd_old, buf, working_block);
if (s1 < 0 || (s1 != working_block)) {
log_dbg("Read error, expecting %d, got %d.",
(int)block_size, (int)s1);
log_dbg("Read error, expecting %zu, got %zd.",
block_size, s1);
return -EIO;
}
s2 = write(fd_new, buf, working_block);
if (s2 < 0) {
log_dbg("Write error, expecting %d, got %d.",
(int)block_size, (int)s2);
log_dbg("Write error, expecting %zu, got %zd.",
block_size, s2);
return -EIO;
}
@@ -752,6 +815,41 @@ static int copy_data_backward(struct reenc_ctx *rc, int fd_old, int fd_new,
return quit ? -EAGAIN : 0;
}
static void zero_rest_of_device(int fd, size_t block_size, void *buf,
uint64_t *bytes, uint64_t offset)
{
ssize_t s1, s2;
log_dbg("Zeroing rest of device.");
if (lseek64(fd, offset, SEEK_SET) < 0) {
log_dbg(_("Cannot seek to device offset.\n"));
return;
}
memset(buf, 0, block_size);
s1 = block_size;
while (!quit && *bytes) {
if (*bytes < s1)
s1 = *bytes;
s2 = write(fd, buf, s1);
if (s2 < 0) {
log_dbg("Write error, expecting %zu, got %zd.",
block_size, s2);
return;
}
if (opt_fsync && fsync(fd) < 0) {
log_dbg("Write error, fsync.");
return;
}
*bytes -= s2;
}
}
static int copy_data(struct reenc_ctx *rc)
{
size_t block_size = opt_bsize * 1024 * 1024;
@@ -774,13 +872,22 @@ static int copy_data(struct reenc_ctx *rc)
goto out;
}
/* Check size */
if (ioctl(fd_new, BLKGETSIZE64, &rc->device_size_real) < 0) {
if (ioctl(fd_old, BLKGETSIZE64, &rc->device_size_org_real) < 0) {
log_err(_("Cannot get device size.\n"));
goto out;
}
rc->device_size = opt_device_size ?: rc->device_size_real;
if (ioctl(fd_new, BLKGETSIZE64, &rc->device_size_new_real) < 0) {
log_err(_("Cannot get device size.\n"));
goto out;
}
if (opt_device_size)
rc->device_size = opt_device_size;
else if (rc->reencrypt_mode == DECRYPT)
rc->device_size = rc->device_size_org_real;
else
rc->device_size = rc->device_size_new_real;
if (posix_memalign((void *)&buf, alignment(fd_new), block_size)) {
log_err(_("Allocation of aligned memory failed.\n"));
@@ -796,9 +903,18 @@ static int copy_data(struct reenc_ctx *rc)
else
r = copy_data_backward(rc, fd_old, fd_new, block_size, buf, &bytes);
set_int_block(1);
print_progress(rc, bytes, 1);
/* Zero (wipe) rest of now plain-only device when decrypting.
* (To not leave any sign of encryption here.) */
if (!r && rc->reencrypt_mode == DECRYPT &&
rc->device_size_new_real > rc->device_size_org_real) {
bytes = rc->device_size_new_real - rc->device_size_org_real;
zero_rest_of_device(fd_new, block_size, buf, &bytes, rc->device_size_org_real);
}
set_int_block(1);
if (r == -EAGAIN)
log_err(_("Interrupted by a signal.\n"));
else if (r < 0)
@@ -844,15 +960,14 @@ static int initialize_uuid(struct reenc_ctx *rc)
static int init_passphrase1(struct reenc_ctx *rc, struct crypt_device *cd,
const char *msg, int slot_to_check, int check)
{
int r = -EINVAL, slot, retry_count;
slot = (slot_to_check == CRYPT_ANY_SLOT) ? 0 : slot_to_check;
char *password;
int r = -EINVAL, retry_count;
size_t passwordLen;
retry_count = opt_tries ?: 1;
while (retry_count--) {
set_int_handler(0);
r = crypt_get_key(msg, &rc->p[slot].password,
&rc->p[slot].passwordLen,
r = crypt_get_key(msg, &password, &passwordLen,
0, 0, NULL /*opt_key_file*/,
0, 0, cd);
if (r < 0)
@@ -864,42 +979,49 @@ static int init_passphrase1(struct reenc_ctx *rc, struct crypt_device *cd,
set_int_block(1);
if (check)
r = crypt_activate_by_passphrase(cd, NULL, slot_to_check,
rc->p[slot].password, rc->p[slot].passwordLen, 0);
password, passwordLen, 0);
else
r = slot;
r = (slot_to_check == CRYPT_ANY_SLOT) ? 0 : slot_to_check;
if (r < 0) {
crypt_safe_free(rc->p[slot].password);
rc->p[slot].password = NULL;
rc->p[slot].passwordLen = 0;
crypt_safe_free(password);
password = NULL;
passwordLen = 0;
}
if (r < 0 && r != -EPERM)
return r;
if (r >= 0) {
rc->keyslot = slot;
rc->keyslot = r;
rc->p[r].password = password;
rc->p[r].passwordLen = passwordLen;
break;
}
log_err(_("No key available with this passphrase.\n"));
}
password = NULL;
passwordLen = 0;
return r;
}
static int init_keyfile(struct reenc_ctx *rc, struct crypt_device *cd, int slot_check)
{
int r, slot;
char *password;
int r;
size_t passwordLen;
slot = (slot_check == CRYPT_ANY_SLOT) ? 0 : slot_check;
r = crypt_get_key(NULL, &rc->p[slot].password, &rc->p[slot].passwordLen,
opt_keyfile_offset, opt_keyfile_size, opt_key_file, 0, 0, cd);
r = crypt_get_key(NULL, &password, &passwordLen, opt_keyfile_offset,
opt_keyfile_size, opt_key_file, 0, 0, cd);
if (r < 0)
return r;
r = crypt_activate_by_passphrase(cd, NULL, slot_check,
rc->p[slot].password, rc->p[slot].passwordLen, 0);
r = crypt_activate_by_passphrase(cd, NULL, slot_check, password,
passwordLen, 0);
/*
* Allow keyslot only if it is last slot or if user explicitly
* specify whch slot to use (IOW others will be disabled).
* specify which slot to use (IOW others will be disabled).
*/
if (r >= 0 && opt_key_slot == CRYPT_ANY_SLOT &&
crypt_keyslot_status(cd, r) != CRYPT_SLOT_ACTIVE_LAST) {
@@ -909,14 +1031,17 @@ static int init_keyfile(struct reenc_ctx *rc, struct crypt_device *cd, int slot_
}
if (r < 0) {
crypt_safe_free(rc->p[slot].password);
rc->p[slot].password = NULL;
rc->p[slot].passwordLen = 0;
crypt_safe_free(password);
if (r == -EPERM)
log_err(_("No key available with this passphrase.\n"));
return r;
} else
rc->keyslot = slot;
} else {
rc->keyslot = r;
rc->p[r].password = password;
rc->p[r].passwordLen = passwordLen;
}
password = NULL;
passwordLen = 0;
return r;
}
@@ -930,8 +1055,8 @@ static int initialize_passphrase(struct reenc_ctx *rc, const char *device)
log_dbg("Passhrases initialization.");
if (opt_new && !rc->in_progress) {
r = init_passphrase1(rc, cd, _("Enter new passphrase: "), 0, 0);
if (rc->reencrypt_mode == ENCRYPT && !rc->in_progress) {
r = init_passphrase1(rc, cd, _("Enter new passphrase: "), opt_key_slot, 0);
return r > 0 ? 0 : r;
}
@@ -942,11 +1067,18 @@ static int initialize_passphrase(struct reenc_ctx *rc, const char *device)
return r;
}
if (opt_key_slot != CRYPT_ANY_SLOT)
snprintf(msg, sizeof(msg),
_("Enter passphrase for key slot %u: "), opt_key_slot);
else
snprintf(msg, sizeof(msg), _("Enter any existing passphrase: "));
if (opt_key_file) {
r = init_keyfile(rc, cd, opt_key_slot);
} else if (rc->in_progress) {
r = init_passphrase1(rc, cd, _("Enter any existing passphrase: "),
CRYPT_ANY_SLOT, 1);
} else if (rc->in_progress ||
opt_key_slot != CRYPT_ANY_SLOT ||
rc->reencrypt_mode == DECRYPT) {
r = init_passphrase1(rc, cd, msg, opt_key_slot, 1);
} else for (i = 0; i < MAX_SLOT; i++) {
ki = crypt_keyslot_status(cd, i);
if (ki != CRYPT_SLOT_ACTIVE && ki != CRYPT_SLOT_ACTIVE_LAST)
@@ -1012,6 +1144,13 @@ static int initialize_context(struct reenc_ctx *rc, const char *device)
rc->reencrypt_direction = BACKWARD;
rc->device_offset = (uint64_t)~0;
}
if (opt_new)
rc->reencrypt_mode = ENCRYPT;
else if (opt_decrypt)
rc->reencrypt_mode = DECRYPT;
else
rc->reencrypt_mode = REENCRYPT;
}
return 0;
@@ -1045,7 +1184,7 @@ static void destroy_context(struct reenc_ctx *rc)
static int run_reencrypt(const char *device)
{
int r = -EINVAL;
struct reenc_ctx rc = {};
static struct reenc_ctx rc = {};
if (initialize_context(&rc, device))
goto out;
@@ -1053,26 +1192,41 @@ static int run_reencrypt(const char *device)
log_dbg("Running reencryption.");
if (!rc.in_progress) {
if (opt_new) {
if ((r = initialize_passphrase(&rc, rc.device)) ||
if ((r = initialize_passphrase(&rc, rc.device)))
goto out;
if (rc.reencrypt_mode == ENCRYPT) {
/* Create fake header for exising device */
if ((r = backup_fake_header(&rc)))
goto out;
} else {
if ((r = backup_luks_headers(&rc)))
goto out;
/* Create fake header for decrypted device */
if (rc.reencrypt_mode == DECRYPT &&
(r = backup_fake_header(&rc)))
goto out;
} else if ((r = initialize_passphrase(&rc, rc.device)) ||
(r = backup_luks_headers(&rc)) ||
(r = device_check(&rc, MAKE_UNUSABLE)))
goto out;
goto out;
if ((r = device_check(&rc, MAKE_UNUSABLE)))
goto out;
}
} else {
if ((r = initialize_passphrase(&rc, rc.header_file_new)))
goto out;
}
if ((r = activate_luks_headers(&rc)))
goto out;
if (!opt_keep_key) {
log_dbg("Running data area reencryption.");
if ((r = activate_luks_headers(&rc)))
goto out;
if ((r = copy_data(&rc)))
goto out;
if ((r = copy_data(&rc)))
goto out;
} else
log_dbg("Keeping existing key, skipping data area reencryption.");
r = restore_luks_header(&rc);
// FIXME: fix error path above to not skip this
if (rc.reencrypt_mode != DECRYPT)
r = restore_luks_header(&rc);
out:
destroy_context(&rc);
return r;
@@ -1109,13 +1263,14 @@ int main(int argc, const char **argv)
{ "cipher", 'c', POPT_ARG_STRING, &opt_cipher, 0, N_("The cipher used to encrypt the disk (see /proc/crypto)"), NULL },
{ "key-size", 's', POPT_ARG_INT, &opt_key_size, 0, N_("The size of the encryption key"), N_("BITS") },
{ "hash", 'h', POPT_ARG_STRING, &opt_hash, 0, N_("The hash used to create the encryption key from the passphrase"), NULL },
{ "keep-key", '\0', POPT_ARG_NONE, &opt_keep_key, 0, N_("Do not change key, no data area reencryption."), NULL },
{ "key-file", 'd', POPT_ARG_STRING, &opt_key_file, 0, N_("Read the key from a file."), NULL },
{ "iter-time", 'i', POPT_ARG_INT, &opt_iteration_time, 0, N_("PBKDF2 iteration time for LUKS (in ms)"), N_("msecs") },
{ "batch-mode", 'q', POPT_ARG_NONE, &opt_batch_mode, 0, N_("Do not ask for confirmation"), NULL },
{ "tries", 'T', POPT_ARG_INT, &opt_tries, 0, N_("How often the input of the passphrase can be retried"), NULL },
{ "use-random", '\0', POPT_ARG_NONE, &opt_random, 0, N_("Use /dev/random for generating volume key."), NULL },
{ "use-urandom", '\0', POPT_ARG_NONE, &opt_urandom, 0, N_("Use /dev/urandom for generating volume key."), NULL },
{ "use-directio", '\0', POPT_ARG_NONE, &opt_directio, 0, N_("Use direct-io when accesing devices."), NULL },
{ "use-directio", '\0', POPT_ARG_NONE, &opt_directio, 0, N_("Use direct-io when accessing devices."), NULL },
{ "use-fsync", '\0', POPT_ARG_NONE, &opt_fsync, 0, N_("Use fsync after each block."), NULL },
{ "write-log", '\0', POPT_ARG_NONE, &opt_write_log, 0, N_("Update log file after every block."), NULL },
{ "key-slot", 'S', POPT_ARG_INT, &opt_key_slot, 0, N_("Use only this slot (others will be disabled)."), NULL },
@@ -1123,7 +1278,8 @@ int main(int argc, const char **argv)
{ "keyfile-size", 'l', POPT_ARG_LONG, &opt_keyfile_size, 0, N_("Limits the read from keyfile"), N_("bytes") },
{ "reduce-device-size",'\0', POPT_ARG_STRING, &opt_reduce_size_str, 0, N_("Reduce data device size (move data offset). DANGEROUS!"), N_("bytes") },
{ "device-size", '\0', POPT_ARG_STRING, &opt_device_size_str, 0, N_("Use only specified device size (ignore rest of device). DANGEROUS!"), N_("bytes") },
{ "new", 'N', POPT_ARG_NONE,&opt_new, 0, N_("Create new header on not encrypted device."), NULL },
{ "new", 'N', POPT_ARG_NONE, &opt_new, 0, N_("Create new header on not encrypted device."), NULL },
{ "decrypt", '\0', POPT_ARG_NONE, &opt_decrypt, 0, N_("Permanently decrypt device (remove encryption)."), NULL },
POPT_TABLEEND
};
poptContext popt_context;
@@ -1214,6 +1370,18 @@ int main(int argc, const char **argv)
usage(popt_context, EXIT_FAILURE, _("Option --new must be used together with --reduce-device-size."),
poptGetInvocationName(popt_context));
if (opt_keep_key && ((!opt_hash && !opt_iteration_time) || opt_cipher || opt_new))
usage(popt_context, EXIT_FAILURE, _("Option --keep-key can be used only with --hash or --iter-time."),
poptGetInvocationName(popt_context));
if (opt_new && opt_decrypt)
usage(popt_context, EXIT_FAILURE, _("Option --new cannot be used together with --decrypt."),
poptGetInvocationName(popt_context));
if (opt_decrypt && (opt_cipher || opt_hash || opt_reduce_size || opt_keep_key || opt_device_size))
usage(popt_context, EXIT_FAILURE, _("Option --decrypt is incompatible with specified parameters."),
poptGetInvocationName(popt_context));
if (opt_debug) {
opt_verbose = 1;
crypt_set_debug_level(-1);

View File

@@ -2,7 +2,7 @@
* Password quality check wrapper
*
* Copyright (C) 2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2012, Milan Broz
* Copyright (C) 2012-2014, 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,10 +1,10 @@
/*
* cryptsetup - setup cryptographic volumes for dm-crypt
*
* Copyright (C) 2004, Christophe Saout <christophe@saout.de>
* Copyright (C) 2004, Jana Saout <jana@saout.de>
* Copyright (C) 2004-2007, Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2012, Milan Broz
* Copyright (C) 2009-2014, Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -143,6 +143,7 @@ int yesDialog(const char *msg, void *usrptr __attribute__((unused)))
if(isatty(STDIN_FILENO) && !opt_batch_mode) {
log_std("\nWARNING!\n========\n");
log_std("%s\n\nAre you sure? (Type uppercase yes): ", msg);
fflush(stdout);
if(getline(&answer, &size, stdin) == -1) {
r = 0;
/* Aborted by signal */
@@ -163,7 +164,7 @@ int yesDialog(const char *msg, void *usrptr __attribute__((unused)))
void show_status(int errcode)
{
char error[256], *error_;
char error[256];
if(!opt_verbose)
return;
@@ -175,12 +176,16 @@ void show_status(int errcode)
crypt_get_error(error, sizeof(error));
if (!error[0]) {
error_ = strerror_r(-errcode, error, sizeof(error));
if (error_ != error) {
if (*error) {
#ifdef STRERROR_R_CHAR_P /* GNU-specific strerror_r */
char *error_ = strerror_r(-errcode, error, sizeof(error));
if (error_ != error)
strncpy(error, error_, sizeof(error));
error[sizeof(error) - 1] = '\0';
}
#else /* POSIX strerror_r variant */
if (strerror_r(-errcode, error, sizeof(error)))
*error = '\0';
#endif
error[sizeof(error) - 1] = '\0';
}
log_err(_("Command failed with code %i"), -errcode);

View File

@@ -1,7 +1,8 @@
/*
* veritysetup - setup cryptographic volumes for dm-verity
*
* Copyright (C) 2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2013, Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2013, 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

@@ -5,7 +5,9 @@ TESTS = api-test \
discards-test \
mode-test \
password-hash-test \
tcrypt-compat-test
tcrypt-compat-test \
luks1-compat-test \
device-test
if VERITYSETUP
TESTS += verity-compat-test
@@ -16,29 +18,34 @@ TESTS += reencryption-compat-test
endif
EXTRA_DIST = compatimage.img.bz2 compatv10image.img.bz2 \
img_fs_ext4.img.bz2 img_fs_vfat.img.bz2 img_fs_xfs.img.bz2 \
valid_header_file.bz2 \
evil_hdr-payload_overwrite.bz2 \
evil_hdr-stripes_payload_dmg.bz2 \
evil_hdr-luks_hdr_damage.bz2 \
evil_hdr-small_luks_device.bz2 \
tcrypt-images.tar.bz2 \
luks1-images.tar.bz2 \
compat-test loopaes-test align-test discards-test mode-test password-hash-test \
verity-compat-test \
reencryption-compat-test \
tcrypt-compat-test \
luks1-compat-test \
device-test \
cryptsetup-valg-supps valg.sh valg-api.sh
CLEANFILES = cryptsetup-tst* valglog*
clean-local:
-rm -rf tcrypt-images
-rm -rf tcrypt-images luks1-images
differ_SOURCES = differ.c
differ_CFLAGS = -Wall -O2
differ_CFLAGS = $(AM_CFLAGS) -Wall -O2
api_test_SOURCES = api-test.c $(top_srcdir)/lib/utils_loop.c
api_test_LDADD = ../lib/libcryptsetup.la
api_test_LDFLAGS = -static
api_test_CFLAGS = -g -Wall -O0 -I$(top_srcdir)/lib/ -I$(top_srcdir)/lib/luks1
api_test_LDFLAGS = $(AM_LDFLAGS) -static
api_test_CFLAGS = -g -Wall -O0 $(AM_CFLAGS) -I$(top_srcdir)/lib/ -I$(top_srcdir)/lib/luks1
api_test_CPPFLAGS = $(AM_CPPFLAGS) -include config.h
check_PROGRAMS = api-test differ

View File

@@ -3,11 +3,16 @@
CRYPTSETUP="../src/cryptsetup"
DEV=""
DEV_STACKED="luks0xbabe"
MNT_DIR="./mnt_luks"
PWD1="93R4P4pIqAH8"
PWD2="mymJeD8ivEhE"
cleanup() {
udevadm settle >/dev/null 2>&1
if [ -d "$MNT_DIR" ] ; then
umount -f $MNT_DIR 2>/dev/null
rmdir $MNT_DIR 2>/dev/null
fi
[ -b /dev/mapper/$DEV_STACKED ] && dmsetup remove $DEV_STACKED >/dev/null 2>&1
rmmod scsi_debug 2>/dev/null
sleep 2
@@ -15,12 +20,18 @@ cleanup() {
fail()
{
echo "FAIL"
[ -n "$1" ] && echo "$1"
if [ -n "$1" ] ; then echo "FAIL $1" ; else echo "FAIL" ; fi
cleanup
exit 100
}
skip()
{
echo "TEST SKIPPED: $1"
cleanup
exit 0
}
add_device() {
modprobe scsi_debug $@
if [ $? -ne 0 ] ; then
@@ -29,7 +40,7 @@ add_device() {
fi
sleep 2
DEV=$(grep scsi_debug /sys/block/*/device/model | cut -f4 -d /)
DEV=$(grep -l -e scsi_debug /sys/block/*/device/model | cut -f4 -d /)
if [ ! -e /sys/block/$DEV/alignment_offset ] ; then
echo "This kernel seems to not support topology info, test skipped."
@@ -198,3 +209,18 @@ format_null 512 4040 8
format_null 512 4096 128
format_null 512 4096 2048
cleanup
echo "# Create enterprise-class 4K drive with fs and LUKS images."
# loop device here presents 512 block but images have 4k block
# cryptsetup should properly use 4k block on direct-io
add_device dev_size_mb=16 sector_size=4096 physblk_exp=0 num_tgts=1
for file in $(ls img_fs_*.img.bz2) ; do
echo "Format using fs image $file."
bzip2 -d -c $file | dd of=$DEV bs=1M 2>/dev/null || fail "bad image"
[ ! -d $MNT_DIR ] && mkdir $MNT_DIR
mount $DEV $MNT_DIR || skip "Mounting image is not available."
echo $PWD1 | $CRYPTSETUP luksFormat -i 1 $MNT_DIR/luks.img || fail
echo $PWD2 | $CRYPTSETUP luksFormat -i 1 $MNT_DIR/luks.img --header $MNT_DIR/luks_header.img || fail
umount $MNT_DIR
done
cleanup

View File

@@ -1,8 +1,8 @@
/*
* cryptsetup library API check functions
*
* Copyright (C) 2009-2012 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2013, Milan Broz
* Copyright (C) 2009-2013 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2014, Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -94,6 +94,7 @@ static int global_lines = 0;
static char *DEVICE_1 = NULL;
static char *DEVICE_2 = NULL;
static char *DEVICE_3 = NULL;
static char *THE_LOOP_DEV = NULL;
static char *tmp_file_1 = NULL;
@@ -123,6 +124,9 @@ static int fips_mode(void)
int fd;
char buf = 0;
if (access("/etc/system-fips", F_OK))
return 0;
fd = open("/proc/sys/crypto/fips_enabled", O_RDONLY);
if (fd < 0)
@@ -246,7 +250,7 @@ static int _prepare_keyfile(const char *name, const char *passphrase, int size)
{
int fd, r;
fd = open(name, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR);
fd = open(name, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR|S_IWUSR);
if (fd != -1) {
r = write(fd, passphrase, size);
close(fd);
@@ -371,6 +375,9 @@ static void _cleanup(void)
if (crypt_loop_device(DEVICE_2))
crypt_loop_detach(DEVICE_2);
if (crypt_loop_device(DEVICE_3))
crypt_loop_detach(DEVICE_3);
_system("rm -f " IMAGE_EMPTY, 0);
_system("rm -f " IMAGE1, 0);
@@ -391,6 +398,7 @@ static void _cleanup(void)
free(THE_LOOP_DEV);
free(DEVICE_1);
free(DEVICE_2);
free(DEVICE_3);
}
static int _setup(void)
@@ -455,6 +463,12 @@ static int _setup(void)
fd = crypt_loop_attach(DEVICE_2, IMAGE_EMPTY, 0, 0, &ro);
close(fd);
}
if (!DEVICE_3)
DEVICE_3 = crypt_loop_get_device();
if (!DEVICE_3) {
printf("Cannot find free loop device.\n");
return 1;
}
/* Keymaterial offset is less than 8 sectors */
_system(" [ ! -e " EVL_HEADER_1 " ] && bzip2 -dk " EVL_HEADER_1 ".bz2", 1);
/* keymaterial offset aims into payload area */
@@ -538,8 +552,8 @@ static void xlog(const char *msg, const char *tst, const char *func, int line, c
#define FAIL_(x, y) do { xlog("(fail) ", #x, __FUNCTION__, __LINE__, y); \
check_ko((x), __LINE__, __FUNCTION__); \
} while(0)
#define EQ_(x, y) do { xlog("(equal) ", #x " == " #y, __FUNCTION__, __LINE__, NULL); \
int64_t _x = (x), _y = (y); \
#define EQ_(x, y) do { int64_t _x = (x), _y = (y); \
xlog("(equal) ", #x " == " #y, __FUNCTION__, __LINE__, NULL); \
if (_x != _y) check_equal(__LINE__, __FUNCTION__, _x, _y); \
} while(0)
#define RUN_(x, y) do { printf("%s: %s\n", #x, (y)); x(); } while (0)
@@ -961,8 +975,11 @@ static void SuspendDevice(void)
suspend_status = crypt_suspend(cd, CDEVICE_1);
if (suspend_status == -ENOTSUP) {
printf("WARNING: Suspend/Resume not supported, skipping test.\n");
goto out;
OK_(crypt_deactivate(cd, CDEVICE_1));
crypt_free(cd);
return;
}
OK_(suspend_status);
FAIL_(crypt_suspend(cd, CDEVICE_1), "already suspended");
@@ -976,10 +993,30 @@ static void SuspendDevice(void)
FAIL_(crypt_resume_by_keyfile_offset(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, 1, 0), "wrong key");
OK_(crypt_resume_by_keyfile_offset(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, 0, 0));
FAIL_(crypt_resume_by_keyfile(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, 0), "not suspended");
_remove_keyfiles();
out:
OK_(crypt_deactivate(cd, CDEVICE_1));
crypt_free(cd);
/* create LUKS device with detached header */
OK_(crypt_init(&cd, DEVICE_1));
OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
OK_(crypt_set_data_device(cd, DEVICE_2));
OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEY1, strlen(KEY1), 0));
crypt_free(cd);
/* Should be able to suspend but not resume if not header specified */
OK_(crypt_init_by_name(&cd, CDEVICE_1));
OK_(crypt_suspend(cd, CDEVICE_1));
FAIL_(crypt_suspend(cd, CDEVICE_1), "already suspended");
FAIL_(crypt_resume_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEY1, strlen(KEY1)-1), "no header");
crypt_free(cd);
OK_(crypt_init_by_name_and_header(&cd, CDEVICE_1, DEVICE_1));
OK_(crypt_resume_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEY1, strlen(KEY1)));
OK_(crypt_deactivate(cd, CDEVICE_1));
crypt_free(cd);
_remove_keyfiles();
}
static void AddDeviceLuks(void)
@@ -1081,6 +1118,14 @@ static void AddDeviceLuks(void)
OK_(crypt_init_by_name_and_header(&cd, CDEVICE_1, DMDIR H_DEVICE));
FAIL_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, &params), "Context is already formated");
EQ_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
crypt_free(cd);
// check active status without header
OK_(crypt_init_by_name_and_header(&cd, CDEVICE_1, NULL));
EQ_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
OK_(!!crypt_get_type(cd));
OK_(strcmp(cipher, crypt_get_cipher(cd)));
OK_(strcmp(cipher_mode, crypt_get_cipher_mode(cd)));
EQ_((int)key_size, crypt_get_volume_key_size(cd));
OK_(crypt_deactivate(cd, CDEVICE_1));
crypt_free(cd);
@@ -1310,8 +1355,8 @@ static void LuksHeaderRestore(void)
// volume key_size mismatch
OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
memcpy(key2, key, key_size - 1);
OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key2, key_size - 1, &params));
memcpy(key2, key, key_size / 2);
OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key2, key_size / 2, &params));
FAIL_(crypt_header_restore(cd, CRYPT_LUKS1, VALID_HEADER), "Volume keysize mismatch");
crypt_free(cd);
@@ -1425,6 +1470,7 @@ static void LuksHeaderBackup(void)
.data_alignment = 2048,
};
char key[128];
int fd, ro = O_RDONLY;
const char *mk_hex = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a";
size_t key_size = strlen(mk_hex) / 2;
@@ -1432,6 +1478,8 @@ static void LuksHeaderBackup(void)
const char *cipher_mode = "cbc-essiv:sha256";
uint64_t r_payload_offset;
const char *passphrase = PASSPHRASE;
crypt_decode_key(key, mk_hex, key_size);
OK_(get_luks_offsets(0, key_size, params.data_alignment, 0, NULL, &r_payload_offset));
@@ -1441,6 +1489,8 @@ static void LuksHeaderBackup(void)
OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, &params));
OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0));
EQ_(crypt_keyslot_add_by_volume_key(cd, 7, key, key_size, passphrase, strlen(passphrase)), 7);
EQ_(crypt_keyslot_add_by_volume_key(cd, 0, key, key_size, passphrase, strlen(passphrase)), 0);
OK_(crypt_header_backup(cd, CRYPT_LUKS1, BACKUP_FILE));
OK_(crypt_deactivate(cd, CDEVICE_1));
crypt_free(cd);
@@ -1454,6 +1504,43 @@ static void LuksHeaderBackup(void)
OK_(crypt_deactivate(cd, CDEVICE_1));
crypt_free(cd);
// exercise luksOpen using backup header in file
OK_(crypt_init(&cd, BACKUP_FILE));
OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
OK_(crypt_set_data_device(cd, DMDIR L_DEVICE_OK));
EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, passphrase, strlen(passphrase), 0), 0);
EQ_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
OK_(crypt_deactivate(cd, CDEVICE_1));
crypt_free(cd);
OK_(crypt_init(&cd, BACKUP_FILE));
OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
OK_(crypt_set_data_device(cd, DMDIR L_DEVICE_OK));
EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, 7, passphrase, strlen(passphrase), 0), 7);
EQ_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
OK_(crypt_deactivate(cd, CDEVICE_1));
crypt_free(cd);
// exercise luksOpen using backup header on block device
fd = crypt_loop_attach(DEVICE_3, BACKUP_FILE, 0, 0, &ro);
close(fd);
OK_(fd < 0);
OK_(crypt_init(&cd, DEVICE_3));
OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
OK_(crypt_set_data_device(cd, DMDIR L_DEVICE_OK));
EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, passphrase, strlen(passphrase), 0), 0);
EQ_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
OK_(crypt_deactivate(cd, CDEVICE_1));
crypt_free(cd);
OK_(crypt_init(&cd, DEVICE_3));
OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
OK_(crypt_set_data_device(cd, DMDIR L_DEVICE_OK));
EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, 7, passphrase, strlen(passphrase), 0), 7);
EQ_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
OK_(crypt_deactivate(cd, CDEVICE_1));
crypt_free(cd);
_cleanup_dmdevices();
}
@@ -1842,7 +1929,7 @@ static void NonFIPSAlg(void)
struct crypt_device *cd;
struct crypt_params_luks1 params = {0};
char key[128] = "";
size_t key_size = 128;
size_t key_size = 128 / 8;
const char *cipher = "aes";
const char *cipher_mode = "cbc-essiv:sha256";
int ret;

View File

@@ -39,7 +39,7 @@ KEY_MATERIAL5_EXT="S331776-395264"
TEST_UUID="12345678-1234-1234-1234-123456789abc"
LOOPDEV=$(losetup -f 2>/dev/null)
FIPS_MODE=$(cat /proc/sys/crypto/fips_enabled 2>/dev/null)
[ -f /etc/system-fips ] && FIPS_MODE=$(cat /proc/sys/crypto/fips_enabled 2>/dev/null)
function remove_mapping()
{
@@ -314,6 +314,9 @@ $CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 3: ENABLED" || fail
echo $PWD2 | $CRYPTSETUP luksAddKey $LOOPDEV --master-key-file /dev/zero --key-slot 4 || fail
$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 4: ENABLED" || fail
echo $PWD3 | $CRYPTSETUP luksAddKey $LOOPDEV --master-key-file /dev/null --key-slot 5 2>/dev/null && fail
$CRYPTSETUP luksAddKey $LOOPDEV --master-key-file /dev/zero --key-slot 5 $KEY1 || fail
$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 5: ENABLED" || fail
# [0]PWD1 [1]PWD2 [2]$KEY1/1 [3]$KEY1 [4]$KEY2
$CRYPTSETUP -q luksFormat $LOOPDEV $KEY1 --key-slot 3 || fail
$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 3: ENABLED" || fail
@@ -527,13 +530,21 @@ $CRYPTSETUP luksOpen -S 5 -d $KEY1 $LOOPDEV $DEV_NAME && fail
prepare "[28] Detached LUKS header" wipe
dd if=/dev/zero of=$HEADER_IMG bs=1M count=4 >/dev/null 2>&1
echo $PWD1 | $CRYPTSETUP luksFormat -i1 $LOOPDEV --header $HEADER_IMG || fail
echo $PWD1 | $CRYPTSETUP luksFormat -i1 $LOOPDEV --header $HEADER_IMG --align-payload 1 >/dev/null 2>&1 && fail
echo $PWD1 | $CRYPTSETUP luksFormat -i1 $LOOPDEV --header $HEADER_IMG --align-payload 8192 || fail
echo $PWD1 | $CRYPTSETUP luksFormat -i1 $LOOPDEV --header $HEADER_IMG --align-payload 0 || fail
echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV --header $HEADER_IMG $DEV_NAME || fail
$CRYPTSETUP -q resize $DEV_NAME --size 100 --header $HEADER_IMG || fail
$CRYPTSETUP -q status $DEV_NAME --header $HEADER_IMG | grep "size:" | grep -q "100 sectors" || fail
$CRYPTSETUP -q status $DEV_NAME | grep "type:" | grep -q "n/a" || fail
$CRYPTSETUP -q status $DEV_NAME | grep "size:" | grep -q "100 sectors" || fail
$CRYPTSETUP luksSuspend $DEV_NAME --header $HEADER_IMG || fail
echo $PWD1 | $CRYPTSETUP luksResume $DEV_NAME --header $HEADER_IMG || fail
$CRYPTSETUP luksClose $DEV_NAME || fail
echo $PWD1 | $CRYPTSETUP luksAddKey -S 5 _fakedev_ --header $HEADER_IMG $KEY5 || fail
$CRYPTSETUP luksDump _fakedev_ --header $HEADER_IMG | grep -q "Key Slot 5: ENABLED" || fail
$CRYPTSETUP luksKillSlot -q _fakedev_ --header $HEADER_IMG 5 || fail
$CRYPTSETUP luksDump _fakedev_ --header $HEADER_IMG | grep -q "Key Slot 5: DISABLED" || fail
prepare "[29] Repair metadata" wipe
$CRYPTSETUP -q luksFormat -i1 $LOOPDEV $KEY1 --key-slot 0 || fail
@@ -544,5 +555,14 @@ $CRYPTSETUP -q repair $LOOPDEV >/dev/null 2>&1 || fail
$CRYPTSETUP luksOpen -d $KEY1 $LOOPDEV $DEV_NAME || fail
$CRYPTSETUP luksClose $DEV_NAME || fail
prepare "[30] LUKS erase" wipe
$CRYPTSETUP -q luksFormat -i1 $LOOPDEV $KEY5 --key-slot 5 || fail
$CRYPTSETUP luksAddKey -S 1 -d $KEY5 $LOOPDEV $KEY1 || fail
$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 1: ENABLED" || fail
$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 5: ENABLED" || fail
$CRYPTSETUP luksErase -q $LOOPDEV || fail
$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 1: DISABLED" || fail
$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 5: DISABLED" || fail
remove_mapping
exit 0

86
tests/device-test Executable file
View File

@@ -0,0 +1,86 @@
#!/bin/bash
CRYPTSETUP="../src/cryptsetup"
MNT_DIR="./mnt_luks"
DEV_NAME="dummy"
PWD1="93R4P4pIqAH8"
PWD2="mymJeD8ivEhE"
cleanup() {
[ -b /dev/mapper/$DEV_NAME ] && dmsetup remove $DEV_NAME
udevadm settle >/dev/null 2>&1
if [ -d "$MNT_DIR" ] ; then
umount -f $MNT_DIR 2>/dev/null
rmdir $MNT_DIR 2>/dev/null
fi
sleep 2
}
fail()
{
if [ -n "$1" ] ; then echo "FAIL $1" ; else echo "FAIL" ; fi
cleanup
exit 100
}
skip()
{
echo "TEST SKIPPED: $1"
cleanup
exit 0
}
format() # key_bits expected [forced]
{
dd if=/dev/zero of=$DEV bs=1M count=5 >/dev/null 2>&1
echo $PWD1 | $CRYPTSETUP luksFormat $DEV -q -i1 -c aes-cbc-essiv:sha256
[ $? -ne 0 ] && fail "Format failed."
# test some operation, just in case
echo -e "$PWD1\n$PWD2" | $CRYPTSETUP luksAddKey $DEV -i1 --key-slot 1
[ $? -ne 0 ] && fail "Keyslot add failed."
$CRYPTSETUP -q luksKillSlot $DEV 1
[ $? -ne 0 ] && fail "Keyslot removal failed."
}
if [ $(id -u) != 0 ]; then
echo "WARNING: You must be root to run this test, test skipped."
exit 0
fi
[ ! -d $MNT_DIR ] && mkdir $MNT_DIR
echo "[1] Using tmpfs for image"
DEV="$MNT_DIR/test.img"
mount -t tmpfs none $MNT_DIR || skip "Mounting tmpfs not available."
format
echo "[2] Kernel dmcrypt performace options"
echo -e "$PWD1" | $CRYPTSETUP open --type plain $DEV $DEV_NAME --perf-same_cpu_crypt >/dev/null 2>&1
if [ $? -ne 0 ] ; then
echo "TEST SKIPPED: dmcrypt options not available"
else
$CRYPTSETUP close $DEV_NAME || fail
# plain
echo -e "$PWD1" | $CRYPTSETUP open --type plain $DEV $DEV_NAME --perf-same_cpu_crypt --perf-submit_from_crypt_cpus || fail
$CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt || fail
$CRYPTSETUP status $DEV_NAME | grep -q submit_from_crypt_cpus || fail
$CRYPTSETUP close $DEV_NAME || fail
echo -e "$PWD1" | $CRYPTSETUP open --type plain $DEV $DEV_NAME --perf-same_cpu_crypt --allow-discards || fail
$CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt || fail
$CRYPTSETUP status $DEV_NAME | grep -q discards || fail
$CRYPTSETUP close $DEV_NAME || fail
# LUKS
echo -e "$PWD1" | $CRYPTSETUP open --type luks1 $DEV $DEV_NAME --perf-same_cpu_crypt --perf-submit_from_crypt_cpus || fail
$CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt || fail
$CRYPTSETUP status $DEV_NAME | grep -q submit_from_crypt_cpus || fail
$CRYPTSETUP close $DEV_NAME || fail
echo -e "$PWD1" | $CRYPTSETUP open --type luks1 $DEV $DEV_NAME --perf-same_cpu_crypt --allow-discards || fail
$CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt || fail
$CRYPTSETUP status $DEV_NAME | grep -q discards || fail
$CRYPTSETUP close $DEV_NAME || fail
fi
cleanup

View File

@@ -27,7 +27,7 @@ add_device() {
fi
sleep 2
DEV=$(grep scsi_debug /sys/block/*/device/model | cut -f4 -d /)
DEV=$(grep -l -e scsi_debug /sys/block/*/device/model | cut -f4 -d /)
DEV="/dev/$DEV"
[ -b $DEV ] || fail "Cannot find $DEV."

BIN
tests/img_fs_ext4.img.bz2 Normal file

Binary file not shown.

BIN
tests/img_fs_vfat.img.bz2 Normal file

Binary file not shown.

BIN
tests/img_fs_xfs.img.bz2 Normal file

Binary file not shown.

80
tests/luks1-compat-test Executable file
View File

@@ -0,0 +1,80 @@
#!/bin/bash
# check luks1 images parsing
# NOTE: if image with whirlpool hash fails, check
# that you are not using old gcrypt with flawed whirlpool
# (see cryptsetup debug output)
CRYPTSETUP=../src/cryptsetup
TST_DIR=luks1-images
MAP=luks1tst
KEYFILE=keyfile1
function remove_mapping()
{
[ -b /dev/mapper/$MAP ] && dmsetup remove $MAP
}
function fail()
{
[ -n "$1" ] && echo "$1"
echo " [FAILED]"
remove_mapping
exit 2
}
function skip()
{
[ -n "$1" ] && echo "$1"
echo "Test skipped."
exit 0
}
function test_one()
{
$CRYPTSETUP benchmark -c "$1" -s "$2" | grep -v "#" || skip
}
function test_required()
{
which lsblk >/dev/null 2>&1 || skip "WARNING: lsblk tool required."
echo "REQUIRED KDF TEST"
$CRYPTSETUP benchmark -h whirlpool | grep "N/A" && skip
echo "REQUIRED CIPHERS TEST"
echo "# Algorithm | Key | Encryption | Decryption"
test_one aes-xts 256
test_one twofish-xts 256
test_one serpent-xts 256
test_one aes-cbc 256
test_one aes-lrw 256
}
export LANG=C
if [ $(id -u) != 0 ]; then
echo "WARNING: You must be root to run activation part of test, test skipped."
exit 0
fi
test_required
[ ! -d $TST_DIR ] && tar xjf luks1-images.tar.bz2
echo "ACTIVATION FS UUID CHECK"
for file in $(ls $TST_DIR/luks1_*) ; do
echo -n " $file"
$CRYPTSETUP luksOpen -d $TST_DIR/$KEYFILE $file $MAP 2>/dev/null
ret=$?
# ignore missing whirlpool (pwd failed is exit code 2)
[ $ret -eq 1 ] && (echo $file | grep -q -e "whirlpool") && echo " [N/A]" && continue
[ $ret -ne 0 ] && fail
$CRYPTSETUP status $MAP >/dev/null || fail
$CRYPTSETUP status /dev/mapper/$MAP >/dev/null || fail
UUID=$(lsblk -n -o UUID /dev/mapper/$MAP)
$CRYPTSETUP remove $MAP || fail
[ "$UUID" != "DEAD-BABE" ] && fail "UUID check failed."
echo " [OK]"
done

BIN
tests/luks1-images.tar.bz2 Normal file

Binary file not shown.

View File

@@ -52,7 +52,7 @@ add_device() {
dmcrypt_check() # device outstring
{
X=$(dmsetup table $1 2>/dev/null | sed 's/.*: //' | cut -d' ' -f 4)
if [ $X = $2 ] ; then
if [ "$X" = $2 ] ; then
echo -n "[table OK]"
else
echo "[table FAIL]"
@@ -65,7 +65,7 @@ dmcrypt_check() # device outstring
echo -n "[status OK]"
else
echo "[status FAIL]"
echo " Expecting $2 got $X."
echo " Expecting $2 got \"$X\"."
fail
fi

View File

@@ -20,13 +20,20 @@ cleanup() {
exit $1
}
crypt_key() # hash keysize pwd/file name outkey [limit]
function fail()
{
echo " $1 [FAILED]"
cleanup 2
}
crypt_key() # hash keysize pwd/file name outkey [limit] [offset]
{
DEV2=$DEV_NAME"_x"
LIMIT=""
MODE=aes-cbc-essiv:sha256
[ $2 -gt 256 ] && MODE=aes-xts-plain
[ -n "$6" ] && LIMIT="-l $6"
[ -n "$7" ] && LIMIT="$LIMIT --keyfile-offset $7"
echo -n "HASH: $1 KSIZE: $2 / $3"
case "$3" in
@@ -46,12 +53,21 @@ crypt_key() # hash keysize pwd/file name outkey [limit]
cat $4 | $CRYPTSETUP create -c $MODE -h $1 -s $2 $LIMIT $DEV2 /dev/mapper/$DEV_NAME 2>/dev/null
ret=$?
;;
file)
$CRYPTSETUP create -c $MODE -d $4 -h $1 -s $2 $DEV2 /dev/mapper/$DEV_NAME 2>/dev/null
cat-)
cat $4 | $CRYPTSETUP create -c $MODE -h $1 -s $2 $LIMIT $DEV2 -d - /dev/mapper/$DEV_NAME 2>/dev/null
ret=$?
;;
file)
$CRYPTSETUP create -q -c $MODE -d $4 -h $1 -s $2 $DEV2 /dev/mapper/$DEV_NAME 2>/dev/null
ret=$?
;;
failpwd)
echo -e -n "$4" | $CRYPTSETUP create -c $MODE -h $1 -s $2 $LIMIT $DEV2 /dev/mapper/$DEV_NAME 2>/dev/null && fail "Expecting failure"
echo " [OK]"
return
;;
*)
fail
fail ""
;;
esac
@@ -107,11 +123,15 @@ crypt_key unknown* 256 file /dev/zero 00000000000000000000000000000000000000000
crypt_key sha256:20 256 pwd "xxx" cd2eb0837c9b4c962c22d2ff8b5441b7b4580588000000000000000000000000
crypt_key sha256:32 256 pwd "xxx" cd2eb0837c9b4c962c22d2ff8b5441b7b45805887f051d39bf133b583baf6860
crypt_key sha256: 256 failpwd "xxx" x
crypt_key sha256:xx 256 failpwd "xxx" x
# key file, 80 chars
echo -n -e "0123456789abcdef\n\x01\x00\x03\xff\xff\r\xff\xff\n\r" \
"2352j3rkjhadcfasc823rqaw7e1 3dq sdq3d 2dkjqw3h2=====" >$KEY_FILE
KEY_FILE_HEX="303132333435363738396162636465660a010003ffff0dffff0a0d20323335326a33726b6a686164636661736338323372716177376531203364712073647133"
# ignore hash if keyfile is specified
crypt_key ripemd160 256 file $KEY_FILE ${KEY_FILE_HEX:0:64}
crypt_key sha256 256 file $KEY_FILE ${KEY_FILE_HEX:0:64}
crypt_key sha256 128 file $KEY_FILE ${KEY_FILE_HEX:0:32}
@@ -120,7 +140,27 @@ crypt_key sha256 512 file $KEY_FILE $KEY_FILE_HEX
# stdin can be limited
crypt_key plain 128 cat /dev/zero 00000000000000000000000000000000 16
crypt_key plain 128 cat /dev/zero 00000000000000000000000000000000 17
# read key only up to \n
crypt_key plain 128 cat $KEY_FILE ${KEY_FILE_HEX:0:28}0000 14
# read full key, ignore keyfile length
crypt_key plain 128 cat- $KEY_FILE ${KEY_FILE_HEX:0:32}
crypt_key plain 128 cat- $KEY_FILE ${KEY_FILE_HEX:0:32} 14
# but do not ignore hash if keysgfile is "-"
crypt_key sha256 128 cat- $KEY_FILE f3b827c8a6f159ad8c8ed5bd5ab3f8c5
crypt_key sha256 128 cat- $KEY_FILE f3b827c8a6f159ad8c8ed5bd5ab3f8c5 0
crypt_key sha256 128 cat- $KEY_FILE f3b827c8a6f159ad8c8ed5bd5ab3f8c5 80
crypt_key sha256 128 cat- $KEY_FILE a82c9227cc54c7475620ce85ba1fca1e 14
crypt_key sha256 128 cat- $KEY_FILE 7df3f4a41a33805596be85c781cac3b4 14 2
crypt_key sha256 128 cat- $KEY_FILE ebbe65a178e886ddbb778e0a5538db72 40 40
# limiting plain (no hash)
crypt_key plain 256 pwd "xxxxxxxx" 7878787878787878000000000000000000000000000000000000000000000000
crypt_key plain:2 256 pwd "xxxxxxxx" 7878000000000000000000000000000000000000000000000000000000000000
crypt_key plain:9 256 failpwd "xxxxxxxx" x
crypt_key sha256 128 cat $KEY_FILE a82c9227cc54c7475620ce85ba1fca1e 14
crypt_key sha256:14 128 cat $KEY_FILE a82c9227cc54c7475620ce85ba1f0000 14

View File

@@ -6,22 +6,38 @@ REENC=../src/cryptsetup-reencrypt
DEV_NAME=reenc9768
DEV_NAME2=reenc1273
IMG=reenc-data
ORIG_IMG=reenc-data-orig
KEY1=key1
PWD1="93R4P4pIqAH8"
PWD2="1cND4319812f"
PWD3="1-9Qu5Ejfnqv"
MNT_DIR=./mnt_luks
START_DIR=$(pwd)
function del_scsi_device()
{
rmmod scsi_debug 2>/dev/null
sleep 2
}
function remove_mapping()
{
[ -b /dev/mapper/$DEV_NAME2 ] && dmsetup remove $DEV_NAME2
[ -b /dev/mapper/$DEV_NAME ] && dmsetup remove $DEV_NAME
[ ! -z "$LOOPDEV1" ] && losetup -d $LOOPDEV1 >/dev/null 2>&1
rm -f $IMG $KEY1 >/dev/null 2>&1
rm -f $IMG $ORIG_IMG $KEY1 >/dev/null 2>&1
umount $MNT_DIR > /dev/null 2>&1
rmdir $MNT_DIR > /dev/null 2>&1
LOOPDEV1=""
del_scsi_device
}
function fail()
{
[ -n "$1" ] && echo "$1"
echo "FAILED"
cd $START_DIR
remove_mapping
exit 2
}
@@ -32,12 +48,25 @@ function skip()
exit 0
}
function add_scsi_device() {
del_scsi_device
modprobe scsi_debug $@
if [ $? -ne 0 ] ; then
echo "This kernel seems to not support proper scsi_debug module, test skipped."
exit 0
fi
sleep 2
SCSI_DEV="/dev/"$(grep -l -e scsi_debug /sys/block/*/device/model | cut -f4 -d /)
[ -b $SCSI_DEV ] || fail "Cannot find $SCSI_DEV."
}
function open_crypt()
{
if [ -n "$1" ] ; then
echo "$1" | $CRYPTSETUP luksOpen $LOOPDEV1 $DEV_NAME || fail
else
$CRYPTSETUP luksOpen -d key1 $LOOPDEV1 $DEV_NAME || fail
$CRYPTSETUP luksOpen -d $KEY1 $LOOPDEV1 $DEV_NAME || fail
fi
}
@@ -50,6 +79,7 @@ function wipe() # $1 pass
{
open_crypt $1
wipe_dev /dev/mapper/$DEV_NAME
udevadm settle >/dev/null 2>&1
$CRYPTSETUP luksClose $DEV_NAME || fail
}
@@ -80,17 +110,107 @@ function check_hash() # $1 pwd, $2 hash
$CRYPTSETUP remove $DEV_NAME || fail
}
function backup_orig()
{
sync
losetup -d $LOOPDEV1
cp $IMG $ORIG_IMG
losetup $LOOPDEV1 $IMG
}
function rollback()
{
sync
losetup -d $LOOPDEV1
cp $ORIG_IMG $IMG
losetup $LOOPDEV1 $IMG
}
function check_slot() #space separeted list of ENABLED key slots
{
local _KS0=DISABLED
local _KS1=$_KS0 _KS2=$_KS0 _KS3=$_KS0 _KS4=$_KS0 _KS5=$_KS0 _KS6=$_KS0 _KS7=$_KS0
local _tmp
for _tmp in $*; do
eval _KS$_tmp=ENABLED
done
local _out=$($CRYPTSETUP luksDump $LOOPDEV1 | grep -e "Key Slot" | cut -d ' ' -f 4)
local _i=0
for _tmp in $_out; do
eval local _orig="\${_KS${_i}}"
if [ "$_tmp" != "$_orig" ]; then
echo "Keyslot $_i is $_tmp, expected result: $_orig"
return 1
fi
_i=$[_i+1]
done
return 0
}
function simple_scsi_reenc()
{
echo -n "$1"
echo $PWD1 | $CRYPTSETUP luksFormat -i1 $SCSI_DEV || fail
echo $PWD1 | $CRYPTSETUP luksOpen $SCSI_DEV $DEV_NAME || fail
HASH=$(sha256sum /dev/mapper/$DEV_NAME | cut -d' ' -f 1)
$CRYPTSETUP luksClose $DEV_NAME || fail
echo $PWD1 | $REENC -q -i 1 $SCSI_DEV || fail
echo $PWD1 | $CRYPTSETUP luksOpen $SCSI_DEV $DEV_NAME || fail
check_hash_dev /dev/mapper/$DEV_NAME $HASH
$CRYPTSETUP luksClose $DEV_NAME || fail
}
function mount_and_test() {
test -d $MNT_DIR || mkdir -p $MNT_DIR
mount $@ $MNT_DIR 2>/dev/null || {
echo -n "failed to mount [SKIP]"
return 0
}
rm $MNT_DIR/* 2>/dev/null
cd $MNT_DIR
echo $PWD2 | $START_DIR/$REENC $LOOPDEV1 -q --use-fsync --use-directio --write-log || return 1
cd $START_DIR
umount $MNT_DIR
echo -n [OK]
}
function test_logging_tmpfs() {
echo -n "[tmpfs]"
mount_and_test -t tmpfs none -o size=$[25*1024*1024] || return 1
echo
}
function test_logging() {
echo -n "$1:"
for img in $(ls img_fs*img.bz2) ; do
wipefs -a $SCSI_DEV > /dev/null
echo -n "[${img%.img.bz2}]"
bzip2 -d -c $img | dd of=$SCSI_DEV >/dev/null 2>&1
mount_and_test $SCSI_DEV || return 1
done
echo
}
[ $(id -u) != 0 ] && skip "WARNING: You must be root to run this test, test skipped."
[ ! -x "$REENC" ] && skip "Cannot find $REENC, test skipped."
which wipefs >/dev/null || skip "Cannot find wipefs, test skipped."
# REENCRYPTION tests
HASH1=b69dae56a14d1a8314ed40664c4033ea0a550eea2673e04df42a66ac6b9faf2c
HASH2=d85ef2a08aeac2812a648deb875485a6e3848fc3d43ce4aa380937f08199f86b
HASH3=e4e5749032a5163c45125eccf3e8598ba5ed840df442c97e1d5ad4ad84359605
HASH4=2daeb1f36095b44b318410b3f4e8b5d989dcc7bb023d1426c492dab0a3053e74
echo "[1] Reencryption"
prepare 8192
prepare 8192
echo $PWD1 | $CRYPTSETUP -q luksFormat -s 128 -c aes-cbc-plain -i 1 --align-payload 4096 $LOOPDEV1 || fail
wipe $PWD1
check_hash $PWD1 $HASH1
@@ -112,12 +232,15 @@ echo $PWD1 | $REENC $LOOPDEV1 -q -i 1 || fail
check_hash $PWD1 $HASH2
echo "[3] Reencryption with keyfile"
echo $PWD1 | $CRYPTSETUP -q luksFormat -d key1 -c aes-cbc-essiv:sha256 -s 128 -i 1 --align-payload 4096 $LOOPDEV1 || fail
echo $PWD1 | $CRYPTSETUP -q luksFormat -d $KEY1 -c aes-cbc-essiv:sha256 -s 128 -i 1 --align-payload 4096 $LOOPDEV1 || fail
wipe
check_hash "" $HASH1
echo $PWD1 | $CRYPTSETUP -q luksAddKey -d key1 $LOOPDEV1 || fail
$REENC $LOOPDEV1 -d key1 -S 0 -i 1 -q || fail
echo $PWD1 | $CRYPTSETUP -q luksAddKey -d $KEY1 $LOOPDEV1 || fail
$REENC $LOOPDEV1 -d $KEY1 -i 1 -q 2>/dev/null && fail
$REENC $LOOPDEV1 -d $KEY1 -S 0 -i 1 -q || fail
check_hash "" $HASH1
check_slot 0 || fail "Only keyslot 0 expected to be enabled"
$REENC $LOOPDEV1 -d $KEY1 -i 1 -q || fail
# FIXME echo $PWD1 | $REENC ...
echo "[4] Encryption of not yet encrypted device"
@@ -131,5 +254,75 @@ dmsetup remove $DEV_NAME2 || fail
echo $PWD1 | $REENC $LOOPDEV1 -c aes-cbc-essiv:sha256 -s 128 --new --reduce-device-size "$OFFSET"S -q
check_hash $PWD1 $HASH3
echo "[5] Reencryption using specific keyslot"
echo $PWD2 | $CRYPTSETUP -q luksFormat -i 1 $LOOPDEV1 || fail
echo -e "$PWD2\n$PWD1" | $CRYPTSETUP -q luksAddKey -i 1 -S 1 $LOOPDEV1 || fail
echo -e "$PWD2\n$PWD2" | $CRYPTSETUP -q luksAddKey -i 1 -S 2 $LOOPDEV1 || fail
echo -e "$PWD2\n$PWD1" | $CRYPTSETUP -q luksAddKey -i 1 -S 3 $LOOPDEV1 || fail
echo -e "$PWD2\n$PWD2" | $CRYPTSETUP -q luksAddKey -i 1 -S 4 $LOOPDEV1 || fail
echo -e "$PWD2\n$PWD1" | $CRYPTSETUP -q luksAddKey -i 1 -S 5 $LOOPDEV1 || fail
echo -e "$PWD2\n$PWD2" | $CRYPTSETUP -q luksAddKey -i 1 -S 6 $LOOPDEV1 || fail
echo -e "$PWD2\n$PWD3" | $CRYPTSETUP -q luksAddKey -i 1 -S 7 $LOOPDEV1 || fail
backup_orig
echo $PWD2 | $REENC -i 1 -S 0 -q $LOOPDEV1 || fail
check_slot 0 || fail "Only keyslot 0 expected to be enabled"
wipe $PWD2
rollback
echo $PWD1 | $REENC -i 1 -S 1 -q $LOOPDEV1 || fail
check_slot 1 || fail "Only keyslot 1 expected to be enabled"
wipe $PWD1
rollback
echo $PWD2 | $REENC -i 1 -S 6 -q $LOOPDEV1 || fail
check_slot 6 || fail "Only keyslot 6 expected to be enabled"
wipe $PWD2
rollback
echo $PWD3 | $REENC -i 1 -S 7 -q $LOOPDEV1 || fail
check_slot 7 || fail "Only keyslot 7 expected to be enabled"
wipe $PWD3
rollback
echo "[6] Reencryption using all active keyslots"
echo -e "$PWD2\n$PWD1\n$PWD2\n$PWD1\n$PWD2\n$PWD1\n$PWD2\n$PWD3" | $REENC -q $LOOPDEV1 || fail
check_slot 0 1 2 3 4 5 6 7 || fail "All keyslots expected to be enabled"
echo "[7] Reencryption of block devices with different block size"
add_scsi_device sector_size=512 dev_size_mb=8
simple_scsi_reenc "[512 sector]"
add_scsi_device sector_size=4096 dev_size_mb=8
simple_scsi_reenc "[4096 sector]"
add_scsi_device sector_size=512 physblk_exp=3 dev_size_mb=8
simple_scsi_reenc "[4096/512 sector]"
echo "[OK]"
echo "[8] Header only reencryption (hash and iteration time)"
echo $PWD1 | $CRYPTSETUP -q luksFormat --hash sha1 $LOOPDEV1 || fail
wipe $PWD1
check_hash $PWD1 $HASH1
echo $PWD1 | $REENC $LOOPDEV1 -q --keep-key --hash sha256 --iter-time 1
check_hash $PWD1 $HASH1
echo $PWD1 | $REENC $LOOPDEV1 -q --keep-key --hash sha512
check_hash $PWD1 $HASH1
echo $PWD1 | $REENC $LOOPDEV1 -q --keep-key --iter-time 1
check_hash $PWD1 $HASH1
echo "[9] Test log I/Os on various underlaying block devices"
prepare 8192
echo $PWD2 | $CRYPTSETUP -q luksFormat -i 1 $LOOPDEV1 || fail
add_scsi_device sector_size=512 dev_size_mb=25
test_logging "[512 sector]" || fail
add_scsi_device sector_size=4096 dev_size_mb=25
test_logging "[4096 sector]" || fail
add_scsi_device sector_size=512 dev_size_mb=25 physblk_exp=3
test_logging "[4096/512 sector]" || fail
test_logging_tmpfs || fail
echo "[10] Removal of encryption"
prepare 8192
echo $PWD1 | $CRYPTSETUP -q luksFormat -i 1 $LOOPDEV1 || fail
wipe $PWD1
check_hash $PWD1 $HASH1
echo $PWD1 | $REENC $LOOPDEV1 -q --decrypt
check_hash_dev $LOOPDEV1 $HASH4
remove_mapping
exit 0

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