Compare commits

...

858 Commits

Author SHA1 Message Date
Milan Broz
9843014dce Add API changes list to release notes. 2017-09-29 09:15:02 +02:00
Milan Broz
728a454919 Update version. 2017-09-29 01:25:25 +02:00
Milan Broz
dff09b7e65 Add RC0 release notes. 2017-09-29 01:22:58 +02:00
Ondrej Kozina
bb40433960 add keyring notes 2017-09-28 11:25:17 +02:00
Milan Broz
6cd770e501 Add temporary description of LUKS2 on-disk format. 2017-09-28 11:23:33 +02:00
Milan Broz
0f347b9c5c SLighly reformat locking doc. 2017-09-28 11:23:03 +02:00
Ondrej Kozina
c3b3d7b022 fix api-test for builds without keyring support 2017-09-27 11:03:11 +02:00
Milan Broz
948006561a Yet another fix for header strings. 2017-09-27 10:54:03 +02:00
Milan Broz
3ccbb8fe84 Fix some problems found by Coverity analysis. 2017-09-27 10:18:38 +02:00
Milan Broz
c1c541642e Add a note about locking to man page. 2017-09-27 08:12:09 +02:00
Ondrej Kozina
b4782809d4 luks2: allow masking of requirements internaly
before this patch any LUKS2 requirement defined in header
would stop a restricted operation from proceeding further.
This patch adds ability to mask requirements (internal only).
2017-09-27 07:48:53 +02:00
Ondrej Kozina
b3feae5474 luks2: unify naming for requirements flags 2017-09-27 07:47:41 +02:00
Ondrej Kozina
c015aeca4e luks2: move pre-activation requirements check lower 2017-09-27 07:47:13 +02:00
Milan Broz
9bbc13f256 Add LUKS2 examples.
Signed-off-by: Milan Broz <gmazyland@gmail.com>
2017-09-27 07:46:41 +02:00
Milan Broz
38d53db6e9 Reformat and fix libcryptsetup.h / Doxygen doc.
No functional change in this patch.
2017-09-26 16:35:20 +02:00
Ondrej Kozina
0f4d83960f add remainders to fix some longstanding issues 2017-09-24 19:50:34 +02:00
Milan Broz
19a1852e4b Support sector size option even for plain devices. 2017-09-24 19:50:28 +02:00
Milan Broz
c6d4ebd80c Add libLUKS2 tests. 2017-09-24 19:50:17 +02:00
Milan Broz
9f2727bb77 Add libLUKS2. 2017-09-24 19:50:12 +02:00
Milan Broz
00b103c85c Allow wip-luks2 build in Travis. 2017-09-24 19:50:05 +02:00
Milan Broz
a0d2d4c0b1 Add uint64_to_str helper. 2017-09-24 19:50:01 +02:00
Milan Broz
64e91951b2 Add generic LUKS format define.
It means "load any LUKS version".
2017-09-24 19:49:56 +02:00
Milan Broz
e7de19fe1d Split utils from API test. 2017-09-24 19:49:51 +02:00
Milan Broz
5536b3a58d Add implementation of device/file locking for metadata.
To be used later.
2017-09-24 19:49:46 +02:00
Milan Broz
a8347d2820 Add integrity intefrace test stub. 2017-09-24 19:49:40 +02:00
Milan Broz
c56bdee177 Add backend support for new device-mapper kernel options.
This patch adds support for using keyring for volume key
and support for new integrity fields for dm-crypt.

Also helpers for searching disk by id.

To be used later.
2017-09-24 19:49:35 +02:00
Milan Broz
894e7b9357 Add base64 implementation.
To be used later. Copy from gnulib.
2017-09-24 19:49:30 +02:00
Milan Broz
2aee1426de Speed up tests by avoiding PBKDF benchmarks in many cases. 2017-09-24 19:49:25 +02:00
Milan Broz
66db5b39bb Change PBKDF insterface to allow forced iterations (time cost) count.
Also move functions to separate utils_pbkdf.c file.

PBKDF can be now set for any context.

TODO: new setting is not covered by tests.
2017-09-24 19:49:21 +02:00
Milan Broz
a73bb733ff Fix list of files for translation. 2017-09-24 10:09:48 +02:00
Michal Virgovic
3d57f5fcbb Add tests for integritysetup error detection. 2017-09-23 23:49:25 +02:00
Ondrej Kozina
c34bee2009 return correct key description format in dm_query_device
dm_query_device is expected to return kernel key description
string only. By mistake the code returned also type in head
of key description.
2017-09-23 23:45:32 +02:00
Milan Broz
c3a0cbfc85 Update documentation. 2017-09-23 23:34:18 +02:00
Milan Broz
57825365fe Fix another signed/unsigned compilation warnings. 2017-09-23 23:30:28 +02:00
Milan Broz
b35785bb1b Fix some signed/unsigned and other compiler warnings. 2017-09-23 23:29:11 +02:00
Milan Broz
0d2f888413 Fix some tests to run under make distcheck and separately. 2017-09-23 23:24:24 +02:00
Milan Broz
a85fee7a0d Silence compiler warning (dmt_flags is always initialized). 2017-09-11 12:36:43 +02:00
Milan Broz
f66dedc759 Add plain64be IV to storage backend. 2017-09-11 12:33:10 +02:00
Ondrej Kozina
a62da3d530 extend stackframe in valgrind tests 2017-08-26 11:46:26 +02:00
Ondrej Kozina
1cc972c723 improve kernel keyring usability detection for tests 2017-08-26 11:46:16 +02:00
Milan Broz
6b7a2f6641 Fix memory leaks in dm_query_integrity and dm_query_verity. 2017-08-26 11:44:21 +02:00
Milan Broz
34b79794ea Mark python test as skipped with exit code 77. 2017-08-26 11:44:03 +02:00
Ondrej Kozina
fb114d8d20 fix memleaks in lower level dm_query_device on error path 2017-08-26 11:43:31 +02:00
Ondrej Kozina
a6106117a9 Fail gracefully if name is NULL in crypt_init_by_name() & co 2017-08-25 21:36:50 +02:00
Ondrej Kozina
b27507790f fix memleak in crypt_resize() 2017-08-25 21:32:57 +02:00
Milan Broz
a0880b64f2 Add magic exit code for automake to count skipped tests. 2017-08-23 16:54:04 +02:00
Milan Broz
6e057c010f Revert "Set block size for loop device if supported by kernel (4.13+)."
This reverts commit 4e2deadba7.

There is too many cases with 4k unaligned images that this optimization
adds more problems than it solves. Revert it for now.
2017-08-23 08:07:27 +02:00
Milan Broz
540972ff59 Move progress function to utils. 2017-08-22 16:13:40 +02:00
Milan Broz
677adc7adc Add crypt_backend_destroy() function and cll it as library destructor. 2017-08-22 15:48:24 +02:00
Milan Broz
096c50cafc Fix memory leak during repeated password entry. 2017-08-22 15:38:29 +02:00
Ondrej Kozina
8c57e3ffca Hint kernel keyring disabled in debug message 2017-08-22 13:47:20 +02:00
Milan Broz
4e2deadba7 Set block size for loop device if supported by kernel (4.13+). 2017-08-22 13:45:59 +02:00
Milan Broz
497fb0b3c3 Fix Argon2 benchmark.
1) If the calculated costs were the same, it run forever.

2) If the calculation returned final values in the first step,
out costs were not updated and benchmark returned too low values.
2017-08-16 15:43:11 +02:00
Milan Broz
8debcf9f92 Do not use too complicated regular expression in test. 2017-08-15 12:01:59 +02:00
Milan Broz
db0a21b93f Fix PBKDF benchmark for old PBKDF2 tests (hash specified only). 2017-08-15 09:20:30 +02:00
angelomariafederichini191269@protonmail.com
e2fee206c2 Allocate suitable sized buffer when reading a keyfile
If the keyfile size is explicitly given, then allocate a suitable sized
buffer right from the start instead of increasing it in 4k steps. This
speeds up reading larger keyfiles.
2017-08-15 08:49:44 +02:00
angelomariafederichini191269@protonmail.com
596e374313 Use bulk read when reading keyfile
If reading a keyfile use bulk read operations instead of reading one
character at the time. This speeds up reading larger keyfiles.

If read should stop at a EOL, then fallback to reading one character at
the time to not read anything beyond the EOL character.
2017-08-15 08:39:53 +02:00
Milan Broz
503956707c Move crypt_keyfile_read() to libcryptsetup internal file.
The utils_crypt.c file is directly linked to userpsace tools,
we should use library call and not local implementation.
2017-08-15 08:35:10 +02:00
Milan Broz
87dd427d79 Make benchmark progress parameter the same as the internal unsigned type. 2017-08-12 17:55:01 +02:00
Milan Broz
5fc79f5627 Move PBKDF internal benchmark to one place.
Also cache its value in active context, so we run benchmark
only once.

The patch also changes calculated value for LUKS1 key digest
to 125 miliseconds (it means that for full 8 used slots
the additional slow-down is circa 1 second).

Note that there is no need to have too high iteration count
for key digest; if it is too computationally expensive, attacker
will better decrypt of one sector with candidate key anyway.
(Check for a known signature.)

The reason to have some delay for key digest check was
to complicate brute-force search for volume key with LUKS header
only (and if RNG used to generate volumekey was flawed
allowing such a search i reasonable time).
2017-08-12 17:50:02 +02:00
Milan Broz
f4bb2ad613 Tweak kdf benchmark log.. 2017-08-11 16:08:44 +02:00
Ondrej Mosnáček
15b4f64b91 Fix Argon2 benchmark for decreasing parameters
When we have measured time smaller than target time, we are decreasing
the parameters. Thus, we should first try to decrease t_cost and only
if that is not possible should we try to decrease m_cost instead. The
original logic was only valid for the case where parameters are being
increased. Most notably this caused unusual parameter combinations for
iteration time < 250 ms.

In this commit we also factor out the now heavily nested parameter
update formula.
2017-08-11 16:01:09 +02:00
Milan Broz
a1a7d41e7a Group functions together more logically.
No functional change in this patch, just code shuffling.
2017-08-11 14:41:11 +02:00
Milan Broz
74547a4313 Remove unused code from integritysetup. 2017-08-10 19:27:24 +02:00
Milan Broz
9a532080d0 Fix PBKDF2 check to not overflow and not divide by zero. 2017-08-10 18:14:36 +02:00
Milan Broz
32c6afb120 Do not run keyring test in without root privileges. 2017-08-10 13:48:23 +02:00
Milan Broz
896eb26877 Add keyutils package to Travis tests. 2017-08-10 13:25:52 +02:00
Milan Broz
0a8bc6f1c7 Decrease iteration count to make compat test faster. 2017-08-10 13:18:42 +02:00
Michal Virgovic
175aaedc79 Add interactive tests. 2017-08-10 13:00:49 +02:00
Milan Broz
4125beb0fb Add callback for PBKDF benchmark.
Also change API so the kdf structure is continuously updated
with the benchmarked data (callback can see progress or debug).
2017-08-10 12:44:24 +02:00
Ondrej Mosnáček
93ea4f4f6f Tweak Argon2 benchmark to finish faster.
The benchmark is taking too long...
2017-08-10 12:39:25 +02:00
Michal Virgovic
d3f4eedb12 Add non-root tests. 2017-08-07 14:35:39 +02:00
Milan Broz
5a49efec58 Allow separate benchmark for a KDF (with --pbkdf option). 2017-08-07 12:30:05 +02:00
Milan Broz
3435f9cb2c Use only crypt_get_integrity_info in API.
Some other functions remain internal only.

Signed-off-by: Milan Broz <gmazyland@gmail.com>
2017-08-06 21:34:01 +02:00
Milan Broz
d891e00f63 Add kernel keyring functions for volume key.
Code is written by Ondrej Kozina.

This patch adds ability to store volume key in kernel keyring
(feature available in recent kernels) and avoid setting
key through dm-ioctl and avoiding key in table mapping.

Will be used in LUKS2.

Signed-off-by: Milan Broz <gmazyland@gmail.com>
2017-08-06 21:30:51 +02:00
Milan Broz
8a859391be Add Argon2 benchmark code.
Code based on patch by Ondrej Mosnacek

The new benchmark works as follows:

Phase 1:
It searches for smallest parameters, such that the duration is 250 ms
(this part is quite fast).
Then it uses that data point to estimate the paramters that will have
the desired duration (and fulfill the basic constraints).

Phase 2:
The candidate parameters are then measured and if their duration falls
within +-5% of the target duration, they are accepted.
Otherwise, new candidate parameters are estimated based on the last
measurement and phase 2 is repeated.

When measuring the duration for given parameters, the measurement
is repeated 3 or 4 times and a minimum of the measured durations
is used as the final duration (to reduce variance in measurements).
A minimum is taken instead of mean, because the measurements definitely
have a certain lower bound, but no upper bound (therefore mean value
would tend to be higher than the value with highest probability density).
The actual "most likely" duration is going to be somewhere just above
the minimum measurable value, so minimum over the observations is
a better estimate than mean.

Signed-off-by: Milan Broz <gmazyland@gmail.com>
2017-08-06 21:30:11 +02:00
Milan Broz
0abf57be5d Change PBKDF interface API.
Prepare API for PBKDF that can set three costs
  - time (similar to iterations in PBKDF2)
  - memory (required memory for memory-hard function)
  - threads (required number of threads/CPUs).

This patch also removes wrongly designed API call
crypt_benchmark_kdf and replaces it with the new call
crypt_benchmark_pbkdf.

Two functions for PBKDF per context setting
are introduced: crypt_set_pbkdf_type and crypt_get_pbkdf_type.

The patch should be backward compatible when using
crypt_set_iteration_time function (works only for PBKDF2).

Signed-off-by: Milan Broz <gmazyland@gmail.com>
2017-08-06 21:24:05 +02:00
Milan Broz
09d14a0b6c Add Argon2 bundled library to crypto backend.
The Argon2i/id is a password hashing function that
won Password Hashing Competiton.

It will be (optionally) used in LUKS2 for passworrd-based
key derivation.

We have to bundle code for now (similar PBKDF2 years ago)
because there is yet no usable implementation in common
crypto libraries.
(Once there is native implementation, cryptsetup
will switch to the crypto library version.)

For now, we use reference (not optimized but portable) implementation.

This patch contains bundled Argon2 algorithm library copied from
  https://github.com/P-H-C/phc-winner-argon2

For more info see Password Hashing Competition site:
  https://password-hashing.net/
and draft of RFC document
  https://datatracker.ietf.org/doc/draft-irtf-cfrg-argon2/

Signed-off-by: Milan Broz <gmazyland@gmail.com>
2017-08-06 21:13:12 +02:00
Milan Broz
9bd06be43b Add info function for integrity devices and print info about journal attributes. 2017-07-31 16:49:19 +02:00
Milan Broz
01598028c4 Aff info function for integrity device and print info ion status. 2017-07-31 16:48:29 +02:00
Milan Broz
cf9428fba1 Fix typo in journal integrity processing. 2017-07-31 15:42:20 +02:00
Milan Broz
4faa9e9f45 Swtich default integritysetup crc32 alg to crc32c (that is hw accelerated in recent Intel CPUs). 2017-07-27 14:26:41 +02:00
Milan Broz
4bcba41d77 Fix crypt_init(cd, NULL) case in the previous commit. 2017-07-27 13:36:53 +02:00
Milan Broz
12040570ca Allow to open device without read check.
In some specific situation we do not want to read the devices
before initialization.

Here it is integrity checking that will produce warning, because
the device is not yet initialized.

Used only in wipe function (here we must use direct-io anyway)
and expect the device is capable of direct-io.
2017-07-27 12:56:07 +02:00
Milan Broz
5824e8d242 Simplify device block size check. 2017-07-26 14:53:37 +02:00
Milan Broz
d7a0d860b9 Use getvfs for block size of filesytem if available. 2017-07-26 14:32:21 +02:00
Milan Broz
dbdb611bcc Document crypt_params_integrity struct members. 2017-07-26 13:21:19 +02:00
Michal Virgovic
3b3e14d056 Update doxygen documentation for version 1.8. 2017-07-26 12:51:17 +02:00
Milan Broz
962bf58f8f Print error message if device exists but as other subsystem. 2017-07-26 12:42:58 +02:00
Milan Broz
6f2ff93519 Do not repeat password question if underlying function returns EINVAL.
This error code means invalid value, no point in repeating the whole sequence.
(If there is a situation that requires repeat, it should not return EINVAL.)
2017-07-26 10:44:42 +02:00
Milan Broz
e853aa2e7c Fix blockwise access functions for systems with big page size.
Initially cryptsetup expected underlying device that was, by definition,
always aligned to a sector size (and length was always multiple of sectors).

For the images in file, we can now access the image directly.
Expecting that the image is always aligned to the whole block is now false
(the last block in file image can be incomplete).

Moreover, we cannot easily detect underlying block device sector (block) size
(the storage stack can be complex with various RAID and loop block sizes),
so code uses systyem PAGE_SIZE in this situation (should be the safest way).

Unfortunately, PAGE_SIZE can be bigger (1MB) than device sector (4k) and
the blockwise functions then fails because the image in file is not
aligned to PAGE_SIZE multiple..

Fix it by checking that read/write for the last part of an image is
the exact requested size and not a full block.

(The problem is for example for an unaligned hidden Truecrypt header
on PPC64LE systems, where page size is 64k.)
2017-07-24 14:17:21 +02:00
Milan Broz
248e35036f Do not fail if wipe size is smaller than block size.
With big page size and image in file this can actually happen.

The command works in this situation but the code will be quite
ineffective (due to blockwise handling).
2017-07-24 14:15:42 +02:00
Ingo Franzki
96f1cdf687 Typo in man page
I guess this should be 'existing' not 'exiting'.

Signed-off-by: Ingo Franzki <ifranzki@linux.vnet.ibm.com>
2017-07-20 09:42:41 +02:00
Michal Virgovic
d483b6d25c Add nonroot tests for travis. 2017-07-19 11:59:24 +02:00
Milan Broz
293fa48884 Run part of test as non root user. 2017-07-19 11:57:55 +02:00
Michal Virgovic
45bd005be9 Enable python tests in travis. 2017-07-14 17:31:49 +02:00
Michal Virgovic
efe88d4979 Add tests for FEC area overlap detection. 2017-07-11 18:16:15 +02:00
Michal Virgovic
913c9aa3d3 FEC-area overlap detection. 2017-07-11 17:36:47 +02:00
Michal Virgovic
a36c53af99 Correction of integritysetup manual. 2017-07-11 11:54:58 +02:00
Michal Virgovic
8ff808c882 Update of integritysetup manual and typos correction.
[Heavily modified by mbroz]
2017-07-03 16:49:41 +02:00
Milan Broz
9ade110a25 Fix typo in tests. 2017-06-29 15:55:35 +02:00
Ondrej Kozina
2b3be9055a Disable conversion for legacy luks1 formats.
And export LUKS header size functions.
2017-06-29 15:50:42 +02:00
Ondrej Kozina
10bb186c76 lib: harden checks for null name in resume/suspend 2017-06-29 15:45:51 +02:00
Milan Broz
198f1d10c4 Point pdf links to kernel.org.
Some browsers seems to be already smarter than a 5th grader
and blocks the content on gitlab.
2017-06-29 12:19:32 +02:00
Milan Broz
5be69e92ce Check for interruption during passphrase retry. 2017-06-28 15:11:28 +02:00
Milan Broz
c80acbe4c8 Add back "Passphrase for (dev):" prompt. 2017-06-28 15:07:58 +02:00
Milan Broz
29681c0aa7 Fix access to devices under non-root user.
We cannot allocate loop device early in luksFormat,
use only device access check here.
2017-06-28 14:24:39 +02:00
Milan Broz
fdd6794ce3 Add some sleep to interactive prompt test.
Seems some distros use broken expect package.
2017-06-27 16:25:11 +02:00
Milan Broz
6c7e9608b9 Fix travis install line. 2017-06-27 15:53:41 +02:00
Milan Broz
5171f65c05 Return back password retry support for luksOpen.
Also add interactive test using expect utility.
2017-06-27 15:49:04 +02:00
Milan Broz
86f327d0f5 Add dmsetup remove retry to api test. 2017-06-27 14:14:20 +02:00
Milan Broz
b16fbde032 Add DM_UDEV_DISABLE_LIBRARY_FALLBACK to libdevmapper wrapper.
This call is required for deferred removal of device.

Morever, if the system reports that udev is running, we should not
try to "fix" problems by creating or removing nodes directly through libdevmapper.

(Non-udev case should still work.)
2017-06-27 09:12:05 +02:00
Milan Broz
9437035147 Use open/close syntax for veritysetup.
(but support create/remove aliases)
2017-06-26 15:31:47 +02:00
Milan Broz
f24fb2899e Use open/close syntax for integritysetup.
(but support create/remove aliases)
2017-06-26 15:24:58 +02:00
Milan Broz
19c5248675 Fix deferred test for old libdevmapper (deferred not compiled-in). 2017-06-24 20:05:26 +02:00
Milan Broz
2c3e0aee08 And check libdevmapper support for deferred flag as well. 2017-06-24 19:37:28 +02:00
Milan Broz
552e9c8408 Check DM support for deferred flag.
So it fails correctly on older systems.
2017-06-24 19:07:14 +02:00
Milan Broz
164bbdfcfc Add test for deferred removal.
Print more info in CLI command.
2017-06-24 10:32:48 +02:00
Milan Broz
3efa00d59a Revert deferred flag for keyslots and temp devices.
It could cause races later, replacing with error device is enough.
2017-06-24 09:57:22 +02:00
Milan Broz
ea694a4588 Fix force removal option. 2017-06-23 15:42:46 +02:00
Milan Broz
32d5e59ab6 Implement deferred removal of device.
This can be used in some automated systems and allows device
to be removed after the last user mapping closes it.
2017-06-23 14:41:54 +02:00
Milan Broz
a58ed1ada3 Better specify error codes from crypt_wipe. 2017-06-22 13:32:05 +02:00
Milan Broz
c80dbb2210 Fxi luksKill slot to work in batch mode in non-tty environment.
If there is no TTY on stdin (like nohup or service) then
batch mode should not fail to kill slot.

For more info see Issue#329.
2017-06-21 13:31:08 +02:00
Milan Broz
ce1e5374b9 Fix API tracker URL. 2017-06-18 09:00:11 +02:00
Ondrej Kozina
c4fa881303 luks1: cleanup for added checks
related to bef56af730
2017-06-16 11:09:41 +02:00
Milan Broz
d02b291e2f Remove TODO line. 2017-06-15 13:57:27 +02:00
Milan Broz
4d21f4673d Add Travis configuration file for automated testing. 2017-06-15 13:46:36 +02:00
Ondrej Kozina
6682e6b663 tests: add test for overlaping keyslots in luks1 image 2017-06-15 11:17:36 +02:00
Ondrej Kozina
bef56af730 luks1: harden checks for possibly corrupted headers
this patches improves two areas:

1) it checks for keyslot areas overlaping each other
2) it checks if all keyslot areas fit in header area of device
   (pre-data-offset area) or if it can fit file (detached header)
   it's being loaded from. Those new checks are based on real data
   found in header (offsets) rather than based on assumption calculated
   from key length
2017-06-15 11:17:28 +02:00
Milan Broz
c7de6939ae Fix ioctl argument for block size check. 2017-06-09 10:33:57 +02:00
Milan Broz
2059266a24 Never decrease device block size (for example after attaching loop device). 2017-06-08 16:22:53 +02:00
Milan Broz
edba04c978 Fix batch mode for tools progress function. 2017-06-08 15:05:28 +02:00
Milan Broz
73030aa5fb Make block size size_t type.
And fix all related comparisons and functions.
2017-06-08 14:39:54 +02:00
Milan Broz
34bf809e51 Use device alignment wrapper.
And cache the value to not call ioctl on every block read/write.
2017-06-08 09:30:53 +02:00
Milan Broz
fd6fc16001 Use tools progress print function for cryptsetup-reencrypt. 2017-06-07 21:58:19 +02:00
Milan Broz
e438acfc5f Add wipe of device to integritysetup format. 2017-06-07 15:32:24 +02:00
Milan Broz
3a27c84d98 Rewrite and export crypt_wipe function.
The crypt_wipe can be used to wipe any part of the device,
and also to initialize integrity based device (to reset checksum).
2017-06-07 15:31:13 +02:00
Milan Broz
c6408f4b31 Link tools with -lm. 2017-06-07 15:24:12 +02:00
Milan Broz
fc026a722b integritysetup: fix processing of integer options. 2017-06-06 09:47:12 +02:00
Milan Broz
573a05a10f Add Veracrypt test image with PIM setting. 2017-06-01 16:44:52 +02:00
Milan Broz
6fc383ade1 Fix detection of target presence. 2017-06-01 12:25:39 +02:00
Milan Broz
40a9178c7f Rework detection of DM target flags.
Because there are already 3 targets used, the current detection
based only on dm-crypt is not sufficient.

Add new definition of dm_flags that allows separate target version detect.

Note: we do not want to load targets explicitly; instead, we repeats
detection after operation that could trigger target load.

If dm_flags() call fails, then the target is not yet loaded.
2017-06-01 09:28:09 +02:00
Milan Broz
82f7cae22c Make FEC verity test determnistic. 2017-05-30 14:50:32 +02:00
Ondrej Mosnáček
f786ed8505 Fix strncat usage
The 'strncat' function may write up to n + 1 bytes into destination, so
the 'n' parameter must be sizeof(dest) - strlen(dest) - 1. See [1] for
a nice explanation from US CERT.

[1] https://www.us-cert.gov/bsi/articles/knowledge/coding-practices/strncpy-and-strncat
2017-05-29 12:08:21 +02:00
Milan Broz
7e06265568 Parse integrity mode directly. 2017-05-29 10:40:06 +02:00
Milan Broz
2a50be152e Increase library and symbols version. 2017-05-29 10:23:24 +02:00
Milan Broz
ba5e91e278 Skip integrity test if target not available. 2017-05-28 23:02:49 +02:00
Milan Broz
5a3e3339e0 Make integrity param optional. 2017-05-28 22:47:05 +02:00
Milan Broz
0bb7098fd8 Add integritysetup command line tool for the dm-integrity standalone setting.
The dm-integrity target is intended to be used for authenticated
encryption through LUKS and dm-crypt.

It can be used in standalone as well; for this use case there
is a simple configuration utility called integritysetup
(similar to veritysetup to dm-verity).
2017-05-28 09:22:17 +02:00
Milan Broz
290b593d0b Add runtime check for FEC availability to dm-verity test. 2017-05-15 16:07:17 +02:00
Michal Virgovic
2745be83dd Add tests for FEC dm-verity extension. 2017-05-15 12:39:06 +02:00
Tobias Stoeckmann
44d5269c0a Prevent double free with invalid verity partition.
It is possible to trigger a double free with an invalid verity
partition. All it takes is an unknown hash algorithm, which makes it
a bit more likely than a completely broken partition header. But all
it takes is an error return value of VERITY_read_sb() or strdup().

If crypt_load fails before setting cd->type, crypt_free will handle
the union as if it was of type "none", which means it will call free()
for "active_name", a field which is only properly set up when the
type was actually "none".

In all other cases, "active_name" contains the first 4 or 8 bytes of
the actually used header structure. Fortunately it can be only a
pointer or NULL, so an attacker has no direct control of the value.
Nonetheless it can easily trigger a double free.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2017-05-02 08:25:40 +02:00
Milan Broz
3f9346836e Get rid of old alignment code and use posix_memalign.
We require posix_memalign already for some time so it makes
no sense to keep old workarounds.
2017-04-30 13:13:46 +02:00
Michal Virgovic
5d1b6f9af3 Update veritysetup man with FEC options. 2017-04-29 15:56:49 +02:00
Milan Broz
882751b51e Update po file... 2017-04-27 12:26:47 +02:00
Milan Broz
bbd59fa314 Fix stupid version typo in release notes. 2017-04-27 10:56:12 +02:00
Milan Broz
57c9d78629 Update README.md. 2017-04-27 10:47:43 +02:00
Milan Broz
78c9004a87 Add 1.7.5 release notes. 2017-04-27 08:42:00 +02:00
Milan Broz
8df2a598a7 Align benchmark output even for longer cipher names. 2017-04-26 14:32:54 +02:00
Harald Hoyer
1691282314 dracut-reencrypt: call "udevadm settle" once more
Somehow testing in qemu resulted sometimes in an endless loop.
Either the timing or the settle fixed the issue.
When the VM was in an endless loop, an strace showed, that the first 512
and 1024 of the crypt partition was read over and over. Either it was
the udev blkid, or some device mapper udev rule.
Maybe the reencrypt tool opens and closes the device fd, where the close
triggers a udev blkid and causes the reencrypt tool to reread the device...
Anyhow.. with this settle the issue was not seen anymore.
2017-04-26 10:50:44 +02:00
Harald Hoyer
3d6bb53b31 dracut-reencrypt: add UUID handling to rd.luks.reencrypt=
This patch adds a udev rule, so that you can specify
rd.luks.reencrypt=<UUID> instead of rd.luks.reencrypt=<devname>

It also moves the job to the "settled" queue, which means, that it is
executed after udev has settled.
2017-04-26 10:50:41 +02:00
Harald Hoyer
6a8a6aea54 dracut-reencrypt: add finished hook
A finished hook prevents dracut-initqueue from exiting and lets it
finish the batched jobs. Without a "finished hook" and without
"root=<dev>" on the kernel command line, the reencrypt job would not be
executed.

Normally you want to reencrypt without a "root=<dev>" on the kernel
command and want to reboot after the reencrypt job is done.

This patch adds the missing "finished hook".
2017-04-26 10:50:36 +02:00
Milan Broz
8c5760fee7 Fix API test for FIPS mode. 2017-04-21 09:32:13 +02:00
Milan Broz
3c2135b36b Fix luksFormat if running in FIPS mode on recent kernel.
Recently introduced check for weak keys for XTS mode makes
zeroed key for algorithm check unusable.

Use random key for the test instead.
2017-04-21 08:22:29 +02:00
Milan Broz
aad597b987 Fix activation of verity device with superblock and FEC. 2017-04-20 09:10:18 +02:00
Milan Broz
5fdfc0b54a Fix AF prototypes and move then to af.h. 2017-04-14 13:25:21 +02:00
Milan Broz
ef966bd261 Fix verity FEC block memory allocation.
Fixes corruption of memory when buffer is too small.
2017-04-14 12:31:44 +02:00
Milan Broz
54cb40fce7 Fix RS algorithm rewrite typo. 2017-04-05 16:29:26 +02:00
Milan Broz
c6a0048b9b Add check for FEC support in kernel dm-verity. 2017-04-05 15:16:13 +02:00
Milan Broz
425e8b9495 Fix possible divide by zero in verity hash blocks calculation. 2017-04-05 14:35:52 +02:00
Milan Broz
82dd6c7fa2 Fix some compiler warnings. 2017-04-05 14:24:20 +02:00
Milan Broz
e4f1faa478 Restructure Reed-Solomon code for verity FEC and remove unneeded parts. 2017-04-05 13:34:26 +02:00
Milan Broz
c7907630f4 Remove some redundant header includes. 2017-04-05 12:03:30 +02:00
Milan Broz
e18a7400b4 Fix compiler warning. 2017-04-05 11:51:22 +02:00
Milan Broz
058831d88c Remove verity FEC superblock support.
It seems to be never used anywhere.
2017-04-05 11:41:08 +02:00
Milan Broz
1da785cb77 Use common function for accessing FEC devices.
TODO: the device wrappet should hanbdle EINTR better...
2017-04-05 10:58:03 +02:00
Milan Broz
3a058a4f21 Remove local fec.h. 2017-04-05 08:29:03 +02:00
Milan Broz
3d6a589a04 Fix dm-verity max-size parameter. 2017-04-04 14:27:52 +02:00
Milan Broz
6c8b3686b4 Add FEC info to init_by_name.
And use it in veritysetup dump.
2017-04-03 13:55:20 +02:00
Milan Broz
fc0bef732b Add FEC offset parameter for verity. 2017-04-03 12:34:50 +02:00
Milan Broz
e8eab081c5 Add code for activation wirh FEC device. 2017-04-03 10:21:37 +02:00
Milan Broz
00419c6c41 Introduce function to calculate verity hash device size. 2017-04-03 10:19:29 +02:00
Milan Broz
7307293c87 Use explicit 32bit value in API for FEC roots. 2017-04-03 10:15:44 +02:00
Milan Broz
912f5b8f5b Do not write FEC superblock if no-superblock option is set. 2017-04-02 15:51:40 +02:00
Sami Tolvanen
c2cf33af24 WIP: Add support for verity FEC. 2017-04-01 21:23:10 +02:00
Milan Broz
eb59311136 Fix access to unaligned hidden TrueCrypt header.
On native 4k-sector device the old hidden header is not aligned
with hw sector size and derect-io access with SEEK_END fails.

Let's extend blockwise functions to support a negative offset
and use the same logic as normal unaligned writes.

Fixes problem mentioned in
https://gitlab.com/cryptsetup/cryptsetup/merge_requests/18
2017-03-27 12:04:31 +02:00
Milan Broz
fc42f878e9 Update README.md for 1.7.4. 2017-03-15 10:54:56 +01:00
Milan Broz
98368c4770 Update copyright years. 2017-03-12 13:17:15 +01:00
Milan Broz
c9da7f9f8c Add 1.7.4. Release notes. 2017-03-12 13:01:05 +01:00
Milan Broz
e7f8727d2d Fix some compiler warnings / wipe PIM properly. 2017-03-12 12:00:38 +01:00
Milan Broz
2657746451 Used LUKS1 compiled-in defaults also in Python wrapper. 2017-03-12 10:29:46 +01:00
Milan Broz
2701993dd6 Update po files. 2017-03-12 10:18:54 +01:00
Daniel Reichelt
9a798a766e support PIM parameter for VeraCrypt compatible devices
This patch adds the --veracrypt-pim=INT and --veracrypt-query-pim command-
line parameters to support specification of or being queried for a custom
Personal Iteration Multiplier respectively. This affects the number of
iterations for key derivation from the entered password. The manpage is
also updated accordingly.

Fixes Issue #307.
2017-03-02 09:11:23 +01:00
Bastien DHIVER
36419b25aa Add hashMode parameter in CryptSetup_luksFormat() 2017-03-01 13:32:26 +01:00
Milan Broz
9da67b701d Clarify use of --size parameter. 2017-02-15 20:26:02 +01:00
Milan Broz
ef7ecb5567 Fix race while allocating free loop device.
Fixes Issue #314.

Thanks to Martin Jeřábek for the report.
2017-01-20 15:27:40 +01:00
Milan Broz
a77c609c62 Fix possible fd leaks after exec.
Thanks Natanael Copa for the report.
Fixes issue#313.
2017-01-20 13:47:14 +01:00
Milan Broz
bca2bab560 Fix OpenSSL 1.1.0 compatibility
If backward-compatible API is not defined (-DOPENSSL_API_COMPAT=0x10100000L)
deprecated symbols cannot be used.

Also see https://bugs.gentoo.org/show_bug.cgi?id=604698

Thanks eroen for reporting this.
2017-01-05 09:06:31 +01:00
Milan Broz
e129b13402 Fix TrueCrypt URL in man page. 2017-01-04 08:04:10 +01:00
Arno Wagner
520b6d7344 some typos fixed in FAQ 2017-01-01 20:39:46 +01:00
Arno Wagner
bed395d039 Updates to FAQ
- Finished section 9 initrd with examples how to do your own
- Some minor fixes elswehere
2017-01-01 20:14:21 +01:00
Milan Broz
566f8c322b Update veritysetup man page.
Thanks Michal Virgovic for patch.
2016-12-13 14:29:13 +01:00
Milan Broz
807cedf4f3 Check for data device and hash device area overlap in veritysetup.
Thanks Michal Virgovic for tests.
2016-12-13 13:52:05 +01:00
Milan Broz
ef8a7d82d8 Update Readme.md. 2016-11-16 16:14:02 +01:00
Milan Broz
b906e8d299 Merge branch 'master' into 'master'
Fix use of LibreSSL.

Libressl declares `OPENSSL_VERSION_NUMBER 	0x20000000L`.

See merge request !12
2016-11-10 07:51:12 +00:00
Aric Belsito
0e14147132 Fix use of LibreSSL. 2016-11-03 11:55:39 -07:00
Milan Broz
c10e106787 Fix missing CRYPT_ACTIVATE_SAME_CPU_CRYPT flag check in status command. 2016-11-02 19:55:51 +01:00
Milan Broz
61725ee7cc Update readme.md for version 1.7.3. 2016-10-30 15:02:21 +01:00
Milan Broz
39f88f1712 Set devel version. 2016-10-30 14:53:54 +01:00
Milan Broz
e14aba8cf1 Add 1.7.3. Release Notes. 2016-10-28 11:19:26 +02:00
Milan Broz
97e774226d Update po files. 2016-10-28 11:01:23 +02:00
Milan Broz
6220e9c6cc Update po files. 2016-10-28 10:56:27 +02:00
Milan Broz
cba2a6c87c Update po files. 2016-10-22 10:35:52 +02:00
Milan Broz
71d7383491 Merge branch 'eviche/cryptsetup-patch-1' 2016-10-22 09:28:41 +02:00
Eduardo Villanueva Che
2c833c2342 Fixed veritysetup bug with hash offsets bigger than 2gb.
The lseek in function write_blockwise() could return value
that is greater than integer for result so it can overflow
and fail the whole write.
[comment added by mbroz]
2016-10-22 09:24:09 +02:00
Milan Broz
45fa8e724f Merge branch 'master' into 'master'
Fix several minor spelling errors found by Lintian

Fixes #306 

* lib/setup.c: miliseconds -> milliseconds
* lib/utils_wipe.c: Unsuported -> Unsupported
* man/crypsetup.8: implicitely -> implicitly
* man/veritysetup.8: verion -> version
* python/pycryptsetup.c: miliseconds -> milliseconds

See merge request !11
2016-10-22 07:04:10 +00:00
Jonas Meurer
b2a6e338b5 Fix several minor spelling errors found by Lintian
* lib/setup.c: miliseconds -> milliseconds
* lib/utils_wipe.c: Unsuported -> Unsupported
* man/crypsetup.8: implicitely -> implicitly
* man/veritysetup.8: verion -> version
* python/pycryptsetup.c: miliseconds -> milliseconds
2016-10-21 21:54:08 +02:00
Milan Broz
34734395c8 Set configured default iteration time early in crypt_init constructor. 2016-10-20 14:23:28 +02:00
Milan Broz
a3ee8f9cb8 Rephrase UUID error message forc cryptsetup-reencrypt. 2016-10-20 14:10:29 +02:00
Milan Broz
7f9e33ca1e Update po files. 2016-10-20 13:47:39 +02:00
Milan Broz
d4e8033fe0 Fix error path after conversion to OpenSSL 1.1.0. 2016-10-20 08:22:38 +02:00
Milan Broz
ab61af7481 Fix Nettle crypto backend definitions. 2016-10-19 21:18:07 +02:00
Milan Broz
8f204b4e23 Support OpenSSL 1.1.0 in cryptsetup backend. 2016-10-19 15:27:01 +02:00
Milan Broz
3b40e9dc93 Try to find python$VERSION-config. 2016-10-19 12:39:14 +02:00
Per x Johansson
b181b0ef6e Fix memory leak when using openssl backend
Fixes a memory leak when using openssl backend caused by mismatched
calls to EVP_DigestInit and EVP_DigestFinal_ex.
2016-10-18 14:05:49 +02:00
Milan Broz
4083bb2c0f Verify passphrase in cryptsetup-reencrypt when encrypting new drive. 2016-09-05 14:42:39 +02:00
Milan Broz
9d004a6aa4 Add link to LUKS spec on title page. 2016-09-05 09:37:36 +02:00
Milan Broz
d30bfe8b8e Update po files. 2016-08-03 14:19:20 +02:00
Milan Broz
38fbd85004 Update po files. 2016-07-25 12:23:09 +02:00
Milan Broz
467728b535 Fix keylength = 0 (no key) case. 2016-07-02 22:42:40 +02:00
Milan Broz
0c990eb0a2 Merge branch 'stoeckmann/cryptsetup-malloc' 2016-07-02 21:06:12 +02:00
Milan Broz
23ce9aa47e Fix crypt_generate_volume_key to use size_t for keylength. 2016-07-02 21:01:25 +02:00
Tobias Stoeckmann
a0587d4307 Avoid integer overflows during memory allocation.
It is possible to overflow integers during memory allocation with
insanely large "key bytes" specified in a LUKS header.

Although it could be argued to properly validate LUKS headers while
parsing them, it's still a good idea to fix any form of possible
overflow attacks against cryptsetup in these allocation functions.
2016-07-02 20:57:10 +02:00
Milan Broz
ea5e9c9fe2 Merge branch 'stoeckmann/cryptsetup-master' 2016-07-02 20:42:32 +02:00
Tobias Stoeckmann
14ebbce280 Avoid buffer overflow in uuid_or_device.
The function uuid_or_device is prone to a buffer overflow if a very long
spec has been defined. The range check happens against PATH_MAX, with
i being set to 5 (due to "UUID=" offset of spec), but "/dev/disk/by-uuid"
has been already written into device.

The difference between "/dev/disk/by-uuid" and "UUID=" is 13, therefore
the correct range check must happen against PATH_MAX - 13.
@@ -204,7 +204,7 @@ const char *uuid_or_device(const char *spec)
                strcpy(device, "/dev/disk/by-uuid/");
2016-07-02 20:41:51 +02:00
Milan Broz
67d55d08f8 Fix PBKDF2 benchmark to not double iteration count for corner case.
If measurement function returns exactly 500 ms, the iteration
calculation loop doubles iteration count but instead of repeating
measurement it uses this value directly.

Thanks to Ondrej Mosnacek for bug report.
2016-06-23 09:47:22 +02:00
Milan Broz
4d3a501b83 Force test to read device to detect corrupted blocks.
(If udev scanning is switched off, there is no real activity on device yet.)
2016-06-23 09:45:06 +02:00
Ondrej Kozina
16fab74ab1 code cleanup related to devfd checks
alter all checks for devfd value after device_open to
less than zero insted of equals to -1. device_open will
return values different from -1 in case error happens.

In LUKSv1 device_open should always return -1 in case of
error but this check is safer.

The rest is just formating improvement.
2016-06-08 13:12:06 +02:00
Milan Broz
f397d42d73 Update Readme.md. 2016-06-04 14:22:00 +02:00
Milan Broz
576a2e5b86 Workaround for align test for scsi_debug kernel in-use issue. 2016-06-04 13:12:15 +02:00
Milan Broz
060a4fbef0 Fix possible leak if reencryption is interrupted. 2016-06-04 12:36:51 +02:00
Milan Broz
f473fb3d7d Revert soname change. 2016-06-04 12:34:43 +02:00
Milan Broz
36f6073ec5 Set devel version. 2016-06-04 11:41:46 +02:00
Milan Broz
ebf7732943 Add 1.7.2 Release notes. 2016-06-04 11:36:36 +02:00
Milan Broz
c62427fd47 Update po files. 2016-06-02 19:18:04 +02:00
Milan Broz
ff09d1c531 Update po files. 2016-05-25 15:10:12 +02:00
Milan Broz
2852a48e6a Fix error message. 2016-05-25 14:56:13 +02:00
Milan Broz
1ab1803a43 Update po files. 2016-05-19 13:12:15 +02:00
Milan Broz
8f84fb49fa Fix help text for cipher benchmark specification. 2016-05-18 09:11:52 +02:00
Ondrej Kozina
e1dca468f5 keymanage: eliminate double close() call
fix  double close() cases in LUKS_hdr_backup() and LUKS_hdr_restore()
functions. It should be harmless unless libcryptsetup is used
in multi-thread setup which is not supported anyway.
2016-05-13 13:05:46 +02:00
Milan Broz
b1b3d93c96 Add ABI tracker output link. 2016-05-07 10:19:05 +02:00
Milan Broz
7d80112d4f Update LUKS doc format.
Clarify fixed sector size and keyslots alignment.
2016-05-04 15:48:04 +02:00
Milan Broz
4dd703ea6c Support activation options for error handling modes in dm-verity.
This patch adds veritysetup support for these Linux kernel dm-verity options:

  --ignore-corruption - dm-verity just logs detected corruption
  --restart-on-corruption - dm-verity restarts the kernel if corruption is detected

  If the options above are not specified, default behaviour for dm-verity remains.
  Default is that I/O operation fails with I/O error if corrupted block is detected.

  --ignore-zero-blocks - Instructs dm-verity to not verify blocks that are expected
   to contain zeroes and always return zeroes directly instead.

NOTE that these options could have serious security or functional impacts,
do not use them without assessing the risks!
2016-05-04 10:07:47 +02:00
Milan Broz
99a254f2f6 Fix dm-verity test typo. 2016-05-04 09:14:32 +02:00
Ondrej Kozina
1b7799cb1d dracut_90reencrypt: fix warns reported by static analysis
- moddir is assigned in parent script run by dracut (warning was
  silenced)

- fix defect wrt to assignement and making variable local on
  same line. The variable cwd was first assigned by subshell
  and later any error originating in subshell was masked by
  making the variable local (which returns always 'true')
2016-04-25 15:47:18 +02:00
Milan Broz
7eba57b4c0 Avoid possible divide-by-zero warnings. 2016-04-24 12:38:19 +02:00
Milan Broz
1f51cfcf57 Set devel version. 2016-04-24 12:13:30 +02:00
Milan Broz
683e4db48b Fix warnings reported by static analysis.
- ensure that strings are \0 terminated (most of this is already
handled on higher level anyway)

- fix resource leak in error path in tcrypt.c

- fix time of check/time of use race in sysfs path processing

- insruct Coverity scanner to ignore constant expression in random.c
(it is intented to stop compile-time misconfiguration of RNG that would be fatal)
2016-04-24 12:07:31 +02:00
Milan Broz
c2ddd48f50 Avoid tar archive warnings if tests are run as superuser. 2016-04-19 14:56:43 +02:00
Milan Broz
eb8ff73595 Merge branch 'VittGam/cryptsetup-patch-1' 2016-04-19 11:24:09 +02:00
Milan Broz
54c4b1656f Include sys/sysmacros.h if present.
Needed for major/minor definitions.

Thanks Mike Frysinger for pointing this out.
2016-04-19 10:57:45 +02:00
Milan Broz
1000b40a3a Link reencryption utility to uuid library.
(Fixes last patch.)
2016-04-19 10:22:26 +02:00
VittGam
e7e5354332 Fix off-by-one error in maximum keyfile size.
Allow keyfiles up to DEFAULT_KEYFILE_SIZE_MAXKB * 1024 bytes in size, and not that value minus one.

Signed-off-by: Vittorio Gambaletta <git-cryptsetup@vittgam.net>
2016-04-19 03:58:10 +00:00
Ondrej Kozina
b5365ba13d cryptsetup-reencrypt: enable resume of decryption
to enable resume of interrupted decryption user has
to pass uuid of the former luks device. That uuid is used
to resume the operation if temporary files LUKS-* still
exist.
2016-04-13 15:01:37 +02:00
Milan Broz
f2cdc6f5f4 Update po files. 2016-04-13 14:58:55 +02:00
Arno Wagner
a0c251c7cc sync to WIKI version 2016-03-23 15:53:02 +01:00
Milan Broz
d7a224e47a Disable DIRECT_IO for LUKS header with unaligned keyslots.
Fixes issue#287.

Such a header is very rare, it is not worth to do more detection here.
2016-03-23 13:44:37 +01:00
Milan Broz
6894701392 Merge branch 'athira-rajeev/cryptsetup-fix_device_block_size_fd' 2016-03-23 10:06:40 +01:00
Athira Rajeev
8e4e898ce5 Fix device_block_size_fd to return bsize correctly incase of files.
This patch is for issue #287

In the code for returning block size ( device_block_size_fd in lib/utils_device.c ),
always returns zero in case of files and device_read_test is not executed.

This patch is to fix device_block_size_fd to return block size correctly incase of files.

Signed-off-by: Athira Rajeevatrajeev@linux.vnet.ibm.com
2016-03-19 18:57:45 +05:30
Milan Broz
add8fb8fd2 Update README for 1.7.1. 2016-02-28 14:48:41 +01:00
Milan Broz
3807dbf2f3 Add 1.7.1 release notes. 2016-02-28 13:38:42 +01:00
Milan Broz
b5d1c9241c Fix align test for new scsi_debug defaults. 2016-02-28 11:12:40 +01:00
Ondrej Kozina
3e742452cd cryptsetup-reencrypt: harden checks for hdr backups removal
There're various situations where hdr backups together with log file
may get removed even when the hdr was already marked unusable. This
patch fixes the most sever case already reported and generaly tries
harder protecting the log file and both hdr backups.
2016-02-28 09:44:22 +01:00
Ondrej Kozina
d7b127549c cryptsetup-reencrypt: drop unreachable code path
MAKE_USABLE flag is never used in device_check()
2016-02-28 09:44:07 +01:00
Milan Broz
d841f97d44 Update po files. 2016-02-28 09:31:36 +01:00
Milan Broz
0c7d947d2d Update po files. 2016-02-23 17:41:55 +01:00
Milan Broz
05604b77ea Move README back. 2016-02-23 17:40:10 +01:00
Ondrej Kozina
2c072eb6b6 Clarify the reencrypt_keyslot= option 2016-02-21 18:48:49 +01:00
Milan Broz
080a9863c1 Temporarily rename README.txt (until GitLab updates markdown README preference handling) 2016-01-30 08:33:04 +01:00
Milan Broz
22f5760d47 Update TODO. 2016-01-26 15:17:02 +01:00
Milan Broz
4dc88e8ffb Fix kernel crypto backend to set key before accept call even for HMAC. 2016-01-04 14:19:50 +01:00
Milan Broz
229497871d Fix write_lseek prototype and avoid using void in arithmetic warning. 2016-01-03 16:05:17 +01:00
Milan Broz
9ce5dd1082 Fix cipher_null key setting in kernel crypto backend. 2016-01-03 11:03:47 +01:00
Ondrej Kozina
03d9db921b Fix hang in low level device-mapper code.
udev cookies should be set right in before the dm_task_run()
call otherwise we risk a hang while waiting for a cookie
associated with not yet executed dm task.

For example: failing to add table line (dm_task_add_target())
results in such hang.
2016-01-02 21:06:15 +01:00
Milan Broz
93ed401b7c Set skcipher key before accept() call in kernel crypto backend.
Also relax input errno checking to catch all errors.
2016-01-02 20:02:28 +01:00
Milan Broz
e34938f21d Allow special "-" (standard input) keyfile hangdling even for TCRYPT devices.
Fail if there are more keyfiles specified for non-TCRYPT device.

Fixes issue#269.
2016-01-01 19:15:06 +01:00
Milan Broz
87dbaa0bd7 Update sr.po. 2015-12-25 10:55:00 +01:00
Milan Broz
119627c8cf Merge branch 'misc/cryptsetup-add_gitignore' 2015-12-25 10:53:16 +01:00
Michael Scherer
973efb63ab Add a basic .gitignore in the project 2015-12-19 22:49:16 +01:00
Milan Broz
a1511e6a86 Merge branch 'louipc/cryptsetup-master' 2015-12-13 10:07:03 +01:00
Loui Chang
1d5663ddec Update version control history url
Signed-off-by: Loui Chang <louipc.ist@gmail.com>
2015-12-13 00:17:25 -05:00
Loui Chang
5e8d92146b Man page typo
Signed-off-by: Loui Chang <louipc.ist@gmail.com>
2015-12-13 00:17:01 -05:00
Ondrej Kozina
8e160562ee read_lseek_blockwise: use void pointer 2015-12-12 17:02:27 +01:00
Milan Broz
7033105ce7 Fix password handling from stdin (it cannot use offset). 2015-12-01 12:20:39 +01:00
Ondrej Kozina
091dfa0c26 Slight code style improvements for blockwise functions. 2015-12-01 10:57:04 +01:00
Ondrej Kozina
7fc006b63b Add interrupt safe read_lseek_blockwise function. 2015-12-01 10:52:42 +01:00
Ondrej Kozina
3e653ace3e Use const for header in LUKS_keyslot_area. 2015-12-01 10:52:25 +01:00
Ondrej Kozina
64f3df44ee Use read/write buffer functions where appropriate. 2015-12-01 10:51:56 +01:00
Ondrej Kozina
42ccddeff3 Add read_buffer and write_buffer functions.
Introduce functions for proper I/O handling. These functions
are able to deal with interrupts and partial I/O.
2015-12-01 10:44:02 +01:00
Ondrej Kozina
0435fbf2e5 Avoid write with zero size.
This can happen if write buffer size is smaller than underlying
block size and initial buffer is misaligned.

Also use size_t for buffer length variables.
2015-12-01 10:42:08 +01:00
Milan Broz
34ddae154e Fix luksKillSlot to not suppress provided password in batch mode.
Batch mode should enable no-query keyslot wipe but only if user
did not provided password or keyfile explicitely.

Fixes issue #265.

Signed-off-by: Milan Broz <gmazyland@gmail.com>
2015-11-22 12:50:34 +01:00
Milan Broz
8da37ce4b0 Update test (removal of get_last_error). 2015-11-20 09:18:58 +01:00
Milan Broz
9cbe74c2db Remove last error handling (error is logged). 2015-11-20 09:18:58 +01:00
Milan Broz
002ba59ff1 Simplify tools_get_key. 2015-11-20 09:18:31 +01:00
Milan Broz
d293de579a Fix various backward incompatibilities in password processing. 2015-11-20 09:18:31 +01:00
Milan Broz
4aea3b81ee Remove password callback interface.
This was a design mistake and should not be handled inside libcryptsetup code.
2015-11-20 09:18:31 +01:00
Milan Broz
5293f5aae1 Move terminal handling to tools wrapper. 2015-11-20 09:18:31 +01:00
Milan Broz
39698fa6b7 Remove terminal input from libcryptsetup API calls. 2015-11-20 09:18:31 +01:00
Milan Broz
e80f9b5c65 Remove key_from_file wrapper. 2015-11-20 09:18:31 +01:00
Milan Broz
f0986be2e3 Export crypt_keyfile_read(). 2015-11-20 09:18:31 +01:00
Milan Broz
252cdef110 Extract keyfile read from get_key wrapper. 2015-11-20 09:18:31 +01:00
Milan Broz
8ab9c9dc68 Update po files. 2015-11-20 08:55:36 +01:00
Milan Broz
a5363f184c Set devel version. 2015-11-03 13:41:14 +01:00
Milan Broz
e2637c5d49 Prepare version 1.7.0. 2015-11-03 13:32:24 +01:00
Milan Broz
4a72695241 Update README.md. 2015-11-03 13:15:42 +01:00
Milan Broz
af31af5e3d Add 1.7.0 Release notes. 2015-11-03 13:03:55 +01:00
Milan Broz
2aa0bb7eac Update LUKS default hash and kernel crypto api hash check. 2015-11-02 21:07:49 +01:00
Milan Broz
8ae62715a8 Update po files. 2015-11-02 21:07:20 +01:00
Arno Wagner
506ba27358 Synced to Wiki version with new markup stripper. 2015-11-02 20:37:47 +01:00
Milan Broz
4384e50578 Decrease iteration time for compat tests. 2015-10-29 12:44:15 +01:00
Milan Broz
1623ee71ab Remove experimental warning for reencrypt tool. 2015-10-29 12:16:37 +01:00
Milan Broz
f425d07ec7 Switch to sha256 and 2s iteration time for LUKS devices defaults.
Note that no longer using SHA1 is just to prevent situation
when it is no longer available on hardened systems, there is
no known security problem (finding collisions is not a problem for LUKS).

Increasing iteration time is in combination with PBKDF2 benchmark
fixes try to keep PBKDF2 iteration count still high enough and
also acceptable for users.

(Long term is to replace PBKDF2 algorithm with Password Hashing
Competiton winner.).

N.B. distributions can change these defaults in compilation time.
2015-10-29 12:08:14 +01:00
Ondrej Kozina
d260be02d4 tcrypt: fix potential memory leak on error path 2015-10-29 12:06:40 +01:00
Milan Broz
4609fd87d7 Fix PBKDF2 iteration benchmark for longer key sizes.
The previous PBKDF2 benchmark code did not take into account
output key length.
For SHA1 (with 160-bits output) and 256-bit keys (and longer)
it means that the final value was higher than it should be.

For other hash algorithms (like SHA256 or SHA512) it caused
that iteration count was smaller (in comparison to SHA1) than
expected for the requested time period.

This patch fixes the code to use key size for the formatted device
(or default LUKS key size if running in informational benchmark mode).

Thanks to A.Visconti, S.Bossi, A.Calo and H.Ragab
(http://www.club.di.unimi.it/) for point this out.
(Based on "What users should know about Full Disk Encryption
based on LUKS" paper to be presented on CANS2015).
2015-10-29 11:52:18 +01:00
Milan Broz
9e90d91446 Update da.po. 2015-10-12 15:16:25 +02:00
Milan Broz
7bbf0796b5 Merge branch 'glebfm/cryptsetup-passwdqc' 2015-10-12 14:17:55 +02:00
Milan Broz
fe3148f074 Tweak passwdqc use. 2015-10-12 14:15:03 +02:00
Gleb Fotengauer-Malinovskiy
5e9c27118e Add optional libpasswdqc support for new LUKS passwords
If password is entered through terminal (no keyfile specified) and
cryptsetup is compiled with --enable-passwdqc[=/etc/passwdqc.conf],
default system passwdqc settings are used to check password quality.
2015-10-08 17:30:26 +00:00
Milan Broz
c362ba9293 Update it.po. 2015-09-24 10:20:31 +02:00
Milan Broz
e97048dd32 Set devel version. 2015-09-08 15:17:16 +02:00
Milan Broz
5ea0ba61be Add release notes for 1.6.7 link. 2015-09-08 13:11:36 +02:00
Milan Broz
7ae863e380 Prepare version 1.6.8. 2015-09-08 12:53:48 +02:00
Milan Broz
f238e8c075 Add 1.6.8 release notes. 2015-09-08 12:26:54 +02:00
Milan Broz
7d9a14fd24 Fix some signed/unsigned compiler warnings. 2015-09-08 08:12:07 +02:00
Milan Broz
2f964d95d8 Fix benign warning in clang analysis output. 2015-09-08 07:54:03 +02:00
Milan Broz
00f419e5ea Add zh_CN.po. 2015-09-05 13:07:05 +02:00
Milan Broz
cc698dcde3 Update es.po. 2015-08-31 10:08:36 +02:00
Milan Broz
edced6cfed Update nl.po. 2015-08-30 12:58:33 +02:00
Milan Broz
4fb11976d2 Update po files. 2015-08-28 12:59:59 +02:00
Milan Broz
68ba5b2b36 Update fr.po. 2015-08-27 16:22:13 +02:00
Milan Broz
65fa22ff23 Override password quality check if used cipher is cipher_null. 2015-08-27 16:21:07 +02:00
Milan Broz
c25d81d2a1 Update po files. 2015-08-27 07:53:13 +02:00
Milan Broz
57d16a7a55 Fix misleading error messages in reencrypt. 2015-08-26 16:15:11 +02:00
Milan Broz
def397d0c8 Update libcryptsetup.h comments. 2015-08-26 16:10:10 +02:00
Milan Broz
7843415243 Move string_to_size to userspace tools. 2015-08-26 12:42:25 +02:00
Milan Broz
5a8b045bdd Properly support stdin "-" handling for luksAddKey. 2015-08-26 12:41:20 +02:00
Milan Broz
ab62f45d57 Use stdin and "-" file check wrapper. 2015-08-26 10:54:33 +02:00
Milan Broz
e521edd6ca Print cryptsetup library version in crypto init. 2015-08-26 10:42:47 +02:00
Milan Broz
3a0293a299 Do not link FIPS helper to cryptsetup anymore.
Just print info about FIPS mode in RNG init.
2015-08-26 10:36:49 +02:00
Milan Broz
8a4db1ad7b Ingore Whirlpool test instead of failing. 2015-08-26 10:35:38 +02:00
Milan Broz
1aba9ab444 Cryptsetup resize will try resize also underlying device.
If encrypted device is file-backed, resize should try to resize
underlying loop device as well.
2015-08-19 14:16:42 +02:00
Milan Broz
dfa2755aba If the null cipher is used, allow only empty password for LUKS.
The cipher_null is no-encryption, it can be used for testing
or temporarily when encrypting device (cryptsetup-reencrypt).

Accepting only empty password prevents situation when you replace
a LUKS header on an unlocking device with the faked header using
null cipher (and the same UUID).
Here a system could think that the device was properly unlocked
(with any entered password) and will try to use this unencrypted
partition instead.
(IOW it prevents situation when attacker intentionaly forces
an user to boot into dirrerent system just by LUKS header manipulation.)

Properly configured systems should have an additional integrity protection
in place here (LUKS here provides only confidentiality) but it is better
to not not allow this situation in the first place.
(Despite the fact that once you allow physical tampering of your system
it cannot be properly secured anymore.)
2015-07-02 08:21:19 +02:00
Milan Broz
6e82bdd9a5 Do not use real password when unlocking "fake" header on reecryption.
If reencrypt removes encryption (or adds encryption to not yet encrypted system)
there is a temporary header using null (none) cipher.
We do not need to pass through password when unlocking these devices.
2015-07-02 08:18:44 +02:00
Milan Broz
0dc245401f Allow to enter empty password through stdin pipe.
Also always use empty passsword when using null cipher in tests.
2015-07-02 08:18:12 +02:00
Milan Broz
a57f1b1b64 Silence repeated device removal in verity test. 2015-07-02 08:13:42 +02:00
Milan Broz
1a50fee1d0 Update po files. 2015-04-19 09:55:13 +02:00
Milan Broz
046e0e5280 Update README.md. 2015-03-23 21:20:56 +01:00
Milan Broz
656b55cd4b Set devel version. 2015-03-23 20:41:33 +01:00
Milan Broz
8d7af433d8 Update po files. 2015-03-23 20:40:04 +01:00
Milan Broz
dc3de39eb7 Include prototype for stat(). 2015-03-23 20:38:14 +01:00
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
Milan Broz
2a2444b961 Fix gcc signed/unsigned warning for key length.
And always use unsigned int declaration.
2013-03-31 11:24:26 +02:00
Milan Broz
2526ec92bd Update vi.po. 2013-03-26 21:19:03 +01:00
Milan Broz
9bddc52601 Update po files. 2013-03-24 23:36:26 +01:00
Milan Broz
1b96e93f91 Add 1.6.1 release notes. 2013-03-24 10:02:19 +01:00
Milan Broz
6127b6959f Update copyright year on changed files. 2013-03-24 09:05:33 +01:00
Milan Broz
330007beb2 Fix loop-AES keyfile parsing.
Loop-AES keyfile should be text keyfile,
properly check that keys are terminated and of the same length.

Fixes issue#153.
2013-03-23 18:10:46 +01:00
wagner
cbfd48d949 Fixed the buit instruction
Improved example
2013-03-23 16:00:58 +01:00
Milan Broz
f64064fe71 Fix deactivation of device when failed underlying node disappeared
If underlying device disappears (failed drive, removed flash drive etc)
cryptsetup cannot report LUKS parameters (header no longer available).

Fix return code of init_by name in this situation (crypt
context is NULL).

Report visible error if deactivation fails and device is still busy.

Fixes issue#149.
2013-03-17 20:54:04 +01:00
Milan Broz
f2521889c2 Deactivate whole device TCRYPT tree if context is NULL
API (unfortunately) supports NULL argument for crypt_deactivate,
with new chained TCRYPT devices it must deactivate all
chained devices as well.

Fixes issue#147.
2013-03-17 19:20:42 +01:00
Milan Broz
642d41970d Update nl.po. 2013-03-17 17:34:41 +01:00
Milan Broz
acd069fd27 Update de.po. 2013-03-10 16:09:00 +01:00
Milan Broz
c810b0514e Return EPERM instead EINVAL for too long TCRYPT passphrase. 2013-02-15 09:52:22 +01:00
Milan Broz
e600024908 Fix passphrase pool overflow for TCRYPT device id passphrase > pool size.
TCRYPT format limits passphrase length to max. 64 characters so simply error in this case.
2013-02-14 14:37:50 +01:00
Milan Broz
fd5b88449a Make passphrase prompts more consistent.
Also see http://code.google.com/p/cryptsetup/issues/detail?id=145
2013-02-11 14:53:49 +01:00
John Spencer
433758e4cb Fix missing headers
2 header inclusions were missing, one for PATH_MAX (limits.h) and one
for FD_ZERO, FD_SET, ... (sys/select.h)

on glibc, those headers are erroneusly (namespace pollution) pulled in
through other headers, so the author didnt notice.

Signed-Off-By: John Spencer <maillist-cryptsetup@barfooze.de>
2013-02-01 08:39:12 +01:00
wagner
5b8f762ab2 sync with wiki 2013-02-01 05:35:36 +01:00
Milan Broz
72db6e4de2 Do not support user uuid for plain & loopaes devices.
This function was not documented.
So now crypt_get_uuid() returns only on-disk UUID.
2013-01-22 16:20:09 +01:00
Milan Broz
2780ccdd62 Properly cleanup on interrupt in api-test. 2013-01-16 15:28:12 +01:00
Milan Broz
fdcabdfd28 Support test run in kernel FIPS mode. 2013-01-15 14:53:19 +01:00
Milan Broz
40b876f550 Set devel version. 2013-01-14 12:49:04 +01:00
Milan Broz
5cb5aeba36 Fix doxygen doc for libcryptsetup.h. 2013-01-14 00:22:50 +01:00
Milan Broz
6a1f49c244 Fix tcrypt test header. 2013-01-13 23:53:35 +01:00
Milan Broz
8613651f18 Use tabs in script. 2013-01-13 20:45:55 +01:00
Milan Broz
be4fea1928 Update po files. 2013-01-13 19:29:12 +01:00
Milan Broz
2c4542a590 Update bitops.h (stolen from util-linux:). 2013-01-13 19:28:36 +01:00
Milan Broz
3ce5359523 Update po files. 2013-01-11 13:03:05 +01:00
Milan Broz
fe4175b551 Fix some extended compile warning. 2013-01-10 17:26:19 +01:00
Milan Broz
310bf08568 Do not include pbkdf2 prototype in header if code is not compiled in. 2013-01-10 16:48:47 +01:00
Milan Broz
c040b4821d Fix null blocks in kernel backend. 2013-01-10 15:37:26 +01:00
Milan Broz
20149281a4 Fix tests to work with pwquality compiled in. 2013-01-10 15:34:11 +01:00
Milan Broz
87f1017f80 Allow to overwrite gcrypt PBKDF2 use for configure. 2013-01-09 18:46:38 +01:00
Milan Broz
664eff9e76 Prepare 1.6.0 release. 2013-01-09 13:23:34 +01:00
Milan Broz
36eb33bc86 Skip test for kernel wihtout autoclear flag. 2013-01-08 18:44:02 +01:00
Milan Broz
df8fb84723 Workaround api-test compilation on some very old systems. 2013-01-08 17:41:06 +01:00
Milan Broz
4de648a77a Properly specify cipher in tests. 2013-01-08 14:45:39 +01:00
Milan Broz
929dc47be4 Fix displaying of error messages for mising kernel features. 2013-01-08 14:19:31 +01:00
Milan Broz
5f222517f0 Change LUKS default cipher to aes-xts-plain64 (AES128-XTS). 2013-01-08 12:21:30 +01:00
Milan Broz
940690be82 Update po files. 2013-01-05 12:51:58 +01:00
Milan Broz
37ec687237 Properly initialize pkg-config in autoconf. 2013-01-05 12:51:21 +01:00
Milan Broz
ca75cd940f Prepare supported PBKDF2 implementation autodetection for gcrypt. 2013-01-03 14:11:52 +01:00
Milan Broz
607fd2b977 Update pl.po. 2013-01-02 22:46:32 +01:00
Milan Broz
e689eb4a0a Fix benchmark alignment (wider columns). 2013-01-02 21:53:49 +01:00
Milan Broz
b6a63c8d5c Update po files. 2013-01-02 13:25:07 +01:00
Yuri Chornoivan
209f1db984 Fix typo 2012-12-31 18:33:33 +01:00
Milan Broz
dd3fddb0e9 Fix autogen script to handle configure.ac. 2012-12-30 18:39:48 +01:00
Dave Reisner
ab080ab544 build: use AM_CPPFLAGS instead of INCLUDES
The latter is marked as deprecated as of automake 1.12.4:

warning: 'INCLUDES' is the old name for 'AM_CPPFLAGS' (or '*_CPPFLAGS')
2012-12-30 18:36:46 +01:00
Dave Reisner
d1466f23ed build: rename configure.in to configure.ac
With automake 1.13, configure.in is no longer honored.
2012-12-30 18:36:12 +01:00
Milan Broz
918c1a6de1 Allow repair of 512bits key header. 2012-12-30 18:32:10 +01:00
Milan Broz
37d52bf01b Require lsblk for tcrypt test. 2012-12-30 12:35:35 +01:00
Milan Broz
46de69d0e6 Add kernel userspace header detection.
Add --disable-kernel_crypto to allow compilation with old kernel.
2012-12-30 12:28:30 +01:00
Milan Broz
0946c704bf Fix status of device if path argument is used. Fix double path prefix for non-existent device path. 2012-12-30 11:48:30 +01:00
wagner
90853cc3ab added warning that previously used containers should
be wiped before use as LUKS or plain dm-crypt containers.
2012-12-30 11:39:08 +01:00
Milan Broz
521184ba8b Fix typos in changelog. 2012-12-29 22:37:21 +01:00
Milan Broz
05da2ed2c2 Skip TCRYPT KDF if hash is not available. 2012-12-29 20:23:52 +01:00
Milan Broz
d4ecc8e24a Add note about pbkdf2 benchmark. 2012-12-29 17:40:46 +01:00
Milan Broz
6ae0d725d3 Prepare version 1.6.0-rc1. 2012-12-29 17:21:58 +01:00
Milan Broz
6190ad928d Support device/file images if O_DIRECT cannot be used (1.5.1).
On some filesystems (like tmpfs) O_DIRECT cannot be used.
So just try to open device without O_DIRECT in the second try.
2012-12-29 15:33:20 +01:00
Arno Wagner
0451e1c23a Added wipefs as option for fast FS removal in section 2.1 2012-12-29 12:49:16 +01:00
Milan Broz
7eccb7ff50 Change License for sub-libraries from GPLv2 only to LGPLv2.1+ ("or any later")
This includes crypto, loopaes, tcrypt handling code I have written myself
and verity code written originally by Mikulas Patocka and modified by me,
copyright by Red Hat.

Other part of library have to stay GPLv2+ only for now
(no agreement from all authors).
2012-12-29 11:47:28 +01:00
Milan Broz
29f21208a0 Change License from GPLv2 only to GPLv2+ ("or any later").
Agreed by all copyright authors.
2012-12-29 11:33:54 +01:00
Milan Broz
099a2b9d17 Add TCRYPT password search example. 2012-12-29 11:12:29 +01:00
Milan Broz
3b4424226f Fix non-translated messages. 2012-12-29 11:11:23 +01:00
wagner
f4a582e3e2 Synced with WIKI version 2012-12-29 07:58:00 +01:00
Milan Broz
e4c4049741 Add basic support for system TCRYPT device.
Rename option hidden to tcrypt-hidden.
2012-12-22 22:34:09 +01:00
Milan Broz
83f02e6682 Add copyright line for files I have written or modified. 2012-12-21 16:40:33 +01:00
Milan Broz
069ba220d2 Add crypt_keyslot_change_by_passphrase() api test. 2012-12-21 16:27:55 +01:00
Milan Broz
54dab83a9e Update fi.po (1.5.1). 2012-12-21 15:16:04 +01:00
Milan Broz
caf1f06bcb Update TODO. 2012-12-21 15:13:36 +01:00
Milan Broz
c7dde8f0e8 Do not maintain ChangeLog anymore, see git log. 2012-12-21 15:08:35 +01:00
Milan Broz
546f0fd0bc Add utils_password.c to po files list. 2012-12-19 18:54:00 +01:00
Milan Broz
9163bcef4b Fix static build with pwquality (until it provides proper pkgconfig). 2012-12-19 18:49:50 +01:00
Milan Broz
e030e3bd15 Add optional libpwquality support for new LUKS passwords.
If password is entered through terminal (no keyfile specified)
and cryptsetup is compiled with --enable-pwquality, default
system pwquality settings are used to check password quality.
2012-12-19 17:25:11 +01:00
Milan Broz
c950cf265f Prepare cryptsetup functions for pwquality check. 2012-12-19 15:27:29 +01:00
Milan Broz
9ae7b7d1be Fix regression in header backup (1.5.1).
Access to backup file must handle write to regular files too.
2012-12-19 13:19:05 +01:00
Milan Broz
0bd8b9823a Fix time of check/use Coverity report in cryptsetup-reencrypt. 2012-12-17 16:10:39 +01:00
Milan Broz
b86c5a93b3 Fix time of check/use Coverity report in veritysetup. 2012-12-17 15:50:42 +01:00
Milan Broz
1e3ba81613 Fix time of check/use Coverity report (and ignore another) in loop/wipe utils. 2012-12-17 15:35:33 +01:00
Milan Broz
a83cc1dbf4 Fix time of check/use Coverity report (and ignore another) in device utils. 2012-12-17 15:19:57 +01:00
Milan Broz
94d732b411 Do not use stat for backup commands. 2012-12-17 14:05:45 +01:00
Milan Broz
50be50c521 Add fixme for ETA calculation. 2012-12-17 09:54:10 +01:00
Milan Broz
b16feb6853 Add verbose messages during reencryption to avoid confusion. 2012-12-14 14:48:36 +01:00
Milan Broz
32c578729c Handle signals in tool context. 2012-12-11 19:01:46 +01:00
Milan Broz
710aad20d3 Move signal handling into common utils code. 2012-12-11 15:40:42 +01:00
Milan Broz
d742e01a32 Remove signal handling from LUKS keyencryption and simplify code. 2012-12-11 15:39:47 +01:00
Milan Broz
50d5cfa8bc Get page size should never fail (in the works case it fails later with wrong alignment). 2012-12-10 17:47:06 +01:00
Milan Broz
80d21c039e Fix some problems found by Coverity scan. 2012-12-10 17:28:52 +01:00
Milan Broz
549ab64358 TCRYPT: properly wipe all buffers; use prefix for all functions. 2012-12-10 16:36:22 +01:00
Milan Broz
e8d09733d4 Require params for crypt_load & TCRYPT type. 2012-12-08 01:31:38 +01:00
Milan Broz
5f05949425 Merge branch 'master' of https://code.google.com/p/cryptsetup 2012-12-07 15:57:00 +01:00
Milan Broz
5dc654433c Disallow header restore if context is nonLUKS device. 2012-12-07 15:55:56 +01:00
Milan Broz
05af3a3383 Move change key into library (add crypt_keyslot_change_by_passphrase).
This change is useful mainly in FIPS mode, where we cannot
extract volume key directly from libcryptsetup.
2012-12-07 15:33:47 +01:00
wagner
2eab3e6402 synced with web-version 2012-12-06 16:24:16 +01:00
Milan Broz
16c82312f3 Add man page description for KDF benchmark. 2012-12-05 20:43:06 +01:00
Milan Broz
bd494d23c5 Add PBKDF2 benchmark. 2012-12-05 20:35:42 +01:00
Milan Broz
95daec798b Use union instead of replicated attributes. 2012-12-03 16:17:43 +01:00
Milan Broz
ef21960600 Document new basic commands open/close (and old syntax aliases). 2012-12-03 13:23:14 +01:00
Milan Broz
a4585423fd Remove some gcc extra warnings (signed/unsigned problems etc). 2012-12-02 23:13:59 +01:00
Milan Broz
5aef0809d4 Add TCRYPT documentation, 2012-12-02 21:32:49 +01:00
Milan Broz
4d9c7d39f4 Add master key dump option for tcryptDump. 2012-12-02 20:27:45 +01:00
Milan Broz
6a532cb1b5 cryptsetup: remove useless arg for action functions. 2012-12-02 20:11:10 +01:00
Milan Broz
d93e4212cd Add new commands open/close and make aliases.
open aliases : create, plainOpen,  luksOpen,  loopaesOpen,  tcryptOpen
close aliases: remove, plainClose, luksClose, loopaesClose, tcryptClose
2012-12-02 20:03:05 +01:00
Milan Broz
72c111bac4 Fix (stupid) crc32 keyfile endianess bug. 2012-12-01 14:32:01 +01:00
Milan Broz
d05f020d5a Add keyfiles tcrypt test. 2012-12-01 13:43:59 +01:00
Milan Broz
dde57477fc And skip tcrypt api test if there is no af_alf kernel interface. 2012-11-30 18:53:32 +01:00
Milan Broz
ffb6ecc488 Add TCRYPT api test, fix some minor problems found. 2012-11-30 18:41:10 +01:00
Milan Broz
6123541d80 Add missing pbkdf check file. 2012-11-30 17:05:03 +01:00
Milan Broz
e510dd9c60 Add sys/types.h for loop wrapper (required on new systems). 2012-11-30 15:08:39 +01:00
Milan Broz
0461d9e822 Better tcrypt test options. 2012-11-30 15:03:01 +01:00
Milan Broz
4f7262aa96 And fix previous comment once more... :) 2012-11-30 13:52:03 +01:00
Milan Broz
eac953c6e4 Fix skcipher failure handling. 2012-11-30 13:37:14 +01:00
Milan Broz
d7fc953fa2 Handle kernel crypto api init failure better. 2012-11-29 18:01:02 +01:00
Milan Broz
f35f34b909 Fix po files. 2012-11-27 19:18:05 +01:00
Milan Broz
34a2176689 TCRYPT: add simple test and image archive. 2012-11-27 19:08:10 +01:00
Milan Broz
21756a1969 TCRYPT: fix activation and hidden device offsets. 2012-11-27 17:13:53 +01:00
Milan Broz
17a8e85cb8 TCRYPT: add backup header option. 2012-11-26 13:15:08 +01:00
Milan Broz
1b191e14d0 Remove test dir during cleanup. 2012-11-25 23:43:14 +01:00
Milan Broz
98db3bc0bf Fix blockwise read/write for end writes near end of device.
Ignore setpriority failure (will be remoced later anyway).
2012-11-25 22:57:32 +01:00
Milan Broz
46cf1c6ce0 TCRYPT: simplify code, support blowfish chains for header 2012-11-25 22:52:47 +01:00
Milan Broz
fbf4c5daf3 Remove trailing spaces from manpage, add usage and help option. 2012-11-23 17:31:41 +01:00
Milan Broz
c81260b3c3 TCRYPT: add dump command 2012-11-23 17:10:57 +01:00
Milan Broz
8d69e19ac1 TCRYPT: support crypt_volume_key_get 2012-11-23 15:20:46 +01:00
Milan Broz
6ab93841e9 TCRYPT: show proper device in status for chained mode 2012-11-23 13:46:23 +01:00
Milan Broz
52cbbdaf38 TCRYPT: move all header handling into library.
Add warning about unsupported modes.
2012-11-23 13:01:43 +01:00
Milan Broz
0996a43dbb TCRYPT: parse cipher chain on init. 2012-11-22 17:28:03 +01:00
Milan Broz
3faaa8b227 TCRYPT: support proper device removal 2012-11-22 14:19:43 +01:00
Daniel Kahn Gillmor
c26bb0f38a make default LUKS PBKDF2 iteration time configurable 2012-11-20 21:23:05 +01:00
Milan Broz
911ffe81f0 TCRYPT: implement (most of) legacy modes support. 2012-11-19 21:25:57 +01:00
Milan Broz
ecf993834c TCRYPT: support keyfiles 2012-11-19 21:25:26 +01:00
Milan Broz
3cbb43a73a Add basic TCRYPT library. 2012-11-19 21:24:59 +01:00
Milan Broz
db97d3d8c8 Add simple cipher benchmarking. 2012-11-19 21:22:43 +01:00
Milan Broz
7199662fbb Add kernel skcipher backend. 2012-11-19 21:21:40 +01:00
Milan Broz
a14a2137e7 Add CRC32 implementation. 2012-11-19 21:18:18 +01:00
Milan Broz
16ac703008 Move PBKDF2 into crypto backend wrapper.
Implement new KDF bechmark check.
Use internal openssl kdf (and prepare gcrypt one).
2012-11-19 21:17:55 +01:00
Milan Broz
24e2ee5812 Add devel version. 2012-10-16 22:35:14 +02:00
Milan Broz
b0d8815dab Relnote addition. 2012-10-16 22:00:19 +02:00
Milan Broz
831a0af508 Update some po files. 2012-10-14 21:11:20 +02:00
Milan Broz
488202feee Version 1.5.1. 2012-10-12 14:18:56 +02:00
Milan Broz
193402ad41 Check read & seek return codes, use uint64 offset.
Signed-off-by: Arno Wagner <wagner.arno@gmail.com>
Signed-off-by: Milan Broz <gmazyland@gmail.com>
2012-10-12 13:18:22 +02:00
Arno Wagner
1b86b7cb4b added keyslot checker Redesigned to only use public definitions
Signed-off-by: Arno Wagner <wagner.arno@gmail.com>
2012-10-11 18:07:35 +02:00
Milan Broz
e5dc991ffd Increase library and package version. 2012-09-19 15:57:56 +02:00
Milan Broz
89e09afdf6 Fix some problems found by Coverity static analysis. 2012-09-19 13:58:00 +02:00
Arno Wagner
bec7fcb14a synced with wiki 2012-09-18 23:30:38 +02:00
Milan Broz
f45d4d0755 Add crypt_keyslot_area() API call.
Useful if you want to analyze/wipe area of disk used for keyslot
from external tool.
2012-09-11 11:59:06 +02:00
Arno Wagner
64558a57e3 fixed typeo 94 -> 95 printable ASCII chars 2012-09-09 02:51:58 +02:00
Milan Broz
29e4414c35 Fix luksHeaderBackup for v1.0 (very old) headers and add some basic test. 2012-08-30 15:39:30 +02:00
Milan Broz
c2e12440d2 Add some offset/keyslot offset checks. 2012-08-30 14:08:34 +02:00
Milan Broz
1685aa5978 Proper handle error in device block get. 2012-08-28 13:30:17 +02:00
Milan Broz
6874f564c1 Remove unused includes. 2012-08-28 13:16:03 +02:00
Milan Broz
4882f70040 Replace round_up macro with function. 2012-08-28 13:11:02 +02:00
Milan Broz
1aca317c77 Move LUKS AF data sector alignment to AF helper function. 2012-08-27 16:52:19 +02:00
Milan Broz
af2730fe2a Always zero memory in crypt_safe_alloc. 2012-08-27 16:28:00 +02:00
Milan Broz
a6d64d1d44 Use AF_split_size() to calculate split data size. 2012-08-27 15:26:22 +02:00
Milan Broz
d15dd89bb7 Get rid of confusing LUKS_PHDR_SIZE macro. 2012-08-27 14:45:21 +02:00
Dave Reisner
961682aa6b lib/utils_crypt: optimize seek to keyfile-offset
Avoid using unbuffered reads when "seeking" to a keyfile offset. This is
abysmally slow when the key is hidden at the end of a large device.
Instead, try to actually call lseek, falling back on reading in chunks
of BUFSIZ bytes until the desired offset is reached.

Command line:

  cryptsetup luksOpen /dev/vdc1 home \
      --keyfile /dev/vdd --keyfile-size 4096 --keyfile-offset 123456789

Before:

  real   0m25.589s
  user   0m7.030s
  sys    0m18.479s

After:

  real   0m4.464s
  user   0m4.253s
  sys    0m0.157s
2012-08-27 13:10:00 +02:00
Milan Broz
2f37cfe569 Do not scan rotational flag for non-block devices / file images. 2012-08-27 12:42:15 +02:00
Arno Wagner
5b5c6dccc0 added prominent note to use LUKS (not plain dm-crypt) unless
understanding the crypto well.
2012-08-24 19:00:47 +02:00
Arno Wagner
d58a5c8cae synced with wiki 2012-08-24 17:02:59 +02:00
Milan Broz
1d5788f779 Set context for DM log for all DM backend entries.
Try to handle error if run as non-root user better.
2012-08-14 19:17:13 +02:00
Milan Broz
97224b072a Add context to DM helpers.
(To be used later.)
2012-08-14 16:25:21 +02:00
Milan Broz
15442c1747 Modprobe kernel modules early in api-test. 2012-08-14 15:54:31 +02:00
Milan Broz
ff9db165eb Use common utils_tools.c for all tools.
Unify tool environment and deduplicate code.
2012-08-13 18:31:26 +02:00
Milan Broz
48332d248f Remove debug line. 2012-08-13 17:16:37 +02:00
Milan Broz
07815c24cd Print better error message if device is read-only etc. 2012-08-13 16:54:41 +02:00
Milan Broz
49b018c765 Create hash image if doesn't exist in veritysetup format. 2012-08-12 23:42:41 +02:00
Milan Broz
65f975655c New device access backend.
Allocate loop device late (only when real block device needed).
Rework underlying device/file access functions.
Move all device (and ioctl) access to utils_device.c.

Allows using file where appropriate without allocation loop device.
2012-08-12 22:00:17 +02:00
Milan Broz
0c1efd1f8a Fix dracut example. 2012-08-03 15:27:59 +02:00
Arno Wagner
bc1cbd8065 update to current WIKI version 2012-08-02 15:58:36 +02:00
Milan Broz
50a2d89add Fix some issues in dict example. 2012-08-02 12:51:28 +02:00
Milan Broz
99643a82ae Be sure verity module is loaded in test. 2012-07-23 15:00:28 +02:00
Milan Broz
fcc35f459c Better define comment lines for for dict example. 2012-07-20 15:36:16 +02:00
Milan Broz
a5aa91ed99 Clear dict example a little bit. 2012-07-20 14:51:51 +02:00
Milan Broz
d83b872c55 Add example of dictionary search. 2012-07-20 00:15:20 +02:00
Milan Broz
8ec2651ad7 Use fixed dir (old dracut lib...) 2012-07-12 21:15:37 +02:00
Milan Broz
53e269c5f1 Add key option to dracut example. 2012-07-12 19:21:22 +02:00
Milan Broz
8b8e206c07 Skip multikey if not supported (e.g. FIPS mode - md5 for IV not available). 2012-07-12 12:53:26 +02:00
Milan Broz
e0562f9708 Version 1.5.0. 2012-07-10 20:20:27 +02:00
Milan Broz
6462ee55d3 Update example files for new dracut. 2012-07-10 19:59:44 +02:00
Milan Broz
91ba5742c6 Update release notes. 2012-07-10 13:09:35 +02:00
Milan Broz
667e469659 Version 1.5.0. 2012-07-10 12:54:22 +02:00
Milan Broz
37cecb5a5b Add example of dracut module for reencryption. 2012-07-10 12:53:32 +02:00
Milan Broz
a47ebccf9a Add module load to test. 2012-07-10 10:15:40 +02:00
Milan Broz
584d5b8d65 Fix library name for FIPS check. 2012-07-09 19:30:25 +02:00
Milan Broz
8eef5bde4f Add link to upstream tracker. 2012-07-09 19:04:39 +02:00
Milan Broz
3532be48c7 Fix libcryptsetup.h docs for verity type. 2012-07-09 18:47:05 +02:00
Milan Broz
5f7309bfa0 Add some verity api test.
Fix set_data_device bug it uncovered.
Fix api-test for nonFIPS hash.
2012-07-09 18:09:51 +02:00
Milan Broz
fa4a246744 Remove utils_debug from pot. 2012-07-08 20:29:30 +02:00
Milan Broz
321386db88 Fix password length unit in configure. 2012-06-28 10:16:49 +02:00
Milan Broz
b99b4825a2 Use resume instead of restart. 2012-06-27 21:28:11 +02:00
Petr Písař
9b455125e9 Pass help text to popt already translated
popt does not process the text registered by poptSetOtherOptionHelp()
through gettext on its own. Application must do it.
2012-06-26 21:26:04 +02:00
Milan Broz
adcb9bfb7d Update po files. 2012-06-26 14:33:08 +02:00
Milan Broz
4abfd38169 Remove open device debugging feature (no longer needed). 2012-06-26 12:55:14 +02:00
Milan Broz
b684fffdaf Switch to use unit suffix for --reduce-device-size option. 2012-06-25 16:06:43 +02:00
Milan Broz
fb3b62ca02 Add --device-size option for reencryption tool. 2012-06-25 15:34:11 +02:00
Milan Broz
c469e458b7 Version 1.5.0-rc2. 2012-06-20 11:29:46 +02:00
Milan Broz
be5473f242 Fix verity test.
(Writing just one byte from urandom means, that there is still
high probability the byte will be the same and it will cause
no data corruption :-)
2012-06-19 18:40:38 +02:00
Milan Broz
527c0fe4f9 Rename without_activation to test_passphrase. 2012-06-19 17:37:31 +02:00
Milan Broz
0ec4d4c9cf Add directio to reenc test. 2012-06-19 16:04:20 +02:00
Milan Broz
28f860def2 Remove old dm-verity superblock handling. 2012-06-19 15:57:05 +02:00
Milan Broz
42abcc0fac Remove some redundant brackets. 2012-06-19 15:49:56 +02:00
Milan Broz
a38fcafcff Add --without-activation option for luksOpen (check passphrase only). 2012-06-19 15:36:19 +02:00
Milan Broz
c4a533c3d5 Fix luks-header-from-active to not require header on device and add UUID setting. 2012-06-19 14:43:10 +02:00
Milan Broz
96f31a2cff Remove dubious compilation warning. 2012-06-19 12:49:16 +02:00
Milan Broz
8f4fb9303f Fix man page makefile. 2012-06-19 10:33:48 +02:00
Milan Broz
336be2da96 Update po files. 2012-06-19 09:56:55 +02:00
Milan Broz
e129bffce9 Remove redundant condition in overflow test. 2012-06-18 17:12:41 +02:00
Milan Broz
a9d9a2ad44 Fix hex_to_bytes and add it to common utils. 2012-06-18 17:09:48 +02:00
Milan Broz
c0a5293435 Introduce cryptsetup-reencrypt - experimental offline LUKS reencryption tool. 2012-06-18 16:06:14 +02:00
Milan Broz
b9ae00956d Add simple examples to man page. 2012-06-18 15:52:36 +02:00
Milan Broz
e37016bf64 Fix malloc of 0 size. 2012-06-18 15:03:47 +02:00
Milan Broz
104c7d6c4f If in progress, just use normal path (check passphrase). 2012-06-18 14:52:35 +02:00
Milan Broz
b773823a1b Add ability to encrypt plain device. 2012-06-18 14:29:22 +02:00
Milan Broz
0894814148 Add some simple reenc test. 2012-06-17 21:59:29 +02:00
Milan Broz
cc948df1dd Sanity check for some options. 2012-06-17 19:30:48 +02:00
Milan Broz
35e3660c61 Add possibility to change key size (optionally by shrinking device). 2012-06-17 15:09:34 +02:00
Milan Broz
28c6901de1 Do not touch new LUKS headers. 2012-06-17 12:44:53 +02:00
Milan Broz
dc067454c1 Rename to crypsetup-reencrypt.
Add man page.
Add configure option.
2012-06-17 12:12:17 +02:00
Milan Broz
32c2bd4222 Check device exclusively. 2012-06-17 02:11:41 +02:00
Milan Broz
cd4ea1c348 Fix signit if reencryption not yet started. 2012-06-17 00:43:45 +02:00
Milan Broz
8984e47414 Use ETA in progress report. 2012-06-17 00:06:30 +02:00
Milan Broz
491e79db4c Add fsync option. 2012-06-16 21:49:45 +02:00
Milan Broz
8a1a0547a8 Fix directio aligned buffer. 2012-06-16 21:13:47 +02:00
Milan Broz
9d47892342 Fix directio (again). 2012-06-16 20:59:21 +02:00
Milan Broz
32cfb1ca25 Fix some compile warnings. 2012-06-16 18:49:37 +02:00
Milan Broz
810aef34ca Do not use global context. 2012-06-16 18:28:49 +02:00
Milan Broz
b23b3c4dfe Fix verbose messages. 2012-06-16 18:10:01 +02:00
Milan Broz
b9d99a1626 Change log manipulation, print log always. 2012-06-16 17:07:29 +02:00
Milan Broz
496a07ed4c Properly support more keyslots.
If key file specified, use only one keyslot.
2012-06-16 01:23:42 +02:00
Milan Broz
fbba97552e Remove new file header option for now. 2012-06-15 15:16:49 +02:00
Milan Broz
0cefe2d107 Create smaller header device. 2012-06-15 15:03:09 +02:00
Milan Broz
768426ad99 Handle interrupts & restart. 2012-06-15 13:51:16 +02:00
Milan Broz
5a48ff5eb2 Fix backward roiutine on 32bit. 2012-06-14 16:13:59 +02:00
Milan Broz
96c8c7ba56 Print better progress status. 2012-06-14 14:58:36 +02:00
Milan Broz
29c2281ab2 Add some simple timer.
Do not use direct-io by default.
2012-06-13 13:52:51 +02:00
Milan Broz
0d70651c5a Merge branch 'reenc' of https://code.google.com/p/cryptsetup into reenc 2012-06-12 18:05:00 +02:00
Milan Broz
b1fb2532e0 Fix hex string conversion length. 2012-06-12 17:55:21 +02:00
Milan Broz
05b695d516 Merge branch 'reenc' of https://code.google.com/p/cryptsetup into reenc
Conflicts:
	src/Makefile.am
2012-06-12 13:26:09 +02:00
Milan Broz
44c9b2fc68 Comment out some temp code. 2012-06-12 13:24:39 +02:00
Milan Broz
018205a9a0 Implement forward/backward reencryption. 2012-06-12 13:24:38 +02:00
Milan Broz
c333108c61 Activate devices privately. 2012-06-12 13:24:38 +02:00
Milan Broz
2fcb521c77 Add experimental LUKS offline reencryption utility. 2012-06-12 13:24:38 +02:00
Milan Broz
0dc87d45a8 Version 1.5.0-rc1. 2012-06-11 14:56:17 +02:00
Milan Broz
03dc073f2b Use block sizes in superblock in 32bit. 2012-06-11 13:42:53 +02:00
Milan Broz
b402f087d7 Verity salt size is really uint16 in sb and uint32 internally. 2012-06-11 13:30:41 +02:00
Milan Broz
656fbde7d1 Fix inclusion of bitops.h. 2012-06-11 12:55:01 +02:00
Milan Broz
a89e6c0ca6 Introduce veritysetup for dm-verity target management. 2012-06-11 12:47:24 +02:00
Milan Broz
d380da7a32 Merge branch 'veritysetup' 2012-06-11 12:44:34 +02:00
Milan Broz
0de4b65ba6 Rename hash-start to hash-offset and switch to use bytes units. 2012-06-11 12:35:18 +02:00
Milan Broz
5c7954a0c7 Require only up to last keyslot area for header device (ignore data offset).
Fix header backup and restore to work on files with large data offset.
2012-06-11 12:20:19 +02:00
Milan Broz
62f334cfa5 Check various number limits. 2012-06-11 00:09:15 +02:00
Milan Broz
6d2c15ea79 Avoid some clang warnings. 2012-06-10 19:55:43 +02:00
Milan Broz
4b8f91d0d9 Remove some compilation warnings. 2012-06-10 18:56:04 +02:00
Milan Broz
c364290be9 Silence sb warning for now. 2012-06-10 18:20:59 +02:00
Milan Broz
a14aab5df7 Loop is automatically allocated in crypt_set_data_device(). 2012-06-10 17:59:14 +02:00
Arno Wagner
47c5b5ed06 Merge branch 'master' of https://code.google.com/p/cryptsetup 2012-06-10 17:59:00 +02:00
Arno Wagner
0eae181092 synced with wiki version 2012-06-10 17:57:22 +02:00
Milan Broz
1cbc53e8ee Get rid of backing_file in struct. 2012-06-10 17:19:08 +02:00
Milan Broz
7535fdb31b Fix man page. 2012-06-10 13:08:19 +02:00
Milan Broz
de9393879e Add more verity debug messages. 2012-06-10 12:58:18 +02:00
Milan Broz
db51a343de Move defines from header. 2012-06-09 23:26:45 +02:00
Milan Broz
e2375c8368 Add verity uuid specification. 2012-06-09 23:20:43 +02:00
Milan Broz
697c6c9324 Prepare new superblock format. 2012-06-09 22:02:06 +02:00
Milan Broz
6d07be898d Enhance status of active device. 2012-06-09 18:28:00 +02:00
Milan Broz
ade21e6c60 Support empty salt for verity, support no superblock. 2012-06-09 13:12:04 +02:00
Milan Broz
fcf5b414d6 Remove redundant flags. 2012-06-09 11:54:10 +02:00
Milan Broz
92d1bebdac Fix missing lines. 2012-06-08 22:47:45 +02:00
Milan Broz
39a5408e98 Add man page. 2012-06-08 22:40:57 +02:00
Milan Broz
937f969cc4 Add verity sources to translation. 2012-06-08 21:58:16 +02:00
Milan Broz
f4101d0f8b Use action names in veritysetup (similar to cryptsetup). 2012-06-08 21:51:58 +02:00
Milan Broz
ce2218ed65 Support init_by_name for verity. 2012-06-08 16:38:26 +02:00
Milan Broz
cdae1b4c60 Move verity_sb definition to private file. 2012-06-08 10:14:54 +02:00
Milan Broz
c4b16923bb Unify dm backend for crypt/verity. 2012-06-08 10:12:12 +02:00
Milan Broz
b016e65daa Use union in dm (crypt/verity) query structure. 2012-06-08 08:58:35 +02:00
Milan Broz
c35839afbc Use configure for defaults. 2012-06-07 15:19:19 +02:00
Milan Broz
cd8826618d Warn if block exceeds page size. 2012-06-07 15:09:58 +02:00
Milan Broz
ab0f7346bc Fix some strings, fix sb_offset. 2012-06-07 14:51:42 +02:00
Milan Broz
9fb8b816c5 Change int types. 2012-06-07 14:29:43 +02:00
Milan Broz
0e79728f86 Detect dm-verity in kernel. 2012-06-07 12:32:06 +02:00
Milan Broz
4b0b82adc5 Rewrite veritysetup to use libcryptsetup. 2012-06-07 00:18:49 +02:00
Milan Broz
850799802b Add simple veritysetup test. 2012-06-03 11:14:15 +02:00
Milan Broz
ed1b59fd25 Increase devel version. 2012-05-31 15:12:24 +02:00
Milan Broz
fa98297547 Merge branch 'master' into veritysetup 2012-05-31 15:11:00 +02:00
Milan Broz
9ae7e122ac Add veritysetup. 2012-05-28 16:04:07 +02:00
Milan Broz
624157ef7b Comment out some temp code. 2012-05-23 09:50:34 +02:00
Milan Broz
5c49268c47 Implement forward/backward reencryption. 2012-05-22 23:28:38 +02:00
Milan Broz
7df1d83ebb Activate devices privately. 2012-05-22 23:27:40 +02:00
Milan Broz
555d5f6e97 Add experimental LUKS offline reencryption utility. 2012-05-22 23:27:40 +02:00
252 changed files with 72094 additions and 13149 deletions

40
.gitignore vendored Normal file
View File

@@ -0,0 +1,40 @@
po/*gmo
*~
Makefile
Makefile.in
Makefile.in.in
*.lo
*.la
*.o
.deps/
.libs/
src/cryptsetup
src/veritysetup
aclocal.m4
autom4te.cache/
compile
config.guess
config.h
config.h.in
config.log
config.rpath
config.status
config.sub
configure
depcomp
install-sh
lib/libcryptsetup.pc
libtool
ltmain.sh
m4/
missing
po/Makevars.template
po/POTFILES
po/Rules-quot
po/*.pot
po/*.header
po/*.sed
po/*.sin
po/stamp-po
stamp-h1

151
.travis-functions.sh Normal file
View File

@@ -0,0 +1,151 @@
#!/bin/bash
#
# .travis-functions.sh:
# - helper functions to be sourced from .travis.yml
# - designed to respect travis' environment but testing locally is possible
# - modified copy from util-linux project
#
if [ ! -f "configure.ac" ]; then
echo ".travis-functions.sh must be sourced from source dir" >&2
return 1 || exit 1
fi
## some config settings
# travis docs say we get 1.5 CPUs
MAKE="make -j2"
DUMP_CONFIG_LOG="short"
export TS_OPT_parsable="yes"
function configure_travis
{
./configure "$@"
err=$?
if [ "$DUMP_CONFIG_LOG" = "short" ]; then
grep -B1 -A10000 "^## Output variables" config.log | grep -v "_FALSE="
elif [ "$DUMP_CONFIG_LOG" = "full" ]; then
cat config.log
fi
return $err
}
function check_nonroot
{
local cfg_opts="$1"
[ -z "$cfg_opts" ] && return
configure_travis \
--enable-python \
--enable-cryptsetup-reencrypt \
"$cfg_opts" \
|| return
$MAKE || return
sudo modprobe dm-crypt
sudo modprobe dm-verity
sudo modprobe dm-integrity
uname -a
sudo dmsetup version
sudo dmsetup targets
make check || return
#sudo $MAKE install || return
}
function check_root
{
local cfg_opts="$1"
[ -z "$cfg_opts" ] && return
configure_travis \
--enable-python \
--enable-cryptsetup-reencrypt \
"$cfg_opts" \
|| return
$MAKE || return
sudo modprobe dm-crypt
sudo modprobe dm-verity
sudo modprobe dm-integrity
uname -a
sudo dmsetup version
sudo dmsetup targets
# FIXME: we should use -E option here
sudo make check || return
#sudo $MAKE install || return
}
function travis_install_script
{
# install some packages from Ubuntu's default sources
sudo apt-get -qq update
sudo apt-get install -qq >/dev/null \
python-dev \
sharutils \
libgcrypt20-dev \
libssl-dev \
libdevmapper-dev \
libpopt-dev \
uuid-dev \
libsepol1-dev \
libtool \
dmsetup \
autoconf \
automake \
pkg-config \
autopoint \
gettext \
expect \
keyutils \
libjson-c-dev \
|| return
}
function travis_before_script
{
set -o xtrace
./autogen.sh
ret=$?
set +o xtrace
return $ret
}
function travis_script
{
local ret
set -o xtrace
case "$MAKE_CHECK" in
gcrypt)
check_nonroot "--with-crypto_backend=gcrypt"
check_root "--with-crypto_backend=gcrypt"
;;
openssl)
check_nonroot "--with-crypto_backend=openssl"
check_root "--with-crypto_backend=openssl"
;;
*)
echo "error, check environment (travis.yml)" >&2
false
;;
esac
ret=$?
set +o xtrace
return $ret
}
function travis_after_script
{
return 0
}

38
.travis.yml Normal file
View File

@@ -0,0 +1,38 @@
language: c
sudo: required
dist: trusty
compiler:
- gcc
env:
- MAKE_CHECK="gcrypt"
- MAKE_CHECK="openssl"
branches:
only:
- master
- wip-luks2
before_install:
- uname -a
- $CC --version
- which $CC
# workaround clang not system wide, fail on sudo make install
- export CC=`which $CC`
# workaround travis-ci issue #5301
- unset PYTHON_CFLAGS
install:
- source ./.travis-functions.sh
- travis_install_script
before_script:
- travis_before_script
script:
- travis_script
after_script:
- travis_after_script

View File

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

View File

@@ -500,3 +500,18 @@ necessary. Here is a sample; alter the names:
Ty Coon, President of Vice
That's all there is to it!
-----
In addition, as a special exception, the copyright holders give
permission to link the code of portions of this program with the
OpenSSL library under certain conditions as described in each
individual source file, and distribute linked combinations
including the two.
You must obey the GNU Lesser General Public License in all respects
for all of the code used other than OpenSSL. If you modify
file(s) with this exception, you may extend this exception to your
version of the file(s), but you are not obligated to do so. If you
do not wish to do so, delete this exception statement from your
version. If you delete this exception statement from all source
files in the program, then also delete it here.

841
ChangeLog
View File

@@ -1,839 +1,6 @@
2012-05-27 Milan Broz <gmazyland@gmail.com>
* Fix readonly activation if underlying device is readonly (1.4.0).
* Include stddef.h in libdevmapper.h (size_t definition).
* Version 1.4.3.
Since version 1.6 this file is no longer maintained.
2012-05-21 Milan Broz <gmazyland@gmail.com>
* Add --enable-fips for linking with fipscheck library.
* Initialize binary and library selfcheck if running in FIPS mode.
* Use FIPS RNG in FIPS mode for KEY and SALT (only gcrypt backend supported).
See docs/*ReleaseNotes for release changes documentation.
2012-05-09 Milan Broz <gmazyland@gmail.com>
* Fix keyslot removal (wipe keyslot) for device with 4k hw block (1.4.0).
* Allow empty cipher (cipher_null) for testing.
2012-05-02 Milan Broz <gmazyland@gmail.com>
* Fix loop mapping on readonly file.
* Relax --shared test, allow mapping even for overlapping segments.
* Support shared flag for LUKS devices (dangerous).
* Switch on retry on device remove for libdevmapper.
* Allow "private" activation (skip some udev global rules) flag.
2012-04-09 Milan Broz <gmazyland@gmail.com>
* Fix header check to support old (cryptsetup 1.0.0) header alignment. (1.4.0)
* Version 1.4.2.
2012-03-16 Milan Broz <gmazyland@gmail.com>
* Add --keyfile-offset and --new-keyfile-offset parameters to API and CLI.
* Add repair command and crypt_repair() for known LUKS metadata problems repair.
* Allow to specify --align-payload only for luksFormat.
2012-03-16 Milan Broz <mbroz@redhat.com>
* Unify password verification option.
* Support password verification with quiet flag if possible. (1.2.0)
* Fix retry if entered passphrases (with verify option) do not match.
* Support UUID=<LUKS_UUID> format for device specification.
2012-02-11 Milan Broz <mbroz@redhat.com>
* Add --master-key-file option to luksOpen (open using volume key).
2012-01-12 Milan Broz <mbroz@redhat.com>
* Fix use of empty keyfile.
2011-11-13 Milan Broz <mbroz@redhat.com>
* Fix error message for luksClose and detached LUKS header.
* Allow --header for status command to get full info with detached header.
2011-11-09 Milan Broz <mbroz@redhat.com>
* Version 1.4.1.
2011-11-05 Milan Broz <mbroz@redhat.com>
* Merge pycryptsetup (Python libcryptsetup bindings).
* Fix stupid typo in set_iteration_time API call.
* Fix cryptsetup status output if parameter is device path.
2011-10-27 Milan Broz <mbroz@redhat.com>
* Fix crypt_get_volume_key_size() for plain device.
* Fix FSF address in license text.
2011-10-25 Milan Broz <mbroz@redhat.com>
* Print informative message in isLuks only in verbose mode.
* Version 1.4.0.
2011-10-10 Milan Broz <mbroz@redhat.com>
* Version 1.4.0-rc1.
2011-10-05 Milan Broz <mbroz@redhat.com>
* Support Nettle 2.4 crypto backend (for ripemd160).
* If device is not rotational, do not use Gutmann wipe method.
* Add crypt_last_error() API call.
* Fix luksKillSLot exit code if slot is inactive or invalid.
* Fix exit code if passphrases do not match in luksAddKey.
* Add LUKS on-disk format description into package.
2011-09-22 Milan Broz <mbroz@redhat.com>
* Support key-slot option for luksOpen (use only explicit keyslot).
2011-08-22 Milan Broz <mbroz@redhat.com>
* Add more paranoid checks for LUKS header and keyslot attributes.
* Fix crypt_load to properly check device size.
* Use new /dev/loop-control (kernel 3.1) if possible.
* Enhance check of device size before writing LUKS header.
* Do not allow context format of already formatted device.
2011-07-25 Milan Broz <mbroz@redhat.com>
* Remove hash/hmac restart from crypto backend and make it part of hash/hmac final.
* Improve check for invalid offset and size values.
2011-07-19 Milan Broz <mbroz@redhat.com>
* Revert default initialisation of volume key in crypt_init_by_name().
* Do not allow key retrieval while suspended (key could be wiped).
* Do not allow suspend for non-LUKS devices.
* Support retries and timeout parameters for luksSuspend.
* Add --header option for detached metadata (on-disk LUKS header) device.
* Add crypt_init_by_name_and_header() and crypt_set_data_device() to API.
* Allow different data offset setting for detached header.
2011-07-07 Milan Broz <mbroz@redhat.com>
* Remove old API functions (all functions using crypt_options).
* Add --enable-discards option to allow discards/TRIM requests.
* Add crypt_get_iv_offset() function to API.
2011-07-01 Milan Broz <mbroz@redhat.com>
* Add --shared option for creating non-overlapping crypt segments.
* Add shared flag to libcryptsetup api.
* Fix plain crypt format parameters to include size option (API change).
2011-06-08 Milan Broz <mbroz@redhat.com>
* Fix return code for status command when device doesn't exists.
2011-05-24 Milan Broz <mbroz@redhat.com>
* Version 1.3.1.
2011-05-17 Milan Broz <mbroz@redhat.com>
* Fix keyfile=- processing in create command (1.3.0).
* Simplify device path status check.
2011-05-03 Milan Broz <mbroz@redhat.com>
* Do not ignore size argument for create command (1.2.0).
2011-04-18 Milan Broz <mbroz@redhat.com>
* Fix error paths in blockwise code and lseek_write call.
* Add Nettle crypto backend support.
2011-04-05 Milan Broz <mbroz@redhat.com>
* Version 1.3.0.
2011-03-22 Milan Broz <mbroz@redhat.com>
* Also support --skip and --hash option for loopaesOpen.
* Fix return code when passphrase is read from pipe.
* Document cryptsetup exit codes.
2011-03-18 Milan Broz <mbroz@redhat.com>
* Respect maximum keyfile size paramater.
* Introduce maximum default keyfile size, add configure option.
* Require the whole key read from keyfile in create command (broken in 1.2.0).
* Fix offset option for loopaesOpen.
* Lock memory also in luksDump command.
* Version 1.3.0-rc2.
2011-03-14 Milan Broz <mbroz@redhat.com>
* Version 1.3.0-rc1.
2011-03-11 Milan Broz <mbroz@redhat.com>
* Add loop manipulation code and support mapping of images in file.
* Add backing device loop info into status message.
* Add luksChangeKey command.
2011-03-05 Milan Broz <mbroz@redhat.com>
* Add exception to COPYING for binary distribution linked with OpenSSL library.
* Set secure data flag (wipe all ioclt buffers) if devmapper library supports it.
2011-01-29 Milan Broz <mbroz@redhat.com>
* Fix mapping removal if device disappeared but node still exists.
* Fix luksAddKey return code if master key is used.
2011-01-25 Milan Broz <mbroz@redhat.com>
* Add loop-AES handling (loopaesOpen and loopaesClose commands).
(requires kernel 2.6.38 and above)
2011-01-05 Milan Broz <mbroz@redhat.com>
* Fix static build (--disable-static-cryptsetup now works properly).
2010-12-30 Milan Broz <mbroz@redhat.com>
* Add compile time crypto backends implementation
(gcrypt, OpenSSL, NSS and userspace Linux kernel crypto api).
* Currently NSS is lacking ripemd160, cannot provide full plain compatibility.
* Use --with-crypto_backend=[gcrypt|openssl|nss|kernel] to configure.
2010-12-20 Milan Broz <mbroz@redhat.com>
* Version 1.2.0.
2010-11-25 Milan Broz <mbroz@redhat.com>
* Fix crypt_activate_by_keyfile() to work with PLAIN devices.
* Fix create command to properly handle keyfile size.
2010-11-16 Milan Broz <mbroz@redhat.com>
* Version 1.2.0-rc1.
2010-11-13 Milan Broz <mbroz@redhat.com>
* Fix password callback call.
* Fix default plain password entry from terminal in activate_by_passphrase.
* Add --dump-master-key option for luksDump to allow volume key dump.
* Allow to activate by internally cached volume key
(format/activate without keyslots active - used for temporary devices).
* Initialize volume key from active device in crypt_init_by_name()
* Fix cryptsetup binary exitcodes.
* Increase library version (still binary compatible with 1.1.x release).
2010-11-01 Milan Broz <mbroz@redhat.com>
* No longer support luksDelKey, reload and --non-exclusive.
* Remove some obsolete info from man page.
* Add crypt_get_type(), crypt_resize(), crypt_keyslot_max()
and crypt_get_active_device() to API.
* Rewrite all implementations in cryptsetup to new API.
* Fix luksRemoveKey to behave as documented (do not ask
for remaining keyslot passphrase).
* Add more regression tests for commands.
* Disallow mapping of device which is already in use (mapped or mounted).
* Disallow luksFormat on device in use.
2010-10-27 Milan Broz <mbroz@redhat.com>
* Rewrite cryptsetup luksFormat, luksOpen, luksAddKey to use new API
to allow adding new features.
* Implement --use-random and --use-urandom for luksFormat to allow
setting of RNG for volume key generator.
* Add crypt_set_rng_type() and crypt_get_rng_type() to API.
* Add crypt_set_uuid() to API.
* Allow UUID setting in luksFormat and luksUUID (--uuid parameter).
* Add --keyfile-size and --new-keyfile-size (in bytes) size and disallow overloading
of --key-size for limiting keyfile reads.
* Fix luksFormat to properly use key file with --master-key-file switch.
* Fix possible double free when handling master key file.
2010-10-17 Milan Broz <mbroz@redhat.com>
* Add crypt_get_device_name() to API (get underlying device name).
* Change detection for static libraries.
* Fix pkg-config use in automake scripts.
* Remove --disable-shared-library switch and handle static library build
by common libtool logic (using --enable-static).
* Add --enable-static-cryptsetup option to build cryptsetup.static binary
together with shared build.
2010-08-05 Milan Broz <mbroz@redhat.com>
* Wipe iteration and salt after KillSlot in LUKS header.
* Rewrite file differ test to C (and fix it to really work).
* Switch to 1MiB default alignment of data.
For more info see https://bugzilla.redhat.com/show_bug.cgi?id=621684
* Do not query non-existent device twice (cryptsetup status /dev/nonexistent).
* Check if requested hash is supported before writing LUKS header.
2010-07-28 Arno Wagner <arno@wagner.name>
* Add FAQ (Frequently Asked Questions) file to distribution.
2010-07-03 Milan Broz <mbroz@redhat.com>
* Fix udev support for old libdevmapper with not compatible definition.
* Version 1.1.3.
2010-06-01 Milan Broz <mbroz@redhat.com>
* Fix device alignment ioctl calls parameters.
* Fix activate_by_* API calls to handle NULL device name as documented.
2010-05-30 Milan Broz <mbroz@redhat.com>
* Version 1.1.2.
2010-05-27 Milan Broz <mbroz@redhat.com>
* Fix luksFormat/luksOpen reading passphrase from stdin and "-" keyfile.
* Support --key-file/-d option for luksFormat.
* Fix description of --key-file and add --verbose and --debug options to man page.
* Add verbose log level and move unlocking message there.
* Remove device even if underlying device disappeared.
* Fix (deprecated) reload device command to accept new device argument.
2010-05-23 Milan Broz <mbroz@redhat.com>
* Fix luksClose operation for stacked DM devices.
* Version 1.1.1.
2010-05-03 Milan Broz <mbroz@redhat.com>
* Fix automatic dm-crypt module loading.
* Escape hyphens in man page.
* Version 1.1.1-rc2.
2010-04-30 Milan Broz <mbroz@redhat.com>
* Try to use pkgconfig for device mapper library.
* Detect old dm-crypt module and disable LUKS suspend/resume.
* Fix apitest to work on older systems.
* Allow no hash specification in plain device constructor.
* Fix luksOpen reading of passphrase on stdin (if "-" keyfile specified).
* Fix isLuks to initialise crypto backend (blkid instead is suggested anyway).
* Version 1.1.1-rc1.
2010-04-12 Milan Broz <mbroz@redhat.com>
* Fix package config to use proper package version.
* Avoid class C++ keyword in library header.
* Detect and use devmapper udev support if available (disable by --disable-udev).
2010-04-06 Milan Broz <mbroz@redhat.com>
* Prefer some device paths in status display.
* Support device topology detectionfor data alignment.
2010-02-25 Milan Broz <mbroz@redhat.com>
* Do not verify unlocking passphrase in luksAddKey command.
* Properly initialise crypto backend in header backup/restore commands.
2010-01-17 Milan Broz <mbroz@redhat.com>
* If gcrypt compiled with capabilities, document workaround for cryptsetup (see lib/gcrypt.c).
* Version 1.1.0.
2010-01-10 Milan Broz <mbroz@redhat.com>
* Fix initialisation of gcrypt duting luksFormat.
* Convert hash name to lower case in header (fix sha1 backward comatible header)
* Check for minimum required gcrypt version.
2009-12-30 Milan Broz <mbroz@redhat.com>
* Fix key slot iteration count calculation (small -i value was the same as default).
* The slot and key digest iteration minimun is now 1000.
* The key digest iteration # is calculated from iteration time (approx 1/8 of that).
* Version 1.1.0-rc4.
2009-12-11 Milan Broz <mbroz@redhat.com>
* Fix error handling during reading passhrase.
2009-12-01 Milan Broz <mbroz@redhat.com>
* Allow changes of default compiled-in cipher parameters through configure.
* Switch default key size for LUKS to 256bits.
* Switch default plain mode to aes-cbc-essiv:sha256 (default is backward incompatible!).
2009-11-14 Milan Broz <mbroz@redhat.com>
* Add CRYPT_ prefix to enum defined in libcryptsetup.h.
* Fix status call to fail when running as non-root user.
* Check in configure if selinux libraries are required in static version.
* Add temporary debug code to find processes locking internal device.
* Simplify build system, use autopoint and clean gettext processing.
* Use proper NLS macros and detection (so the message translation works again).
* Version 1.1.0-rc3.
2009-09-30 Milan Broz <mbroz@redhat.com>
* Fix exported symbols and versions in libcryptsetup.
* Do not use internal lib functions in cryptsetup.
* Add crypt_log to library.
* Fix crypt_remove_device (remove, luksClose) implementation.
* Move dm backend initialisation to library calls.
* Move duplicate Command failed message to verbose level (error is printed always).
* Add some password and used algorithms notes to man page.
* Version 1.1.0-rc2.
2009-09-28 Milan Broz <mbroz@redhat.com>
* Add luksHeaderBackup and luksHeaderRestore commands.
* Fail passphrase read if piped input no longer exists.
* Version 1.1.0-rc1.
2009-09-15 Milan Broz <mbroz@redhat.com>
* Initialize crypto library before LUKS header load.
* Fix manpage to not require --size which expands to device size by default.
2009-09-10 Milan Broz <mbroz@redhat.com>
* Clean up Makefiles and configure script.
* Version 1.1.0-test0.
2009-09-08 Milan Broz <mbroz@redhat.com>
* Use dm-uuid for all crypt devices, contains device type and name now.
* Try to read first sector from device to properly check that device is ready.
2009-09-02 Milan Broz <mbroz@redhat.com>
* Add luksSuspend (freeze device and wipe key) and luksResume (with provided passphrase).
2009-08-30 Milan Broz <mbroz@redhat.com>
* Require device device-mapper to build and do not use backend wrapper for dm calls.
* Move memory locking and dm initialization to command layer.
* Increase priority of process if memory is locked.
* Add log macros and make logging modre consitent.
* Move command successful messages to verbose level.
* Introduce --debug parameter.
* Move device utils code and provide context parameter (for log).
* Keyfile now must be provided by path, only stdin file descriptor is used (api only).
* Do not call isatty() on closed keyfile descriptor.
* Run performance check for PBKDF2 from LUKS code, do not mix hash algoritms results.
* Add ability to provide pre-generated master key and UUID in LUKS header format.
* Add LUKS function to verify master key digest.
* Move key slot manuipulation function into LUKS specific code.
* Replace global options struct with separate parameters in helper functions.
* Add new libcryptsetup API (documented in libcryptsetup.h).
* Implement old API calls using new functions.
* Remove old API code helper functions.
* Add --master-key-file option for luksFormat and luksAddKey.
2009-08-17 Milan Broz <mbroz@redhat.com>
* Fix PBKDF2 speed calculation for large passhrases.
* Allow using passphrase provided in options struct for LuksOpen.
* Allow restrict keys size in LuksOpen.
2009-07-30 Milan Broz <mbroz@redhat.com>
* Fix errors when compiled with LUKS_DEBUG.
* Print error when getline fails.
* Remove po/cryptsetup-luks.pot, it's autogenerated.
* Return ENOENT for empty keyslots, EINVAL will be used later for other type of error.
* Switch PBKDF2 from internal SHA1 to libgcrypt, make hash algorithm not hardcoded to SHA1 here.
* Add required parameters for changing hash used in LUKS key setup scheme.
* Do not export simple XOR helper now used only inside AF functions.
* Completely remove internal SHA1 implementanion code, not needed anymore.
* Enable hash algorithm selection for LUKS through -h luksFormat option.
2009-07-28 Milan Broz <mbroz@redhat.com>
* Pad luks header to 512 sector size.
* Rework read/write blockwise to not split operation to many pieces.
* Use posix_memalign if available.
2009-07-22 Milan Broz <mbroz@redhat.com>
* Fix segfault if provided slot in luksKillslot is invalid.
* Remove unneeded timeout when remove of temporary device succeeded.
2009-07-22 Milan Broz <mbroz@redhat.com>
* version 1.0.7
2009-07-16 Milan Broz <mbroz@redhat.com>
* Allow removal of last slot in luksRemoveKey and luksKillSlot.
2009-07-11 Milan Broz <mbroz@redhat.com>
* Add --disable-selinux option and fix static build if selinux is required.
* Reject unsupported --offset and --skip options for luksFormat and update man page.
2009-06-22 Milan Broz <mbroz@redhat.com>
* Summary of changes in subversion for 1.0.7-rc1:
* Various man page fixes.
* Set UUID in device-mapper for LUKS devices.
* Retain readahead of underlying device.
* Display device name when asking for password.
* Check device size when loading LUKS header. Remove misleading error message later.
* Add error hint if dm-crypt mapping failed.
* Use better error messages if device doesn't exist or is already used by other mapping.
* Fix make distcheck.
* Check if all slots are full during luksAddKey.
* Fix segfault in set_error.
* Code cleanups, remove precompiled pot files, remove unnecessary files from po directory
* Fix uninitialized return value variable in setup.c.
* Code cleanups. (thanks to Ivan Stankovic)
* Fix wrong output for remaining key at key deletion.
* Allow deletion of key slot while other keys have the same key information.
* Add missing AM_PROG_CC_C_O to configure.in
* Remove duplicate sentence in man page.
* Wipe start of device (possible fs signature) before LUKS-formatting.
* Do not process configure.in in hidden directories.
* Return more descriptive error in case of IO or header format error.
* Use remapping to error target instead of calling udevsettle for temporary crypt device.
* Check device mapper communication and warn user if device-mapper support missing in kernel.
* Fix signal handler to properly close device.
* write_lseek_blockwise: declare innerCount outside the if block.
* add -Wall to the default CFLAGS. fix some signedness issues.
* Error handling improvement.
* Add non-exclusive override to interface definition.
* Refactor key slot selection into keyslot_from_option.
2007-05-01 Clemens Fruhwirth <clemens@endorphin.org>
* lib/backends.c, man/cryptsetup.8: Apply patch from Ludwig Nussel
<ludwig.nussel@suse.de>, for old SuSE compat hashing.
2007-04-16 Clemens Fruhwirth <clemens@endorphin.org>
* Summary of changes in subversion:
Fix segfault for key size > 32 bytes.
Kick ancient header version conversion.
Fix http://bugs.debian.org/403075
No passwort retrying for I/O errors.
Fix hang on "-i 0".
Fix parenthesization error that prevented --tries from working
correctly.
2006-11-28 gettextize <bug-gnu-gettext@gnu.org>
* m4/gettext.m4: Upgrade to gettext-0.15.
* m4/glibc2.m4: New file, from gettext-0.15.
* m4/intmax.m4: New file, from gettext-0.15.
* m4/inttypes-h.m4: New file, from gettext-0.15.
* m4/inttypes-pri.m4: Upgrade to gettext-0.15.
* m4/lib-link.m4: Upgrade to gettext-0.15.
* m4/lib-prefix.m4: Upgrade to gettext-0.15.
* m4/lock.m4: New file, from gettext-0.15.
* m4/longdouble.m4: New file, from gettext-0.15.
* m4/longlong.m4: New file, from gettext-0.15.
* m4/nls.m4: Upgrade to gettext-0.15.
* m4/po.m4: Upgrade to gettext-0.15.
* m4/printf-posix.m4: New file, from gettext-0.15.
* m4/signed.m4: New file, from gettext-0.15.
* m4/size_max.m4: New file, from gettext-0.15.
* m4/visibility.m4: New file, from gettext-0.15.
* m4/wchar_t.m4: New file, from gettext-0.15.
* m4/wint_t.m4: New file, from gettext-0.15.
* m4/xsize.m4: New file, from gettext-0.15.
* m4/Makefile.am: New file.
* configure.in (AC_OUTPUT): Add m4/Makefile.
(AM_GNU_GETTEXT_VERSION): Bump to 0.15.
2006-10-22 David Härdeman <david@hardeman.nu>
* Allow hashing of keys passed through stdin.
2006-10-13 Clemens Fruhwirth <clemens@endorphin.org>
* configure.in: 1.0.4 release
2006-10-13 Clemens Fruhwirth <clemens@endorphin.org>
* man/cryptsetup.8: Document --tries switch; patch by Jonas
Meurer.
2006-10-13 Clemens Fruhwirth <clemens@endorphin.org>
* lib/setup.c: Added terminal timeout rewrite as forwarded by
Jonas Meurer
2006-10-04 Clemens Fruhwirth <clemens@endorphin.org>
* Merged patch from Marc Merlin <marc@merlins.org> to allow user
selection of key slot.
2006-09-26 gettextize <bug-gnu-gettext@gnu.org>
* m4/codeset.m4: Upgrade to gettext-0.14.4.
* m4/gettext.m4: Upgrade to gettext-0.14.4.
* m4/glibc2.m4: New file, from gettext-0.14.4.
* m4/glibc21.m4: Upgrade to gettext-0.14.4.
* m4/iconv.m4: Upgrade to gettext-0.14.4.
* m4/intdiv0.m4: Upgrade to gettext-0.14.4.
* m4/intmax.m4: New file, from gettext-0.14.4.
* m4/inttypes.m4: Upgrade to gettext-0.14.4.
* m4/inttypes_h.m4: Upgrade to gettext-0.14.4.
* m4/inttypes-pri.m4: Upgrade to gettext-0.14.4.
* m4/isc-posix.m4: Upgrade to gettext-0.14.4.
* m4/lcmessage.m4: Upgrade to gettext-0.14.4.
* m4/lib-ld.m4: Upgrade to gettext-0.14.4.
* m4/lib-link.m4: Upgrade to gettext-0.14.4.
* m4/lib-prefix.m4: Upgrade to gettext-0.14.4.
* m4/longdouble.m4: New file, from gettext-0.14.4.
* m4/longlong.m4: New file, from gettext-0.14.4.
* m4/nls.m4: Upgrade to gettext-0.14.4.
* m4/po.m4: Upgrade to gettext-0.14.4.
* m4/printf-posix.m4: New file, from gettext-0.14.4.
* m4/progtest.m4: Upgrade to gettext-0.14.4.
* m4/signed.m4: New file, from gettext-0.14.4.
* m4/size_max.m4: New file, from gettext-0.14.4.
* m4/stdint_h.m4: Upgrade to gettext-0.14.4.
* m4/uintmax_t.m4: Upgrade to gettext-0.14.4.
* m4/ulonglong.m4: Upgrade to gettext-0.14.4.
* m4/wchar_t.m4: New file, from gettext-0.14.4.
* m4/wint_t.m4: New file, from gettext-0.14.4.
* m4/xsize.m4: New file, from gettext-0.14.4.
* Makefile.am (ACLOCAL_AMFLAGS): New variable.
* configure.in (AM_GNU_GETTEXT_VERSION): Bump to 0.14.4.
2006-08-04 Clemens Fruhwirth <clemens@endorphin.org>
* configure.in: 1.0.4-rc2
2006-08-04 Clemens Fruhwirth <clemens@endorphin.org>
* luks/Makefile.am: Add a few regression tests
2006-08-04 Clemens Fruhwirth <clemens@endorphin.org>
* lib/setup.c (get_key): Applied patch from David Härdeman
<david@2gen.com> for reading binary keys from stdin using
the "-" as key file.
2006-08-04 Clemens Fruhwirth <clemens@endorphin.org>
* lib/setup.c (__crypt_luks_add_key): For checking options struct
(optionsCheck) filter out CRYPT_FLAG_VERIFY and
CRYPT_FLAG_VERIFY_IF_POSSIBLE, so that in no case password verification is done
for password retrieval.
2006-08-04 Clemens Fruhwirth <clemens@endorphin.org>
* configure.in: Merge Patch from http://bugs.gentoo.org/show_bug.cgi?id=132126 for sepol
2006-07-23 Clemens Fruhwirth <clemens@endorphin.org>
* Applied patches from David Härdeman <david@2gen.com> to fix 64
bit compiler warning issues.
2006-05-19 Clemens Fruhwirth <clemens@endorphin.org>
* Applied patches from Jonas Meurer
- fix terminal status after timeout
- add remark for --tries to manpage
- allow more than 32 chars from standard input.
- exit status fix for cryptsetup status.
2006-05-06 Clemens Fruhwirth <clemens@endorphin.org>
* src/cryptsetup.c (yesDialog): Fix getline problem for 64-bit archs.
2006-04-05 Clemens Fruhwirth <clemens@endorphin.org>
* configure.in: Release 1.0.3.
* Applied patch by Johannes Weißl for more meaningful exit codes
and password retries
2006-03-30 Clemens Fruhwirth <clemens@endorphin.org>
* lib/setup.c (__crypt_create_device): (char *) -> (const char *)
2006-03-30 Clemens Fruhwirth <clemens@endorphin.org>
* Apply alignPayload patch from Peter Palfrader <weasel@debian.org>
2006-03-15 Clemens Fruhwirth <clemens@endorphin.org>
* configure.in: 1.0.3-rc3. Most unplease release ever.
* lib/setup.c (__crypt_create_device): More verbose error message.
2006-02-26 Clemens Fruhwirth <clemens@endorphin.org>
* lib/setup.c: Revert to 1.0.1 key reading.
2006-02-25 Clemens Fruhwirth <clemens@endorphin.org>
* man/cryptsetup.8: merge patch from Jonas Meurer
2006-02-25 Clemens Fruhwirth <clemens@endorphin.org>
* configure.in: 1.0.3-rc2
2006-02-25 Clemens Fruhwirth <clemens@endorphin.org>
* lib/libdevmapper.c (dm_create_device): Remove dup check here.
* lib/setup.c (__crypt_luks_open): Adopt same dup check as regular
create command.
2006-02-22 Clemens Fruhwirth <clemens@endorphin.org>
* configure.in: Spin 1.0.3-rc1
2006-02-22 Clemens Fruhwirth <clemens@endorphin.org>
* src/cryptsetup.c (action_create): Change defaulting.
(action_luksFormat): Change defaulting.
* lib/setup.c (parse_into_name_and_mode): Revert that default
change. This is FORBIDDEN here, as it will change cryptsetup
entire default. This is BAD in a non-LUKS world.
2006-02-21 Clemens Fruhwirth <clemens@endorphin.org>
* luks/keyencryption.c (setup_mapping): Add proper size restriction to mapping.
(LUKS_endec_template): Add more verbose error message.
2006-02-21 Clemens Fruhwirth <clemens@endorphin.org>
* lib/libdevmapper.c (dm_query_device): Incorporate patch from
Bastian Blank
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=344313
2006-02-21 Clemens Fruhwirth <clemens@endorphin.org>
* src/cryptsetup.c: Rename show_error -> show_status.
2006-02-20 Clemens Fruhwirth <clemens@endorphin.org>
* lib/libdevmapper.c (dm_create_device): Prevent existing mapping
from being removed when a mapping with the same name is added
* Add timeout patch from Jonas Meurer
* src/cryptsetup.c: Remove conditional error printing to enable
printing the no-error msg (Command successful). Verify passphrase
for LUKS volumes.
(main): Add no-verify-passphrase
* lib/setup.c (parse_into_name_and_mode): Change default mode complition to essiv:sha256.
2006-01-04 Clemens Fruhwirth <clemens@endorphin.org>
* src/cryptsetup.c (help): Merge patch from Gentoo: change gettext(..) to _(..).
2005-12-06 Clemens Fruhwirth <clemens@endorphin.org>
* man/cryptsetup.8: Correct "seconds" to "microseconds" in the explaination for -i.
2005-11-09 Clemens Fruhwirth <clemens@endorphin.org>
* src/cryptsetup.c (main): Add version string.
2005-11-08 Clemens Fruhwirth <clemens@endorphin.org>
* lib/backends.c: compile fix.
2005-09-11 Clemens Fruhwirth <clemens@endorphin.org>
* lib/setup.c (get_key): Fixed another incompatibility from my
get_key rewrite with original cryptsetup.
2005-09-11 Clemens Fruhwirth <clemens@endorphin.org>
* Merged changes from Florian Knauf's fk02 branch.
2005-09-08 Clemens Fruhwirth <clemens@endorphin.org>
* lib/setup.c (get_key): Fixed another incompatiblity with
original cryptsetup.
2005-08-20 Clemens Fruhwirth <clemens@endorphin.org>
* Checked in a patch from Michael Gebetsroither <gebi@sbox.tugraz.at>
to silent all confirmation dialogs.
2005-06-23 Clemens Fruhwirth <clemens@endorphin.org>
* src/cryptsetup.c (help): print PACKAGE_STRING
2005-06-20 Clemens Fruhwirth <clemens@endorphin.org>
* luks/keymanage.c (LUKS_set_key): Security check against header manipulation
* src/cryptsetup.c (action_luksDelKey): Safety check in luksDelKey
* luks/keymanage.c: Changed disk layout generation to align key material to 4k boundaries.
(LUKS_is_last_keyslot): Added LUKS_is_last_keyslot function.
* Applied patch from Bill Nottingham fixing a lot of prototypes.
* src/cryptsetup.c (action_luksOpen): Add support for -r flag.
* configure.in: Version bump 1.0.1
2005-06-16 Clemens Fruhwirth <clemens@endorphin.org>
* lib/setup.c (__crypt_luks_open): Remove mem leaking of dmCipherSpec.
(get_key): Fix missing zero termination for read string.
2005-06-12 Clemens Fruhwirth <clemens@endorphin.org>
* luks/keyencryption.c (setup_mapping): Added CRYPT_FLAG_READONLY in case of O_RDONLY mode
2005-06-11 Clemens Fruhwirth <clemens@endorphin.org>
* configure.in: Version bump 1.0.1-pre
2005-06-09 Clemens Fruhwirth <clemens@endorphin.org>
* lib/utils.c: Added write_llseek_blocksize method to support sector wiping on sector_size != 512
media
2005-05-23 Clemens Fruhwirth <clemens@endorphin.org>
* lib/setup.c (crypt_luksDelKey): Added missing return statement
(setup_leave): Added missing return statement
* luks/keyencryption.c (clear_mapping): Added missing return statement
2005-05-19 Clemens Fruhwirth <clemens@endorphin.org>
* lib/utils.c (write_blockwise, read_blockwise): Changed to soft bsize instead of SECTOR_SIZE
* luks/keymanage.c (wipe): Changed open mode to O_DIRECT | O_SYNC, and changed write
to use the blockwise write helper
2005-04-21 Clemens Fruhwirth <clemens@endorphin.org>
* man/cryptsetup.8: Corrected an error, thanks to Dick Middleton.
2005-04-09 Clemens Fruhwirth <clemens@endorphin.org>
* luks/sha/hmac.c: Add 64 bit bug fix courtesy to
Oliver Paukstadt <pstadt@sourcentral.org>.
* luks/pbkdf.c, luks/keyencryption.c, luks/keymanage.c, luks/af.c: Added a license
disclaimer and remove option for "any future GPL versions".
2005-03-25 Clemens Fruhwirth <clemens@endorphin.org>
* configure.in: man page Makefile. Version bump 1.0.
* man/cryptsetup.8: finalize man page and move to section 8.
* src/cryptsetup.c (action_luksFormat): Add "are you sure" for interactive sessions.
* lib/setup.c (crypt_luksDump), src/cryptsetup.c: add LUKS dump command
2005-03-24 Clemens Fruhwirth <clemens@endorphin.org>
* src/cryptsetup.c, luks/Makefile.am (test), lib/setup.c (setup_enter):
rename luksInit to luksFormat
2005-03-12 Clemens Fruhwirth <clemens@endorphin.org>
* man/cryptsetup.1: Add man page.
* lib/setup.c: Remove unneccessary LUKS_write_phdr call, so the
phdr is written after passphrase reading, so the user can change
his mind, and not have a partial written LUKS header on it's disk.
2005-02-09 Clemens Fruhwirth <clemens@endorphin.org>
* luks/keymanage.c (LUKS_write_phdr): converted argument phdr to
pointer, and make a copy of phdr for conversion
* configure.in: Version dump.
* luks/keyencryption.c: Convert to read|write_blockwise.
* luks/keymanage.c: Convert to read|write_blockwise.
* 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>
* 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>
* lib/: libcryptsetup.h, libdevmapper.c: Small fixes.
2004-03-09 Tuesday 21:41 Christophe Saout <christophe@saout.de>
* lib/internal.h, lib/libcryptsetup.h, lib/libdevmapper.c,
lib/setup.c, po/de.po, src/cryptsetup.c: Added internal flags to
keep track of malloc'ed return values in struct crypt_options and
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>
* ChangeLog, configure.in, setup-gettext, lib/Makefile.am,
lib/backends.c, lib/blockdev.h, lib/gcrypt.c, lib/internal.h,
lib/libcryptsetup.h, lib/libdevmapper.c, lib/setup.c,
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>
* ChangeLog, Makefile.am, acinclude.m4, configure.in,
lib/Makefile.am, lib/backends.c, lib/blockdev.h, lib/gcrypt.c,
lib/libdevmapper.c, lib/setup.c, lib/utils.c, po/de.po,
src/Makefile.am: BLKGETSIZE64 fixes and started modularity
enhancements
2004-03-04 Thursday 21:06 Christophe Saout <christophe@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>
* 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>
* 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: Initial revision
See version control history for full commit messages.
https://gitlab.com/cryptsetup/cryptsetup/commits/master

3090
FAQ

File diff suppressed because it is too large Load Diff

View File

@@ -5,7 +5,8 @@ SUBDIRS = \
man \
python \
tests \
po
po \
scripts
ACLOCAL_AMFLAGS = -I m4

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

90
README.md Normal file
View File

@@ -0,0 +1,90 @@
![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.
Last version of the LUKS format specification is
[available here](https://www.kernel.org/pub/linux/utils/cryptsetup/LUKS_docs/on-disk-format.pdf).
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/).
-----------------
**CVE-2016-4484 (Initrd root shell)**
This is problem in **intramfs** **scripts** only (these are **not** part of cryptsetup project), it is neiter bug in cryptsetup nor in LUKS.
Some distributions could add these scripts to distributed package, please check your distro updates for more info.
[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.7.5**
* [cryptsetup-1.7.5.tar.xz](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.7/cryptsetup-1.7.5.tar.xz)
* Signature [cryptsetup-1.7.5.tar.sign](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.7/cryptsetup-1.7.5.tar.sign)
_(You need to decompress file first to check signature.)_
* [Cryptsetup 1.7.5 Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.7/v1.7.5-ReleaseNotes).
Previous versions
* [Version 1.7.4](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.7/cryptsetup-1.7.4.tar.xz) -
[Signature](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.7/cryptsetup-1.7.4.tar.sign) -
[Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.7/v1.7.4-ReleaseNotes).
* [Version 1.7.3](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.7/cryptsetup-1.7.3.tar.xz) -
[Signature](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.7/cryptsetup-1.7.3.tar.sign) -
[Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.7/v1.7.3-ReleaseNotes).
* [Version 1.7.2](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.7/cryptsetup-1.7.2.tar.xz) -
[Signature](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.7/cryptsetup-1.7.2.tar.sign) -
[Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.7/v1.7.2-ReleaseNotes).
* [Version 1.7.1](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.7/cryptsetup-1.7.1.tar.xz) -
[Signature](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.7/cryptsetup-1.7.1.tar.sign) -
[Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.7/v1.7.1-ReleaseNotes).
* [Version 1.7.0](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.7/cryptsetup-1.7.0.tar.xz) -
[Signature](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.7/cryptsetup-1.7.0.tar.sign) -
[Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.7/v1.7.0-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.
The libcryptsetup API/ABI changes are tracked in [compatibility report](https://gitlab.com/cryptsetup/cryptsetup/wikis/ABI-tracker/timeline/libcryptsetup/index.html).
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).

10
TODO
View File

@@ -1,7 +1,5 @@
Version 1.5.0:
- Export wipe device functions
- Support K/M suffixes for align payload (new switch?).
- FIPS patches (RNG, volume key restrictions, move changekey to library)
- online reencryption api?
- integrate more metadata formats
- 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?).
- Fix all crazy automake warnings (or switch to Cmake).
- Nettle3 backend is not compatible

View File

@@ -22,7 +22,7 @@ DIE=0
DIE=1
}
(grep "^AM_PROG_LIBTOOL" $srcdir/configure.in >/dev/null) && {
(grep "^AM_PROG_LIBTOOL" $srcdir/configure.ac >/dev/null) && {
(libtool --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "**Error**: You must have libtool installed."
@@ -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,15 +1,22 @@
AC_PREREQ([2.67])
AC_INIT([cryptsetup],[1.4.3])
AC_INIT([cryptsetup],[2.0.0-rc0])
dnl library version from <major>.<minor>.<release>[-<suffix>]
LIBCRYPTSETUP_VERSION=$(echo $PACKAGE_VERSION | cut -f1 -d-)
LIBCRYPTSETUP_VERSION_INFO=6:0:2
LIBCRYPTSETUP_VERSION_INFO=12:0:0
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
@@ -25,28 +32,60 @@ AC_PROG_INSTALL
AC_PROG_MAKE_SET
AC_ENABLE_STATIC(no)
LT_INIT
PKG_PROG_PKG_CONFIG
AC_C_RESTRICT
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)
sys/sysmacros.h sys/statvfs.h ctype.h unistd.h locale.h byteswap.h endian.h stdint.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.])])
AC_ARG_ENABLE(keyring, AS_HELP_STRING([--disable-keyring],[disable kernel keyring support and builtin kernel keyring token]),[], [enable_keyring=yes])
if test "x$enable_keyring" = "xyes"; then
AC_CHECK_HEADERS(linux/keyctl.h,,[AC_MSG_ERROR([You need Linux kernel headers with kernel keyring service compiled.])])
dnl ==========================================================================
dnl check whether kernel is compiled with kernel keyring service syscalls
AC_CHECK_DECL(__NR_add_key,,[AC_MSG_ERROR([The kernel is missing add_key syscall.])], [#include <syscall.h>])
AC_CHECK_DECL(__NR_keyctl,,[AC_MSG_ERROR([The kernel is missing keyctl syscall.])], [#include <syscall.h>])
AC_CHECK_DECL(__NR_request_key,,[AC_MSG_ERROR([The kernel is missing request_key syscall.])], [#include <syscall.h>])
dnl ==========================================================================
dnl check that key_serial_t hasn't been adopted yet in stdlib
AC_CHECK_TYPES([key_serial_t], [], [], [
AC_INCLUDES_DEFAULT
#ifdef HAVE_LINUX_KEYCTL_H
# include <linux/keyctl.h>
#endif
])
AC_DEFINE(KERNEL_KEYRING, 1, [Enable kernel keyring service support])
fi
AM_CONDITIONAL(KERNEL_KEYRING, test x$enable_keyring = xyes)
saved_LIBS=$LIBS
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 ==========================================================================
@@ -62,7 +101,7 @@ 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])
@@ -73,12 +112,6 @@ if test "x$with_fips" = "xyes"; then
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], [
@@ -87,6 +120,48 @@ AC_DEFUN([NO_FIPS], [
fi
])
dnl ==========================================================================
dnl pwquality library (cryptsetup CLI only)
AC_ARG_ENABLE([pwquality],
AS_HELP_STRING([--enable-pwquality],
[enable password quality checking using pwquality library]),
[with_pwquality=$enableval],
[with_pwquality=no])
if test "x$with_pwquality" = "xyes"; then
AC_DEFINE(ENABLE_PWQUALITY, 1, [Enable password quality checking using pwquality library])
PKG_CHECK_MODULES([PWQUALITY], [pwquality >= 1.0.0],,
AC_MSG_ERROR([You need pwquality library.]))
dnl FIXME: this is really hack for now
PWQUALITY_STATIC_LIBS="$PWQUALITY_LIBS -lcrack -lz"
fi
dnl ==========================================================================
dnl passwdqc library (cryptsetup CLI only)
AC_ARG_ENABLE([passwdqc],
AS_HELP_STRING([--enable-passwdqc@<:@=CONFIG_PATH@:>@],
[enable password quality checking using passwdqc library (optionally with CONFIG_PATH)]),
[enable_passwdqc=$enableval],
[enable_passwdqc=no])
case "$enable_passwdqc" in
yes|no) use_passwdqc_config="" ;;
/*) use_passwdqc_config="$enable_passwdqc"; enable_passwdqc=yes ;;
*) AC_MSG_ERROR([Unrecognized --enable-passwdqc parameter.]) ;;
esac
AC_DEFINE_UNQUOTED([PASSWDQC_CONFIG_FILE], ["$use_passwdqc_config"], [passwdqc library config file])
if test "x$enable_passwdqc" = "xyes"; then
AC_DEFINE(ENABLE_PASSWDQC, 1, [Enable password quality checking using passwdqc library])
PASSWDQC_LIBS="-lpasswdqc"
fi
if test "x$with_pwquality$enable_passwdqc" = "xyesyes"; then
AC_MSG_ERROR([--enable-pwquality and --enable-passwdqc are mutually incompatible.])
fi
dnl ==========================================================================
dnl Crypto backend functions
@@ -96,8 +171,24 @@ AC_DEFUN([CONFIGURE_GCRYPT], [
else
GCRYPT_REQ_VERSION=1.1.42
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]),
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"
@@ -120,12 +211,13 @@ AC_DEFUN([CONFIGURE_OPENSSL], [
AC_MSG_ERROR([You need openssl library.]))
CRYPTO_CFLAGS=$OPENSSL_CFLAGS
CRYPTO_LIBS=$OPENSSL_LIBS
use_internal_pbkdf2=0
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([])
@@ -148,15 +240,17 @@ AC_DEFUN([CONFIGURE_NSS], [
CRYPTO_CFLAGS=$NSS_CFLAGS
CRYPTO_LIBS=$NSS_LIBS
use_internal_pbkdf2=1
NO_FIPS([])
])
AC_DEFUN([CONFIGURE_KERNEL], [
AC_CHECK_HEADERS(linux/if_alg.h,,
[AC_MSG_ERROR([You need Linux kernel with userspace crypto interface.])])
[AC_MSG_ERROR([You need Linux kernel headers with userspace crypto interface.])])
# AC_CHECK_DECLS([AF_ALG],,
# [AC_MSG_ERROR([You need Linux kernel with userspace crypto interface.])],
# [#include <sys/socket.h>])
use_internal_pbkdf2=1
NO_FIPS([])
])
@@ -165,12 +259,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=0
NO_FIPS([])
])
@@ -186,7 +281,22 @@ if test x$enable_static_cryptsetup = xyes; then
enable_static=yes
fi
fi
AM_CONDITIONAL(STATIC_CRYPTSETUP, test x$enable_static_cryptsetup = xyes)
AM_CONDITIONAL(STATIC_TOOLS, test x$enable_static_cryptsetup = xyes)
AC_ARG_ENABLE(veritysetup,
AS_HELP_STRING([--disable-veritysetup],
[disable veritysetup support]),[], [enable_veritysetup=yes])
AM_CONDITIONAL(VERITYSETUP, test x$enable_veritysetup = xyes)
AC_ARG_ENABLE([cryptsetup-reencrypt],
AS_HELP_STRING([--enable-cryptsetup-reencrypt],
[enable cryptsetup-reencrypt tool]))
AM_CONDITIONAL(REENCRYPT, test x$enable_cryptsetup_reencrypt = xyes)
AC_ARG_ENABLE(integritysetup,
AS_HELP_STRING([--disable-integritysetup],
[disable integritysetup support]),[], [enable_integritysetup=yes])
AM_CONDITIONAL(INTEGRITYSETUP, test x$enable_integritysetup = xyes)
AC_ARG_ENABLE(selinux,
AS_HELP_STRING([--disable-selinux],
@@ -209,6 +319,7 @@ LIBS=$saved_LIBS
LIBS="$LIBS $DEVMAPPER_LIBS"
AC_CHECK_DECLS([dm_task_secure_data], [], [], [#include <libdevmapper.h>])
AC_CHECK_DECLS([dm_task_retry_remove], [], [], [#include <libdevmapper.h>])
AC_CHECK_DECLS([dm_task_deferred_remove], [], [], [#include <libdevmapper.h>])
AC_CHECK_DECLS([DM_UDEV_DISABLE_DISK_RULES_FLAG], [have_cookie=yes], [have_cookie=no], [#include <libdevmapper.h>])
if test "x$enable_udev" = xyes; then
if test "x$have_cookie" = xno; then
@@ -219,11 +330,27 @@ if test "x$enable_udev" = xyes; then
fi
LIBS=$saved_LIBS
dnl Check for JSON-C used in LUKS2
PKG_CHECK_MODULES([JSON_C], [json-c])
dnl Crypto backend configuration.
AC_ARG_WITH([crypto_backend],
AS_HELP_STRING([--with-crypto_backend=BACKEND], [crypto backend (gcrypt/openssl/nss/kernel/nettle) [gcrypt]]),
[], with_crypto_backend=gcrypt
)
dnl Kernel crypto API backend needed for benchmark and tcrypt
AC_ARG_ENABLE([kernel_crypto], AS_HELP_STRING([--disable-kernel_crypto],
[disable kernel userspace crypto (no benchmark and tcrypt)]),
[with_kernel_crypto=$enableval],
[with_kernel_crypto=yes])
if test "x$with_kernel_crypto" = "xyes"; then
AC_CHECK_HEADERS(linux/if_alg.h,,
[AC_MSG_ERROR([You need Linux kernel headers with userspace crypto interface. (Or use --disable-kernel_crypto.)])])
AC_DEFINE(ENABLE_AF_ALG, 1, [Enable using of kernel userspace crypto])
fi
case $with_crypto_backend in
gcrypt) CONFIGURE_GCRYPT([]) ;;
openssl) CONFIGURE_OPENSSL([]) ;;
@@ -238,6 +365,16 @@ AM_CONDITIONAL(CRYPTO_BACKEND_NSS, test $with_crypto_backend = nss)
AM_CONDITIONAL(CRYPTO_BACKEND_KERNEL, test $with_crypto_backend = kernel)
AM_CONDITIONAL(CRYPTO_BACKEND_NETTLE, test $with_crypto_backend = nettle)
AM_CONDITIONAL(CRYPTO_INTERNAL_PBKDF2, test $use_internal_pbkdf2 = 1)
AC_DEFINE_UNQUOTED(USE_INTERNAL_PBKDF2, [$use_internal_pbkdf2], [Use internal PBKDF2])
AC_ARG_ENABLE(argon2, AS_HELP_STRING([--disable-argon2],
[disable internal implementation of Argon2 PBKDF]),[], [enable_argon2=yes])
AM_CONDITIONAL(CRYPTO_INTERNAL_ARGON2, test x$enable_argon2 = xyes)
if test x$enable_argon2 = xyes ; then
AC_DEFINE(USE_INTERNAL_ARGON2, 1, [Use internal Argon2])
fi
dnl Magic for cryptsetup.static build.
if test x$enable_static_cryptsetup = xyes; then
saved_PKG_CONFIG=$PKG_CONFIG
@@ -273,10 +410,17 @@ fi
AC_SUBST([DEVMAPPER_LIBS])
AC_SUBST([DEVMAPPER_STATIC_LIBS])
AC_SUBST([PWQUALITY_LIBS])
AC_SUBST([PWQUALITY_STATIC_LIBS])
AC_SUBST([PASSWDQC_LIBS])
AC_SUBST([CRYPTO_CFLAGS])
AC_SUBST([CRYPTO_LIBS])
AC_SUBST([CRYPTO_STATIC_LIBS])
AC_SUBST([JSON_C_LIBS])
AC_SUBST([LIBCRYPTSETUP_VERSION])
AC_SUBST([LIBCRYPTSETUP_VERSION_INFO])
@@ -309,15 +453,27 @@ AC_ARG_ENABLE([python], AS_HELP_STRING([--enable-python],[enable Python bindings
[with_python=$enableval],
[with_python=no])
if test "x$with_python" = "xyes"; then
AM_PATH_PYTHON([2.4])
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 "$PYTHON-config" ; then
AC_MSG_ERROR([Cannot find python development packages to build bindings])
if test "x$with_python" = "xyes"; then
AM_PATH_PYTHON([$PYTHON_VERSION])
AC_PATH_PROGS([PYTHON_CONFIG], [python${PYTHON_VERSION}-config python-config], [no])
if test "${PYTHON_CONFIG}" = "no"; then
AC_MSG_ERROR([cannot find python${PYTHON_VERSION}-config or python-config in PATH])
fi
PYTHON_INCLUDES=$($PYTHON-config --includes)
AC_MSG_CHECKING(for python headers using $PYTHON_CONFIG --includes)
PYTHON_INCLUDES=$($PYTHON_CONFIG --includes)
AC_MSG_RESULT($PYTHON_INCLUDES)
AC_SUBST(PYTHON_INCLUDES)
AC_MSG_CHECKING(for python libraries using $PYTHON_CONFIG --libs)
PYTHON_LIBS=$($PYTHON_CONFIG --libs)
AC_MSG_RESULT($PYTHON_LIBS)
AC_SUBST(PYTHON_LIBS)
fi
AM_CONDITIONAL([PYTHON_CRYPTSETUP], [test "x$with_python" = "xyes"])
@@ -327,16 +483,39 @@ CS_STR_WITH([plain-cipher], [cipher for plain mode], [aes])
CS_STR_WITH([plain-mode], [cipher mode for plain mode], [cbc-essiv:sha256])
CS_NUM_WITH([plain-keybits],[key length in bits for plain mode], [256])
CS_STR_WITH([luks1-hash], [hash function for LUKS1 header], [sha1])
CS_STR_WITH([luks1-hash], [hash function for LUKS1 header], [sha256])
CS_STR_WITH([luks1-cipher], [cipher for LUKS1], [aes])
CS_STR_WITH([luks1-mode], [cipher mode for LUKS1], [cbc-essiv:sha256])
CS_STR_WITH([luks1-mode], [cipher mode for LUKS1], [xts-plain64])
CS_NUM_WITH([luks1-keybits],[key length in bits for LUKS1], [256])
CS_STR_WITH([luks2-pbkdf], [Default PBKDF algorithm (pbkdf2 or argon2i/argon2id) for LUKS2], [argon2i])
CS_NUM_WITH([luks1-iter-time], [PBKDF2 iteration time for LUKS1 (in ms)], [2000])
CS_NUM_WITH([luks2-iter-time], [Argon2 PBKDF iteration time for LUKS2 (in ms)], [800])
CS_NUM_WITH([luks2-memory-kb], [Argon2 PBKDF memory cost for LUKS2 (in kB)], [131072])
CS_NUM_WITH([luks2-parallel-threads],[Argon2 PBKDF max parallel cost for LUKS2 (if CPUs available)], [4])
CS_STR_WITH([loopaes-cipher], [cipher for loop-AES mode], [aes])
CS_NUM_WITH([loopaes-keybits],[key length in bits for loop-AES mode], [256])
CS_NUM_WITH([keyfile-size-maxkb],[maximum keyfile size (in kilobytes)], [8192])
CS_NUM_WITH([passphrase-size-max],[maximum keyfile size (in kilobytes)], [512])
CS_NUM_WITH([keyfile-size-maxkb],[maximum keyfile size (in KiB)], [8192])
CS_NUM_WITH([passphrase-size-max],[maximum keyfile size (in characters)], [512])
CS_STR_WITH([verity-hash], [hash function for verity mode], [sha256])
CS_NUM_WITH([verity-data-block], [data block size for verity mode], [4096])
CS_NUM_WITH([verity-hash-block], [hash block size for verity mode], [4096])
CS_NUM_WITH([verity-salt-size], [salt size for verity mode], [32])
CS_NUM_WITH([verity-fec-roots], [parity bytes for verity FEC], [2])
CS_STR_WITH([luks2-lock-path], [path to directory for LUKSv2 locks], [/run/lock/cryptsetup])
test -z "$with_luks2_lock_path" && with_luks2_lock_path=/run/lock/cryptsetup
test "${with_luks2_lock_path:0:1}" = "/" || AC_MSG_ERROR([--with-luks2-lock-path argument must be an absolute path.])
DEFAULT_LUKS2_LOCK_PATH=$with_luks2_lock_path
AC_SUBST(DEFAULT_LUKS2_LOCK_PATH)
CS_NUM_WITH([luks2-lock-dir-perms], [default luks2 locking directory permissions], [0700])
test -z "$with_luks2_lock_dir_perms" && with_luks2_lock_dir_perms=0700
DEFAULT_LUKS2_LOCK_DIR_PERMS=$with_luks2_lock_dir_perms
AC_SUBST(DEFAULT_LUKS2_LOCK_DIR_PERMS)
dnl ==========================================================================
@@ -344,12 +523,19 @@ AC_CONFIG_FILES([ Makefile
lib/Makefile
lib/libcryptsetup.pc
lib/crypto_backend/Makefile
lib/crypto_backend/argon2/Makefile
lib/luks1/Makefile
lib/luks2/Makefile
lib/loopaes/Makefile
lib/verity/Makefile
lib/tcrypt/Makefile
lib/integrity/Makefile
src/Makefile
po/Makefile.in
man/Makefile
tests/Makefile
python/Makefile
scripts/Makefile
scripts/cryptsetup_tmpfiles.conf
])
AC_OUTPUT

887
docs/ChangeLog.old Normal file
View File

@@ -0,0 +1,887 @@
2012-12-21 Milan Broz <gmazyland@gmail.com>
* Since version 1.6 This file is no longer maintained.
* See version control log http://code.google.com/p/cryptsetup/source/list
2012-10-11 Milan Broz <gmazyland@gmail.com>
* Added keyslot checker (by Arno Wagner).
* Version 1.5.1.
2012-09-11 Milan Broz <gmazyland@gmail.com>
* Add crypt_keyslot_area() API call.
2012-08-27 Milan Broz <gmazyland@gmail.com>
* Optimize seek to keyfile-offset (Issue #135, thx to dreisner).
* Fix luksHeaderBackup for very old v1.0 unaligned LUKS headers.
2012-08-12 Milan Broz <gmazyland@gmail.com>
* Allocate loop device late (only when real block device needed).
* Rework underlying device/file access functions.
* Create hash image if doesn't exist in veritysetup format.
* Provide better error message if running as non-root user (device-mapper, loop).
2012-07-10 Milan Broz <gmazyland@gmail.com>
* Version 1.5.0.
2012-06-25 Milan Broz <gmazyland@gmail.com>
* Add --device-size option for reencryption tool.
* Switch to use unit suffix for --reduce-device-size option.
* Remove open device debugging feature (no longer needed).
* Fix library name for FIPS check.
2012-06-20 Milan Broz <gmazyland@gmail.com>
* Version 1.5.0-rc2.
2012-06-18 Milan Broz <gmazyland@gmail.com>
* Introduce cryptsetup-reencrypt - experimental offline LUKS reencryption tool.
* Fix luks-header-from-active script (do not use LUKS header on-disk, add UUID).
* Add --test-passphrase option for luksOpen (check passphrase only).
2012-06-11 Milan Broz <gmazyland@gmail.com>
* Introduce veritysetup for dm-verity target management.
* Version 1.5.0-rc1.
2012-06-10 Milan Broz <gmazyland@gmail.com>
* Both data and header device can now be a file.
* Loop is automatically allocated in crypt_set_data_device().
* Require only up to last keyslot area for header device (ignore data offset).
* Fix header backup and restore to work on files with large data offset.
2012-05-27 Milan Broz <gmazyland@gmail.com>
* Fix readonly activation if underlying device is readonly (1.4.0).
* Include stddef.h in libdevmapper.h (size_t definition).
* Version 1.4.3.
2012-05-21 Milan Broz <gmazyland@gmail.com>
* Add --enable-fips for linking with fipscheck library.
* Initialize binary and library selfcheck if running in FIPS mode.
* Use FIPS RNG in FIPS mode for KEY and SALT (only gcrypt backend supported).
2012-05-09 Milan Broz <gmazyland@gmail.com>
* Fix keyslot removal (wipe keyslot) for device with 4k hw block (1.4.0).
* Allow empty cipher (cipher_null) for testing.
2012-05-02 Milan Broz <gmazyland@gmail.com>
* Fix loop mapping on readonly file.
* Relax --shared test, allow mapping even for overlapping segments.
* Support shared flag for LUKS devices (dangerous).
* Switch on retry on device remove for libdevmapper.
* Allow "private" activation (skip some udev global rules) flag.
2012-04-09 Milan Broz <gmazyland@gmail.com>
* Fix header check to support old (cryptsetup 1.0.0) header alignment. (1.4.0)
* Version 1.4.2.
2012-03-16 Milan Broz <gmazyland@gmail.com>
* Add --keyfile-offset and --new-keyfile-offset parameters to API and CLI.
* Add repair command and crypt_repair() for known LUKS metadata problems repair.
* Allow to specify --align-payload only for luksFormat.
2012-03-16 Milan Broz <mbroz@redhat.com>
* Unify password verification option.
* Support password verification with quiet flag if possible. (1.2.0)
* Fix retry if entered passphrases (with verify option) do not match.
* Support UUID=<LUKS_UUID> format for device specification.
2012-02-11 Milan Broz <mbroz@redhat.com>
* Add --master-key-file option to luksOpen (open using volume key).
2012-01-12 Milan Broz <mbroz@redhat.com>
* Fix use of empty keyfile.
2011-11-13 Milan Broz <mbroz@redhat.com>
* Fix error message for luksClose and detached LUKS header.
* Allow --header for status command to get full info with detached header.
2011-11-09 Milan Broz <mbroz@redhat.com>
* Version 1.4.1.
2011-11-05 Milan Broz <mbroz@redhat.com>
* Merge pycryptsetup (Python libcryptsetup bindings).
* Fix stupid typo in set_iteration_time API call.
* Fix cryptsetup status output if parameter is device path.
2011-10-27 Milan Broz <mbroz@redhat.com>
* Fix crypt_get_volume_key_size() for plain device.
* Fix FSF address in license text.
2011-10-25 Milan Broz <mbroz@redhat.com>
* Print informative message in isLuks only in verbose mode.
* Version 1.4.0.
2011-10-10 Milan Broz <mbroz@redhat.com>
* Version 1.4.0-rc1.
2011-10-05 Milan Broz <mbroz@redhat.com>
* Support Nettle 2.4 crypto backend (for ripemd160).
* If device is not rotational, do not use Gutmann wipe method.
* Add crypt_last_error() API call.
* Fix luksKillSLot exit code if slot is inactive or invalid.
* Fix exit code if passphrases do not match in luksAddKey.
* Add LUKS on-disk format description into package.
2011-09-22 Milan Broz <mbroz@redhat.com>
* Support key-slot option for luksOpen (use only explicit keyslot).
2011-08-22 Milan Broz <mbroz@redhat.com>
* Add more paranoid checks for LUKS header and keyslot attributes.
* Fix crypt_load to properly check device size.
* Use new /dev/loop-control (kernel 3.1) if possible.
* Enhance check of device size before writing LUKS header.
* Do not allow context format of already formatted device.
2011-07-25 Milan Broz <mbroz@redhat.com>
* Remove hash/hmac restart from crypto backend and make it part of hash/hmac final.
* Improve check for invalid offset and size values.
2011-07-19 Milan Broz <mbroz@redhat.com>
* Revert default initialisation of volume key in crypt_init_by_name().
* Do not allow key retrieval while suspended (key could be wiped).
* Do not allow suspend for non-LUKS devices.
* Support retries and timeout parameters for luksSuspend.
* Add --header option for detached metadata (on-disk LUKS header) device.
* Add crypt_init_by_name_and_header() and crypt_set_data_device() to API.
* Allow different data offset setting for detached header.
2011-07-07 Milan Broz <mbroz@redhat.com>
* Remove old API functions (all functions using crypt_options).
* Add --enable-discards option to allow discards/TRIM requests.
* Add crypt_get_iv_offset() function to API.
2011-07-01 Milan Broz <mbroz@redhat.com>
* Add --shared option for creating non-overlapping crypt segments.
* Add shared flag to libcryptsetup api.
* Fix plain crypt format parameters to include size option (API change).
2011-06-08 Milan Broz <mbroz@redhat.com>
* Fix return code for status command when device doesn't exists.
2011-05-24 Milan Broz <mbroz@redhat.com>
* Version 1.3.1.
2011-05-17 Milan Broz <mbroz@redhat.com>
* Fix keyfile=- processing in create command (1.3.0).
* Simplify device path status check.
2011-05-03 Milan Broz <mbroz@redhat.com>
* Do not ignore size argument for create command (1.2.0).
2011-04-18 Milan Broz <mbroz@redhat.com>
* Fix error paths in blockwise code and lseek_write call.
* Add Nettle crypto backend support.
2011-04-05 Milan Broz <mbroz@redhat.com>
* Version 1.3.0.
2011-03-22 Milan Broz <mbroz@redhat.com>
* Also support --skip and --hash option for loopaesOpen.
* Fix return code when passphrase is read from pipe.
* Document cryptsetup exit codes.
2011-03-18 Milan Broz <mbroz@redhat.com>
* Respect maximum keyfile size paramater.
* Introduce maximum default keyfile size, add configure option.
* Require the whole key read from keyfile in create command (broken in 1.2.0).
* Fix offset option for loopaesOpen.
* Lock memory also in luksDump command.
* Version 1.3.0-rc2.
2011-03-14 Milan Broz <mbroz@redhat.com>
* Version 1.3.0-rc1.
2011-03-11 Milan Broz <mbroz@redhat.com>
* Add loop manipulation code and support mapping of images in file.
* Add backing device loop info into status message.
* Add luksChangeKey command.
2011-03-05 Milan Broz <mbroz@redhat.com>
* Add exception to COPYING for binary distribution linked with OpenSSL library.
* Set secure data flag (wipe all ioclt buffers) if devmapper library supports it.
2011-01-29 Milan Broz <mbroz@redhat.com>
* Fix mapping removal if device disappeared but node still exists.
* Fix luksAddKey return code if master key is used.
2011-01-25 Milan Broz <mbroz@redhat.com>
* Add loop-AES handling (loopaesOpen and loopaesClose commands).
(requires kernel 2.6.38 and above)
2011-01-05 Milan Broz <mbroz@redhat.com>
* Fix static build (--disable-static-cryptsetup now works properly).
2010-12-30 Milan Broz <mbroz@redhat.com>
* Add compile time crypto backends implementation
(gcrypt, OpenSSL, NSS and userspace Linux kernel crypto api).
* Currently NSS is lacking ripemd160, cannot provide full plain compatibility.
* Use --with-crypto_backend=[gcrypt|openssl|nss|kernel] to configure.
2010-12-20 Milan Broz <mbroz@redhat.com>
* Version 1.2.0.
2010-11-25 Milan Broz <mbroz@redhat.com>
* Fix crypt_activate_by_keyfile() to work with PLAIN devices.
* Fix create command to properly handle keyfile size.
2010-11-16 Milan Broz <mbroz@redhat.com>
* Version 1.2.0-rc1.
2010-11-13 Milan Broz <mbroz@redhat.com>
* Fix password callback call.
* Fix default plain password entry from terminal in activate_by_passphrase.
* Add --dump-master-key option for luksDump to allow volume key dump.
* Allow to activate by internally cached volume key
(format/activate without keyslots active - used for temporary devices).
* Initialize volume key from active device in crypt_init_by_name()
* Fix cryptsetup binary exitcodes.
* Increase library version (still binary compatible with 1.1.x release).
2010-11-01 Milan Broz <mbroz@redhat.com>
* No longer support luksDelKey, reload and --non-exclusive.
* Remove some obsolete info from man page.
* Add crypt_get_type(), crypt_resize(), crypt_keyslot_max()
and crypt_get_active_device() to API.
* Rewrite all implementations in cryptsetup to new API.
* Fix luksRemoveKey to behave as documented (do not ask
for remaining keyslot passphrase).
* Add more regression tests for commands.
* Disallow mapping of device which is already in use (mapped or mounted).
* Disallow luksFormat on device in use.
2010-10-27 Milan Broz <mbroz@redhat.com>
* Rewrite cryptsetup luksFormat, luksOpen, luksAddKey to use new API
to allow adding new features.
* Implement --use-random and --use-urandom for luksFormat to allow
setting of RNG for volume key generator.
* Add crypt_set_rng_type() and crypt_get_rng_type() to API.
* Add crypt_set_uuid() to API.
* Allow UUID setting in luksFormat and luksUUID (--uuid parameter).
* Add --keyfile-size and --new-keyfile-size (in bytes) size and disallow overloading
of --key-size for limiting keyfile reads.
* Fix luksFormat to properly use key file with --master-key-file switch.
* Fix possible double free when handling master key file.
2010-10-17 Milan Broz <mbroz@redhat.com>
* Add crypt_get_device_name() to API (get underlying device name).
* Change detection for static libraries.
* Fix pkg-config use in automake scripts.
* Remove --disable-shared-library switch and handle static library build
by common libtool logic (using --enable-static).
* Add --enable-static-cryptsetup option to build cryptsetup.static binary
together with shared build.
2010-08-05 Milan Broz <mbroz@redhat.com>
* Wipe iteration and salt after KillSlot in LUKS header.
* Rewrite file differ test to C (and fix it to really work).
* Switch to 1MiB default alignment of data.
For more info see https://bugzilla.redhat.com/show_bug.cgi?id=621684
* Do not query non-existent device twice (cryptsetup status /dev/nonexistent).
* Check if requested hash is supported before writing LUKS header.
2010-07-28 Arno Wagner <arno@wagner.name>
* Add FAQ (Frequently Asked Questions) file to distribution.
2010-07-03 Milan Broz <mbroz@redhat.com>
* Fix udev support for old libdevmapper with not compatible definition.
* Version 1.1.3.
2010-06-01 Milan Broz <mbroz@redhat.com>
* Fix device alignment ioctl calls parameters.
* Fix activate_by_* API calls to handle NULL device name as documented.
2010-05-30 Milan Broz <mbroz@redhat.com>
* Version 1.1.2.
2010-05-27 Milan Broz <mbroz@redhat.com>
* Fix luksFormat/luksOpen reading passphrase from stdin and "-" keyfile.
* Support --key-file/-d option for luksFormat.
* Fix description of --key-file and add --verbose and --debug options to man page.
* Add verbose log level and move unlocking message there.
* Remove device even if underlying device disappeared.
* Fix (deprecated) reload device command to accept new device argument.
2010-05-23 Milan Broz <mbroz@redhat.com>
* Fix luksClose operation for stacked DM devices.
* Version 1.1.1.
2010-05-03 Milan Broz <mbroz@redhat.com>
* Fix automatic dm-crypt module loading.
* Escape hyphens in man page.
* Version 1.1.1-rc2.
2010-04-30 Milan Broz <mbroz@redhat.com>
* Try to use pkgconfig for device mapper library.
* Detect old dm-crypt module and disable LUKS suspend/resume.
* Fix apitest to work on older systems.
* Allow no hash specification in plain device constructor.
* Fix luksOpen reading of passphrase on stdin (if "-" keyfile specified).
* Fix isLuks to initialise crypto backend (blkid instead is suggested anyway).
* Version 1.1.1-rc1.
2010-04-12 Milan Broz <mbroz@redhat.com>
* Fix package config to use proper package version.
* Avoid class C++ keyword in library header.
* Detect and use devmapper udev support if available (disable by --disable-udev).
2010-04-06 Milan Broz <mbroz@redhat.com>
* Prefer some device paths in status display.
* Support device topology detectionfor data alignment.
2010-02-25 Milan Broz <mbroz@redhat.com>
* Do not verify unlocking passphrase in luksAddKey command.
* Properly initialise crypto backend in header backup/restore commands.
2010-01-17 Milan Broz <mbroz@redhat.com>
* If gcrypt compiled with capabilities, document workaround for cryptsetup (see lib/gcrypt.c).
* Version 1.1.0.
2010-01-10 Milan Broz <mbroz@redhat.com>
* Fix initialisation of gcrypt duting luksFormat.
* Convert hash name to lower case in header (fix sha1 backward comatible header)
* Check for minimum required gcrypt version.
2009-12-30 Milan Broz <mbroz@redhat.com>
* Fix key slot iteration count calculation (small -i value was the same as default).
* The slot and key digest iteration minimun is now 1000.
* The key digest iteration # is calculated from iteration time (approx 1/8 of that).
* Version 1.1.0-rc4.
2009-12-11 Milan Broz <mbroz@redhat.com>
* Fix error handling during reading passhrase.
2009-12-01 Milan Broz <mbroz@redhat.com>
* Allow changes of default compiled-in cipher parameters through configure.
* Switch default key size for LUKS to 256bits.
* Switch default plain mode to aes-cbc-essiv:sha256 (default is backward incompatible!).
2009-11-14 Milan Broz <mbroz@redhat.com>
* Add CRYPT_ prefix to enum defined in libcryptsetup.h.
* Fix status call to fail when running as non-root user.
* Check in configure if selinux libraries are required in static version.
* Add temporary debug code to find processes locking internal device.
* Simplify build system, use autopoint and clean gettext processing.
* Use proper NLS macros and detection (so the message translation works again).
* Version 1.1.0-rc3.
2009-09-30 Milan Broz <mbroz@redhat.com>
* Fix exported symbols and versions in libcryptsetup.
* Do not use internal lib functions in cryptsetup.
* Add crypt_log to library.
* Fix crypt_remove_device (remove, luksClose) implementation.
* Move dm backend initialisation to library calls.
* Move duplicate Command failed message to verbose level (error is printed always).
* Add some password and used algorithms notes to man page.
* Version 1.1.0-rc2.
2009-09-28 Milan Broz <mbroz@redhat.com>
* Add luksHeaderBackup and luksHeaderRestore commands.
* Fail passphrase read if piped input no longer exists.
* Version 1.1.0-rc1.
2009-09-15 Milan Broz <mbroz@redhat.com>
* Initialize crypto library before LUKS header load.
* Fix manpage to not require --size which expands to device size by default.
2009-09-10 Milan Broz <mbroz@redhat.com>
* Clean up Makefiles and configure script.
* Version 1.1.0-test0.
2009-09-08 Milan Broz <mbroz@redhat.com>
* Use dm-uuid for all crypt devices, contains device type and name now.
* Try to read first sector from device to properly check that device is ready.
2009-09-02 Milan Broz <mbroz@redhat.com>
* Add luksSuspend (freeze device and wipe key) and luksResume (with provided passphrase).
2009-08-30 Milan Broz <mbroz@redhat.com>
* Require device device-mapper to build and do not use backend wrapper for dm calls.
* Move memory locking and dm initialization to command layer.
* Increase priority of process if memory is locked.
* Add log macros and make logging modre consitent.
* Move command successful messages to verbose level.
* Introduce --debug parameter.
* Move device utils code and provide context parameter (for log).
* Keyfile now must be provided by path, only stdin file descriptor is used (api only).
* Do not call isatty() on closed keyfile descriptor.
* Run performance check for PBKDF2 from LUKS code, do not mix hash algoritms results.
* Add ability to provide pre-generated master key and UUID in LUKS header format.
* Add LUKS function to verify master key digest.
* Move key slot manuipulation function into LUKS specific code.
* Replace global options struct with separate parameters in helper functions.
* Add new libcryptsetup API (documented in libcryptsetup.h).
* Implement old API calls using new functions.
* Remove old API code helper functions.
* Add --master-key-file option for luksFormat and luksAddKey.
2009-08-17 Milan Broz <mbroz@redhat.com>
* Fix PBKDF2 speed calculation for large passhrases.
* Allow using passphrase provided in options struct for LuksOpen.
* Allow restrict keys size in LuksOpen.
2009-07-30 Milan Broz <mbroz@redhat.com>
* Fix errors when compiled with LUKS_DEBUG.
* Print error when getline fails.
* Remove po/cryptsetup-luks.pot, it's autogenerated.
* Return ENOENT for empty keyslots, EINVAL will be used later for other type of error.
* Switch PBKDF2 from internal SHA1 to libgcrypt, make hash algorithm not hardcoded to SHA1 here.
* Add required parameters for changing hash used in LUKS key setup scheme.
* Do not export simple XOR helper now used only inside AF functions.
* Completely remove internal SHA1 implementanion code, not needed anymore.
* Enable hash algorithm selection for LUKS through -h luksFormat option.
2009-07-28 Milan Broz <mbroz@redhat.com>
* Pad luks header to 512 sector size.
* Rework read/write blockwise to not split operation to many pieces.
* Use posix_memalign if available.
2009-07-22 Milan Broz <mbroz@redhat.com>
* Fix segfault if provided slot in luksKillslot is invalid.
* Remove unneeded timeout when remove of temporary device succeeded.
2009-07-22 Milan Broz <mbroz@redhat.com>
* version 1.0.7
2009-07-16 Milan Broz <mbroz@redhat.com>
* Allow removal of last slot in luksRemoveKey and luksKillSlot.
2009-07-11 Milan Broz <mbroz@redhat.com>
* Add --disable-selinux option and fix static build if selinux is required.
* Reject unsupported --offset and --skip options for luksFormat and update man page.
2009-06-22 Milan Broz <mbroz@redhat.com>
* Summary of changes in subversion for 1.0.7-rc1:
* Various man page fixes.
* Set UUID in device-mapper for LUKS devices.
* Retain readahead of underlying device.
* Display device name when asking for password.
* Check device size when loading LUKS header. Remove misleading error message later.
* Add error hint if dm-crypt mapping failed.
* Use better error messages if device doesn't exist or is already used by other mapping.
* Fix make distcheck.
* Check if all slots are full during luksAddKey.
* Fix segfault in set_error.
* Code cleanups, remove precompiled pot files, remove unnecessary files from po directory
* Fix uninitialized return value variable in setup.c.
* Code cleanups. (thanks to Ivan Stankovic)
* Fix wrong output for remaining key at key deletion.
* Allow deletion of key slot while other keys have the same key information.
* Add missing AM_PROG_CC_C_O to configure.in
* Remove duplicate sentence in man page.
* Wipe start of device (possible fs signature) before LUKS-formatting.
* Do not process configure.in in hidden directories.
* Return more descriptive error in case of IO or header format error.
* Use remapping to error target instead of calling udevsettle for temporary crypt device.
* Check device mapper communication and warn user if device-mapper support missing in kernel.
* Fix signal handler to properly close device.
* write_lseek_blockwise: declare innerCount outside the if block.
* add -Wall to the default CFLAGS. fix some signedness issues.
* Error handling improvement.
* Add non-exclusive override to interface definition.
* Refactor key slot selection into keyslot_from_option.
2007-05-01 Clemens Fruhwirth <clemens@endorphin.org>
* lib/backends.c, man/cryptsetup.8: Apply patch from Ludwig Nussel
<ludwig.nussel@suse.de>, for old SuSE compat hashing.
2007-04-16 Clemens Fruhwirth <clemens@endorphin.org>
* Summary of changes in subversion:
Fix segfault for key size > 32 bytes.
Kick ancient header version conversion.
Fix http://bugs.debian.org/403075
No passwort retrying for I/O errors.
Fix hang on "-i 0".
Fix parenthesization error that prevented --tries from working
correctly.
2006-11-28 gettextize <bug-gnu-gettext@gnu.org>
* m4/gettext.m4: Upgrade to gettext-0.15.
* m4/glibc2.m4: New file, from gettext-0.15.
* m4/intmax.m4: New file, from gettext-0.15.
* m4/inttypes-h.m4: New file, from gettext-0.15.
* m4/inttypes-pri.m4: Upgrade to gettext-0.15.
* m4/lib-link.m4: Upgrade to gettext-0.15.
* m4/lib-prefix.m4: Upgrade to gettext-0.15.
* m4/lock.m4: New file, from gettext-0.15.
* m4/longdouble.m4: New file, from gettext-0.15.
* m4/longlong.m4: New file, from gettext-0.15.
* m4/nls.m4: Upgrade to gettext-0.15.
* m4/po.m4: Upgrade to gettext-0.15.
* m4/printf-posix.m4: New file, from gettext-0.15.
* m4/signed.m4: New file, from gettext-0.15.
* m4/size_max.m4: New file, from gettext-0.15.
* m4/visibility.m4: New file, from gettext-0.15.
* m4/wchar_t.m4: New file, from gettext-0.15.
* m4/wint_t.m4: New file, from gettext-0.15.
* m4/xsize.m4: New file, from gettext-0.15.
* m4/Makefile.am: New file.
* configure.in (AC_OUTPUT): Add m4/Makefile.
(AM_GNU_GETTEXT_VERSION): Bump to 0.15.
2006-10-22 David Härdeman <david@hardeman.nu>
* Allow hashing of keys passed through stdin.
2006-10-13 Clemens Fruhwirth <clemens@endorphin.org>
* configure.in: 1.0.4 release
2006-10-13 Clemens Fruhwirth <clemens@endorphin.org>
* man/cryptsetup.8: Document --tries switch; patch by Jonas
Meurer.
2006-10-13 Clemens Fruhwirth <clemens@endorphin.org>
* lib/setup.c: Added terminal timeout rewrite as forwarded by
Jonas Meurer
2006-10-04 Clemens Fruhwirth <clemens@endorphin.org>
* Merged patch from Marc Merlin <marc@merlins.org> to allow user
selection of key slot.
2006-09-26 gettextize <bug-gnu-gettext@gnu.org>
* m4/codeset.m4: Upgrade to gettext-0.14.4.
* m4/gettext.m4: Upgrade to gettext-0.14.4.
* m4/glibc2.m4: New file, from gettext-0.14.4.
* m4/glibc21.m4: Upgrade to gettext-0.14.4.
* m4/iconv.m4: Upgrade to gettext-0.14.4.
* m4/intdiv0.m4: Upgrade to gettext-0.14.4.
* m4/intmax.m4: New file, from gettext-0.14.4.
* m4/inttypes.m4: Upgrade to gettext-0.14.4.
* m4/inttypes_h.m4: Upgrade to gettext-0.14.4.
* m4/inttypes-pri.m4: Upgrade to gettext-0.14.4.
* m4/isc-posix.m4: Upgrade to gettext-0.14.4.
* m4/lcmessage.m4: Upgrade to gettext-0.14.4.
* m4/lib-ld.m4: Upgrade to gettext-0.14.4.
* m4/lib-link.m4: Upgrade to gettext-0.14.4.
* m4/lib-prefix.m4: Upgrade to gettext-0.14.4.
* m4/longdouble.m4: New file, from gettext-0.14.4.
* m4/longlong.m4: New file, from gettext-0.14.4.
* m4/nls.m4: Upgrade to gettext-0.14.4.
* m4/po.m4: Upgrade to gettext-0.14.4.
* m4/printf-posix.m4: New file, from gettext-0.14.4.
* m4/progtest.m4: Upgrade to gettext-0.14.4.
* m4/signed.m4: New file, from gettext-0.14.4.
* m4/size_max.m4: New file, from gettext-0.14.4.
* m4/stdint_h.m4: Upgrade to gettext-0.14.4.
* m4/uintmax_t.m4: Upgrade to gettext-0.14.4.
* m4/ulonglong.m4: Upgrade to gettext-0.14.4.
* m4/wchar_t.m4: New file, from gettext-0.14.4.
* m4/wint_t.m4: New file, from gettext-0.14.4.
* m4/xsize.m4: New file, from gettext-0.14.4.
* Makefile.am (ACLOCAL_AMFLAGS): New variable.
* configure.in (AM_GNU_GETTEXT_VERSION): Bump to 0.14.4.
2006-08-04 Clemens Fruhwirth <clemens@endorphin.org>
* configure.in: 1.0.4-rc2
2006-08-04 Clemens Fruhwirth <clemens@endorphin.org>
* luks/Makefile.am: Add a few regression tests
2006-08-04 Clemens Fruhwirth <clemens@endorphin.org>
* lib/setup.c (get_key): Applied patch from David Härdeman
<david@2gen.com> for reading binary keys from stdin using
the "-" as key file.
2006-08-04 Clemens Fruhwirth <clemens@endorphin.org>
* lib/setup.c (__crypt_luks_add_key): For checking options struct
(optionsCheck) filter out CRYPT_FLAG_VERIFY and
CRYPT_FLAG_VERIFY_IF_POSSIBLE, so that in no case password verification is done
for password retrieval.
2006-08-04 Clemens Fruhwirth <clemens@endorphin.org>
* configure.in: Merge Patch from http://bugs.gentoo.org/show_bug.cgi?id=132126 for sepol
2006-07-23 Clemens Fruhwirth <clemens@endorphin.org>
* Applied patches from David Härdeman <david@2gen.com> to fix 64
bit compiler warning issues.
2006-05-19 Clemens Fruhwirth <clemens@endorphin.org>
* Applied patches from Jonas Meurer
- fix terminal status after timeout
- add remark for --tries to manpage
- allow more than 32 chars from standard input.
- exit status fix for cryptsetup status.
2006-05-06 Clemens Fruhwirth <clemens@endorphin.org>
* src/cryptsetup.c (yesDialog): Fix getline problem for 64-bit archs.
2006-04-05 Clemens Fruhwirth <clemens@endorphin.org>
* configure.in: Release 1.0.3.
* Applied patch by Johannes Weißl for more meaningful exit codes
and password retries
2006-03-30 Clemens Fruhwirth <clemens@endorphin.org>
* lib/setup.c (__crypt_create_device): (char *) -> (const char *)
2006-03-30 Clemens Fruhwirth <clemens@endorphin.org>
* Apply alignPayload patch from Peter Palfrader <weasel@debian.org>
2006-03-15 Clemens Fruhwirth <clemens@endorphin.org>
* configure.in: 1.0.3-rc3. Most unplease release ever.
* lib/setup.c (__crypt_create_device): More verbose error message.
2006-02-26 Clemens Fruhwirth <clemens@endorphin.org>
* lib/setup.c: Revert to 1.0.1 key reading.
2006-02-25 Clemens Fruhwirth <clemens@endorphin.org>
* man/cryptsetup.8: merge patch from Jonas Meurer
2006-02-25 Clemens Fruhwirth <clemens@endorphin.org>
* configure.in: 1.0.3-rc2
2006-02-25 Clemens Fruhwirth <clemens@endorphin.org>
* lib/libdevmapper.c (dm_create_device): Remove dup check here.
* lib/setup.c (__crypt_luks_open): Adopt same dup check as regular
create command.
2006-02-22 Clemens Fruhwirth <clemens@endorphin.org>
* configure.in: Spin 1.0.3-rc1
2006-02-22 Clemens Fruhwirth <clemens@endorphin.org>
* src/cryptsetup.c (action_create): Change defaulting.
(action_luksFormat): Change defaulting.
* lib/setup.c (parse_into_name_and_mode): Revert that default
change. This is FORBIDDEN here, as it will change cryptsetup
entire default. This is BAD in a non-LUKS world.
2006-02-21 Clemens Fruhwirth <clemens@endorphin.org>
* luks/keyencryption.c (setup_mapping): Add proper size restriction to mapping.
(LUKS_endec_template): Add more verbose error message.
2006-02-21 Clemens Fruhwirth <clemens@endorphin.org>
* lib/libdevmapper.c (dm_query_device): Incorporate patch from
Bastian Blank
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=344313
2006-02-21 Clemens Fruhwirth <clemens@endorphin.org>
* src/cryptsetup.c: Rename show_error -> show_status.
2006-02-20 Clemens Fruhwirth <clemens@endorphin.org>
* lib/libdevmapper.c (dm_create_device): Prevent existing mapping
from being removed when a mapping with the same name is added
* Add timeout patch from Jonas Meurer
* src/cryptsetup.c: Remove conditional error printing to enable
printing the no-error msg (Command successful). Verify passphrase
for LUKS volumes.
(main): Add no-verify-passphrase
* lib/setup.c (parse_into_name_and_mode): Change default mode complition to essiv:sha256.
2006-01-04 Clemens Fruhwirth <clemens@endorphin.org>
* src/cryptsetup.c (help): Merge patch from Gentoo: change gettext(..) to _(..).
2005-12-06 Clemens Fruhwirth <clemens@endorphin.org>
* man/cryptsetup.8: Correct "seconds" to "microseconds" in the explaination for -i.
2005-11-09 Clemens Fruhwirth <clemens@endorphin.org>
* src/cryptsetup.c (main): Add version string.
2005-11-08 Clemens Fruhwirth <clemens@endorphin.org>
* lib/backends.c: compile fix.
2005-09-11 Clemens Fruhwirth <clemens@endorphin.org>
* lib/setup.c (get_key): Fixed another incompatibility from my
get_key rewrite with original cryptsetup.
2005-09-11 Clemens Fruhwirth <clemens@endorphin.org>
* Merged changes from Florian Knauf's fk02 branch.
2005-09-08 Clemens Fruhwirth <clemens@endorphin.org>
* lib/setup.c (get_key): Fixed another incompatiblity with
original cryptsetup.
2005-08-20 Clemens Fruhwirth <clemens@endorphin.org>
* Checked in a patch from Michael Gebetsroither <gebi@sbox.tugraz.at>
to silent all confirmation dialogs.
2005-06-23 Clemens Fruhwirth <clemens@endorphin.org>
* src/cryptsetup.c (help): print PACKAGE_STRING
2005-06-20 Clemens Fruhwirth <clemens@endorphin.org>
* luks/keymanage.c (LUKS_set_key): Security check against header manipulation
* src/cryptsetup.c (action_luksDelKey): Safety check in luksDelKey
* luks/keymanage.c: Changed disk layout generation to align key material to 4k boundaries.
(LUKS_is_last_keyslot): Added LUKS_is_last_keyslot function.
* Applied patch from Bill Nottingham fixing a lot of prototypes.
* src/cryptsetup.c (action_luksOpen): Add support for -r flag.
* configure.in: Version bump 1.0.1
2005-06-16 Clemens Fruhwirth <clemens@endorphin.org>
* lib/setup.c (__crypt_luks_open): Remove mem leaking of dmCipherSpec.
(get_key): Fix missing zero termination for read string.
2005-06-12 Clemens Fruhwirth <clemens@endorphin.org>
* luks/keyencryption.c (setup_mapping): Added CRYPT_FLAG_READONLY in case of O_RDONLY mode
2005-06-11 Clemens Fruhwirth <clemens@endorphin.org>
* configure.in: Version bump 1.0.1-pre
2005-06-09 Clemens Fruhwirth <clemens@endorphin.org>
* lib/utils.c: Added write_llseek_blocksize method to support sector wiping on sector_size != 512
media
2005-05-23 Clemens Fruhwirth <clemens@endorphin.org>
* lib/setup.c (crypt_luksDelKey): Added missing return statement
(setup_leave): Added missing return statement
* luks/keyencryption.c (clear_mapping): Added missing return statement
2005-05-19 Clemens Fruhwirth <clemens@endorphin.org>
* lib/utils.c (write_blockwise, read_blockwise): Changed to soft bsize instead of SECTOR_SIZE
* luks/keymanage.c (wipe): Changed open mode to O_DIRECT | O_SYNC, and changed write
to use the blockwise write helper
2005-04-21 Clemens Fruhwirth <clemens@endorphin.org>
* man/cryptsetup.8: Corrected an error, thanks to Dick Middleton.
2005-04-09 Clemens Fruhwirth <clemens@endorphin.org>
* luks/sha/hmac.c: Add 64 bit bug fix courtesy to
Oliver Paukstadt <pstadt@sourcentral.org>.
* luks/pbkdf.c, luks/keyencryption.c, luks/keymanage.c, luks/af.c: Added a license
disclaimer and remove option for "any future GPL versions".
2005-03-25 Clemens Fruhwirth <clemens@endorphin.org>
* configure.in: man page Makefile. Version bump 1.0.
* man/cryptsetup.8: finalize man page and move to section 8.
* src/cryptsetup.c (action_luksFormat): Add "are you sure" for interactive sessions.
* lib/setup.c (crypt_luksDump), src/cryptsetup.c: add LUKS dump command
2005-03-24 Clemens Fruhwirth <clemens@endorphin.org>
* src/cryptsetup.c, luks/Makefile.am (test), lib/setup.c (setup_enter):
rename luksInit to luksFormat
2005-03-12 Clemens Fruhwirth <clemens@endorphin.org>
* man/cryptsetup.1: Add man page.
* lib/setup.c: Remove unneccessary LUKS_write_phdr call, so the
phdr is written after passphrase reading, so the user can change
his mind, and not have a partial written LUKS header on it's disk.
2005-02-09 Clemens Fruhwirth <clemens@endorphin.org>
* luks/keymanage.c (LUKS_write_phdr): converted argument phdr to
pointer, and make a copy of phdr for conversion
* configure.in: Version dump.
* luks/keyencryption.c: Convert to read|write_blockwise.
* luks/keymanage.c: Convert to read|write_blockwise.
* lib/utils.c: Add read|write_blockwise functions, to use in
O_DIRECT file accesses.
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 Jana Saout <jana@saout.de>
* lib/: libcryptsetup.h, libdevmapper.c: Small fixes.
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
keep track of malloc'ed return values in struct crypt_options and
add a function to free the memory. Also add a readonly flag to
libcryptsetup.
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,
lib/libcryptsetup.h, lib/libdevmapper.c, lib/setup.c,
lib/utils.c, po/de.po, src/Makefile.am, src/cryptsetup.c: More
reorganization work.
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,
lib/libdevmapper.c, lib/setup.c, lib/utils.c, po/de.po,
src/Makefile.am: BLKGETSIZE64 fixes and started modularity
enhancements
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 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 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: Initial revision

56
docs/Keyring.txt Normal file
View File

@@ -0,0 +1,56 @@
Integration with kernel keyring service
---------------------------------------
We have two different use cases for kernel keyring service:
I) Volume keys
Since upstream kernel 4.10 dm-crypt device mapper target allows loading volume
key (VK) in kernel keyring service. The key offloaded in kernel keyring service
is only referenced (by key description) in dm-crypt target and the VK is therefore
no longer stored directly in dm-crypt target. Starting with cryptsetup 2.0 we
load VK in kernel keyring by default for LUKSv2 devices (when dm-crypt with the
feature is available).
Currently cryptsetup loads VK in 'logon' type kernel key so that VK is passed in
the kernel and can't be read from userspace afterward. Also cryptsetup loads VK in
thread keyring (before passing the reference to dm-crypt target) so that the key
lifetime is directly bound to the process that performs the dm-crypt setup. When
cryptsetup process exits (for whatever reason) the key gets unlinked in kernel
automatically. In summary, the key description visible in dm-crypt table line is
a reference to VK that usually no longer exists in kernel keyring service if you
used cryptsetup to for device activation.
Using this feature dm-crypt no longer maintains a direct key copy (but there's
always at least one copy in kernel crypto layer).
II) Keyslot passphrase
The second use case for kernel keyring is to allow cryptsetup reading the keyslot
passphrase stored in kernel keyring instead. The user may load passphrase in kernel
keyring and notify cryptsetup to read it from there later. Currently, cryptsetup
cli supports kernel keyring for passphrase only via LUKS2 internal token
(luks2-keyring). Library also provides a general method for device activation by
reading passphrase from keyring: crypt_activate_by_keyring(). The key type
for use case II) must always be 'user' since we need to read the actual key
data from userspace unlike with VK in I). Ability to read keyslot passphrase
from kernel keyring also allows easily auto-activate LUKS2 devices.
Simple example how to use kernel keyring for keyslot passphrase:
1) create LUKS2 keyring token for keyslot 0 (in LUKS2 device/image)
cryptsetup token add --key-description my:key -S 0 /dev/device
2) Load keyslot passphrase in user keyring
read -s -p "Keyslot passphrase: "; echo -n $REPLY | keyctl padd user my:key @u
3) Activate device using passphrase stored in kernel keyring
cryptsetup open /dev/device my_unlocked_device
4a) unlink the key when no longer needed by
keyctl unlink %user:my:key @u
4b) or revoke it immediately by
keyctl revoke %user:my:key
If cryptsetup asks for passphrase in step 3) something went wrong with keyring
activation. See --debug output then.

279
docs/LUKS2-format.txt Normal file
View File

@@ -0,0 +1,279 @@
LUKS2 on-disk format
====================
Note: these are temporary documentation notes only.
The more formal definition will be published later.
Design goals
~~~~~~~~~~~~
The LUKS2 is an on-disk storage format designed to
provide simple key management, primarily intended for Full Disk
Encryption based on dm-crypt.
The LUKS2 is highly inspired by LUKS1 format and in some
specific situations (most of the default installations) can be converted
in-place (in both ways - to and from LUKS1).
The LUKS2 format is designed to allow future updates of various
parts without the need to modify binary structures.
On-disk format provides redundancy of metadata, detection
of metadata corruption and automatic repair from metadata copy.
NOTE: For security reasons, there is no redundancy in keyslots
binary data (encrypted keys) but format allows updating to redundant
keyslot encryption in future (add forward error correction codes
is one possibility).
On-disk structure
~~~~~~~~~~~~~~~~~
The LUKS2 header contains three parts:
- binary header (one 4096 bytes sector)
- area for metadata stored in JSON format
- keyslot area (per-context binary data).
The binary header and JSON area are stored twice to increase
redundancy. Keyslot area is allocated per-demand, and it is stored only once.
The basic on-disk structure is then
0 4096
| bin hdr1 | JSON ... | bin hdr2 | JSON ... | Keyslot data | <padding> | (data payload)
Binary header
~~~~~~~~~~~~~
The binary header is intended for quick scanning (by blkid and udev) and contains
magic string to detect the device, basic information (labels), header size information
and metadata checksum.
Checksum covers both binary data and following JSON area and is calculated
with checksum fields zeroed. By default plain SHA256 checksum is used.
The primary binary header is always stored in sector 0 of the device.
The C structure of binary header (see luks2.h) is
#define LUKS2_MAGIC_1ST "LUKS\xba\xbe"
#define LUKS2_MAGIC_2ND "SKUL\xba\xbe"
#define LUKS2_MAGIC_L 6
#define LUKS2_UUID_L 40
#define LUKS2_LABEL_L 48
#define LUKS2_SALT_L 64
#define LUKS2_CHECKSUM_ALG_L 32
#define LUKS2_CHECKSUM_L 64
struct luks2_hdr_disk {
char magic[LUKS2_MAGIC_L]; /* "LUKS\xba\xbe" (1st) or "SKUL\xba\be" (2nd) */
uint16_t version; /* Version 2 */
uint64_t hdr_size; /* in bytes, including JSON area */
uint64_t seqid; /* sequence ID, increased on every update */
char label[LUKS2_LABEL_L]; /* ASCII label or empty */
char checksum_alg[LUKS2_CHECKSUM_ALG_L]; /* checksum algorithm, "sha256" */
uint8_t salt[LUKS2_SALT_L]; /* random salt, unique for every header */
char uuid[LUKS2_UUID_L]; /* UUID of device */
char subsystem[LUKS2_LABEL_L]; /* owner subsystem label or empty */
uint64_t hdr_offset; /* header offset from device start in bytes */
char _padding[184]; /* must be zeroed */
uint8_t csum[LUKS2_CHECKSUM_L]; /* header checksum */
char _padding4096[7*512]; /* must be zeroed */
} __attribute__ ((packed));
The LUKS1 compatible field (magic, UUID) are placed intentionally on the same offsets.
The header version must be set to 2.
The UUID is the same format as in LUKS1.
Magic string differs between the first and second header.
The hdr_offset must match physical header offset on the device.
If hdr_offset does not match, the header is misplaced and must not be used.
(It is a prevention to partition resize or manipulation with device start offset.)
The hdr_size contains the size of the binary header and JSON data area.
The offset and size of the second (backup) header must match to these data.
(Prevention to rewrite of a header with different JSON area size.)
There are two labels - label and subsystem. Content of these fields will be visible
in UDEV/blkid scan and can be used for similar purposes as a filesystem label.
These fields are by default empty.
The salt field in binary header is generated by an RNG and is different for
every header, even the backup header must contain a different salt.
The salt in binary header is not used after the header is read, the main intention
is to avoid deduplication of the header sector.
The salt must be regenerated on every header repair (but not on regular update).
The sequential number (seqid) is a counter that is always increased when a new
update of the header is written. The header with higher seqid is more recent and
is used for recovery (if there are two headers with different seqid, the
more recent one is automatically used).
The rest of binary header must be zeroed.
JSON area
~~~~~~~~~
The JSON area starts immediately after the binary header. Its size is set
by binary header hdr_size field (JSON area size = hdr_size - 4096).
The area contains metadata in JSON format and is fixed. Unused remainder
of the area must be empty.
The header cannot store larger metadata that this fixed buffer and header
size must be set properly during format. For now, only areas with 14 kB
header (4kB binary header + 14kB JSON area) is created during format.
The JSON is structured to be able to describe system in very generic way,
but LUKS2 intentionally limits options to values that are supportable
in implemented version.
JSON structure is as follows:
Mandatory sections (must be present but some can be empty):
- config
- keyslots
- digests
- segments
- tokens
Except for config section, all section contains array of objects that must be named
as number (unsigned integer) - for example keyslot "0", "1" etc.
Every object is typed (must contain attribute "type").
According to type, library decides how to handle (or ignore) such an object.
Binary data inside JSON (for example salt) is stored in Hexa64 encoding.
If a value is needed to be stored as a 64bit integer (usually offset or size),
it is stored in text format and later converted to the 64bit integer.
(JSON cannot store 64bit integers directly.)
Config section
~~~~~~~~~~~~~~
Config contains information about JSON buffer size (cross-checked with binary header),
keyslot area size and optional object with activation flags.
The "flags" section is array of activation flags that are automatically used
when LUKS device is activated (for example it can unconditionally allow TRIM/discard
functionality on the encrypted device).
Segments sections
~~~~~~~~~~~~~~~~~
The segment is an encrypted area on the disk containing data (in LUKS1 often
mentioned as a data payload).
For now, only one data area is available for the user.
(More segments will be later used for on-line re-encryption functionality.)
Segments contain definition about encryption parameters, sector size and
start and length of the segments. By default, the segment starts directly
after the LUKS2 header and is marked as "dynamic" (it automatically detects
the size of the available device).
Optionally it can contain information about data integrity protection,
then the data segments is formatted as dm-integrity device and dm-crypt
encryption is stacked above.
To activate a segment, there must be at least one digest linked to it.
Keyslots section
~~~~~~~~~~~~~~~~
Keyslot object contains information stored key - area, where it is stored
(keyslot data), encryption, anti-forensic function, and Key Derivation Function
and its parameters (PBKDF type, costs, salt).
For now, only internal "luks2" keyslot type is available, it uses the same logic
as LUKS1 keyslot, but allows to define per-keyslot algorithms
(for example different PBKDF).
Digests section
~~~~~~~~~~~~~~~
The digest is used to verify that volume key decrypted from a keyslot is correct.
A digest is linked to keyslots and segment.
For now, only "pbkdf2" digest (LUKS1 compatible digest that uses PBKDF2)
is supported.
Tokens section
~~~~~~~~~~~~~~
A token is an object that can describe "how to get passphrase or key" to unlock
particular keyslot or it can be used t store any additional data (even unrelated
to a keyslot).
This area can be user configurable, and libcryptsetup provides interface to
store used data directly in JSON format.
Some token types are implemented internally, for now, there is only "luks2-keyring".
type. This token type tries to load unlocking passphrase from kernel keyring
with stored identification.
There can be external application that uses token objects to store metadata and
implements bindings to specific hardware (TPM etc.).
LUKS2 JSON Format Example
~~~~~~~~~~~~~~~~~~~~~~~~~
For illustration this is example of a LUKS2 device JSON:
{
"keyslots":{
"0":{
"type":"luks2",
"key_size":32,
"kdf":{
"type":"argon2i",
"time":181,
"memory":1024,
"cpus":4,
"salt":"Xfc5ScS8tCLrdbt6jtyWsBjCwAn3Msn\/enOYaAq8PEo="
},
"af":{
"type":"luks1",
"hash":"sha256",
"stripes":4000
},
"area":{
"type":"raw",
"encryption":"aes-xts-plain64",
"key_size":32,
"offset":"32768",
"size":"131072"
}
}
},
"tokens":{
"0":{
"type":"luks2-keyring",
"keyslots":[
"0"
],
"key_description":"my-token"
}
},
"segments":{
"0":{
"type":"crypt",
"offset":"4194304",
"iv_tweak":"0",
"size":"dynamic",
"encryption":"aes-xts-plain64",
"sector_size":512
}
},
"digests":{
"0":{
"type":"pbkdf2",
"keyslots":[
"0"
],
"segments":[
"0"
],
"hash":"sha256",
"iterations":155298,
"salt":"WgMOideLECc5hfnmFVu3bwttJpkfnpf2RayE2WhP8zU=",
"digest":"olobPk9pc0GItqofH78aMPmRaOZIbRevlvSlTZ91NLI="
}
},
"config":{
"json_size":"12288",
"keyslots_size":"4161536",
"flags":[
"allow-discards"
]
}
}

61
docs/LUKS2-locking.txt Normal file
View File

@@ -0,0 +1,61 @@
LUKS2 device locking overview
=============================
Why
~~~
LUKS2 format keeps two identical copies of metadata stored consecutively
at the head of metadata device (file or bdev). The metadata
area (both copies) must be updated in a single atomic operation to avoid
header corruption during concurrent write.
While with LUKS1 users may have clear knowledge of when a LUKS header is
being updated (written to) or when it's being read solely the need for
locking with legacy format was not so obvious as it is with the LUKSv2 format.
With LUKS2 the boundary between read-only and read-write is blurry and what
used to be the exclusively read-only operation (i.e., cryptsetup open command) may
easily become read-update operation silently without user's knowledge.
Major feature of LUKS2 format is resilience against accidental
corruption of metadata (i.e., partial header overwrite by parted or cfdisk
while creating partition on mistaken block device).
Such header corruption is detected early on header read and auto-recovery
procedure takes place (the corrupted header with checksum mismatch is being
replaced by the secondary one if that one is intact).
On current Linux systems header load operation may be triggered without user
direct intervention for example by udev rule or from systemd service.
Such clash of header read and auto-recovery procedure could have severe
consequences with the worst case of having LUKS2 device unaccessible or being
broken beyond repair.
The whole locking of LUKSv2 device headers split into two categories depending
what backend the header is stored on:
I) block device
~~~~~~~~~~~~~~~
We perform flock() on file descriptors of files stored in a private
directory (by default /run/lock/cryptsetup). The file name is derived
from major:minor couple of affected block device. Note we recommend
that access to private locking directory is supposed to be limited
to superuser only. For this method to work the distribution needs
to install the locking directory with appropriate access rights.
II) regular files
~~~~~~~~~~~~~~~~~
First notable difference between headers stored in a file
vs. headers stored in a block device is that headers in a file may be
manipulated by the regular user unlike headers on block devices. Therefore
we perform flock() protection on file with the luks2 header directly.
Limitations
~~~~~~~~~~~
a) In general, the locking model provides serialization of I/Os targeting
the header only. It means the header is always written or read at once
while locking is enabled.
We do not suppress any other negative effect that two or more concurrent
writers of the same header may cause.
b) The locking is not cluster aware in any way.

View File

@@ -1,4 +1,4 @@
# Doxyfile 1.7.4
# Doxyfile 1.8.8
#---------------------------------------------------------------------------
# Project related configuration options
@@ -10,6 +10,7 @@ PROJECT_BRIEF = "Public cryptsetup API"
PROJECT_LOGO =
OUTPUT_DIRECTORY = doxygen_api_docs
CREATE_SUBDIRS = NO
ALLOW_UNICODE_NAMES = NO
OUTPUT_LANGUAGE = English
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
@@ -27,11 +28,14 @@ INHERIT_DOCS = YES
SEPARATE_MEMBER_PAGES = NO
TAB_SIZE = 8
ALIASES =
TCL_SUBST =
OPTIMIZE_OUTPUT_FOR_C = YES
OPTIMIZE_OUTPUT_JAVA = NO
OPTIMIZE_FOR_FORTRAN = NO
OPTIMIZE_OUTPUT_VHDL = NO
EXTENSION_MAPPING =
MARKDOWN_SUPPORT = YES
AUTOLINK_SUPPORT = YES
BUILTIN_STL_SUPPORT = NO
CPP_CLI_SUPPORT = NO
SIP_SUPPORT = NO
@@ -39,13 +43,15 @@ IDL_PROPERTY_SUPPORT = YES
DISTRIBUTE_GROUP_DOC = NO
SUBGROUPING = YES
INLINE_GROUPED_CLASSES = NO
INLINE_SIMPLE_STRUCTS = NO
TYPEDEF_HIDES_STRUCT = YES
SYMBOL_CACHE_SIZE = 0
LOOKUP_CACHE_SIZE = 0
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
EXTRACT_ALL = NO
EXTRACT_PRIVATE = NO
EXTRACT_PACKAGE = NO
EXTRACT_STATIC = NO
EXTRACT_LOCAL_CLASSES = YES
EXTRACT_LOCAL_METHODS = NO
@@ -58,6 +64,7 @@ INTERNAL_DOCS = NO
CASE_SENSE_NAMES = YES
HIDE_SCOPE_NAMES = NO
SHOW_INCLUDE_FILES = YES
SHOW_GROUPED_MEMB_INC = NO
FORCE_LOCAL_INCLUDES = NO
INLINE_INFO = YES
SORT_MEMBER_DOCS = YES
@@ -73,13 +80,13 @@ GENERATE_DEPRECATEDLIST= YES
ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = YES
SHOW_DIRECTORIES = NO
SHOW_FILES = YES
SHOW_NAMESPACES = YES
FILE_VERSION_FILTER =
LAYOUT_FILE =
CITE_BIB_FILES =
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
# Configuration options related to warning and progress messages
#---------------------------------------------------------------------------
QUIET = NO
WARNINGS = YES
@@ -89,9 +96,10 @@ WARN_NO_PARAMDOC = NO
WARN_FORMAT = "$file:$line: $text"
WARN_LOGFILE =
#---------------------------------------------------------------------------
# configuration options related to the input files
# Configuration options related to the input files
#---------------------------------------------------------------------------
INPUT = "doxygen_index" "../lib/libcryptsetup.h"
INPUT = "doxygen_index.h" \
"../lib/libcryptsetup.h"
INPUT_ENCODING = UTF-8
FILE_PATTERNS =
RECURSIVE = NO
@@ -107,8 +115,9 @@ INPUT_FILTER =
FILTER_PATTERNS =
FILTER_SOURCE_FILES = NO
FILTER_SOURCE_PATTERNS =
USE_MDFILE_AS_MAINPAGE =
#---------------------------------------------------------------------------
# configuration options related to source browsing
# Configuration options related to source browsing
#---------------------------------------------------------------------------
SOURCE_BROWSER = NO
INLINE_SOURCES = NO
@@ -116,16 +125,19 @@ STRIP_CODE_COMMENTS = YES
REFERENCED_BY_RELATION = NO
REFERENCES_RELATION = NO
REFERENCES_LINK_SOURCE = YES
SOURCE_TOOLTIPS = YES
USE_HTAGS = NO
VERBATIM_HEADERS = YES
CLANG_ASSISTED_PARSING = NO
CLANG_OPTIONS =
#---------------------------------------------------------------------------
# configuration options related to the alphabetical class index
# Configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
ALPHABETICAL_INDEX = YES
COLS_IN_ALPHA_INDEX = 5
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# configuration options related to the HTML output
# Configuration options related to the HTML output
#---------------------------------------------------------------------------
GENERATE_HTML = YES
HTML_OUTPUT = html
@@ -133,13 +145,14 @@ HTML_FILE_EXTENSION = .html
HTML_HEADER =
HTML_FOOTER =
HTML_STYLESHEET =
HTML_EXTRA_STYLESHEET =
HTML_EXTRA_FILES =
HTML_COLORSTYLE_HUE = 220
HTML_COLORSTYLE_SAT = 100
HTML_COLORSTYLE_GAMMA = 80
HTML_TIMESTAMP = YES
HTML_ALIGN_MEMBERS = YES
HTML_DYNAMIC_SECTIONS = NO
HTML_INDEX_NUM_ENTRIES = 100
GENERATE_DOCSET = NO
DOCSET_FEEDNAME = "Doxygen generated docs"
DOCSET_BUNDLE_ID = org.doxygen.Project
@@ -163,19 +176,26 @@ QHG_LOCATION =
GENERATE_ECLIPSEHELP = NO
ECLIPSE_DOC_ID = org.doxygen.Project
DISABLE_INDEX = NO
ENUM_VALUES_PER_LINE = 4
GENERATE_TREEVIEW = NO
USE_INLINE_TREES = NO
ENUM_VALUES_PER_LINE = 4
TREEVIEW_WIDTH = 250
EXT_LINKS_IN_WINDOW = NO
FORMULA_FONTSIZE = 10
FORMULA_TRANSPARENT = YES
USE_MATHJAX = NO
MATHJAX_FORMAT = HTML-CSS
MATHJAX_RELPATH = http://www.mathjax.org/mathjax
MATHJAX_EXTENSIONS =
MATHJAX_CODEFILE =
SEARCHENGINE = YES
SERVER_BASED_SEARCH = NO
EXTERNAL_SEARCH = NO
SEARCHENGINE_URL =
SEARCHDATA_FILE = searchdata.xml
EXTERNAL_SEARCH_ID =
EXTRA_SEARCH_MAPPINGS =
#---------------------------------------------------------------------------
# configuration options related to the LaTeX output
# Configuration options related to the LaTeX output
#---------------------------------------------------------------------------
GENERATE_LATEX = YES
LATEX_OUTPUT = latex
@@ -186,13 +206,15 @@ PAPER_TYPE = a4
EXTRA_PACKAGES =
LATEX_HEADER =
LATEX_FOOTER =
LATEX_EXTRA_FILES =
PDF_HYPERLINKS = YES
USE_PDFLATEX = YES
LATEX_BATCHMODE = NO
LATEX_HIDE_INDICES = NO
LATEX_SOURCE_CODE = NO
LATEX_BIB_STYLE = plain
#---------------------------------------------------------------------------
# configuration options related to the RTF output
# Configuration options related to the RTF output
#---------------------------------------------------------------------------
GENERATE_RTF = NO
RTF_OUTPUT = rtf
@@ -201,26 +223,31 @@ RTF_HYPERLINKS = NO
RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
#---------------------------------------------------------------------------
# configuration options related to the man page output
# Configuration options related to the man page output
#---------------------------------------------------------------------------
GENERATE_MAN = NO
MAN_OUTPUT = man
MAN_EXTENSION = .3
MAN_SUBDIR =
MAN_LINKS = NO
#---------------------------------------------------------------------------
# configuration options related to the XML output
# Configuration options related to the XML output
#---------------------------------------------------------------------------
GENERATE_XML = NO
XML_OUTPUT = xml
XML_SCHEMA =
XML_DTD =
XML_PROGRAMLISTING = YES
#---------------------------------------------------------------------------
# configuration options for the AutoGen Definitions output
# Configuration options related to the DOCBOOK output
#---------------------------------------------------------------------------
GENERATE_DOCBOOK = NO
DOCBOOK_OUTPUT = docbook
DOCBOOK_PROGRAMLISTING = NO
#---------------------------------------------------------------------------
# Configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
# configuration options related to the Perl module output
# Configuration options related to the Perl module output
#---------------------------------------------------------------------------
GENERATE_PERLMOD = NO
PERLMOD_LATEX = NO
@@ -239,18 +266,20 @@ PREDEFINED =
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration::additions related to external references
# Configuration options related to external references
#---------------------------------------------------------------------------
TAGFILES =
GENERATE_TAGFILE =
ALLEXTERNALS = NO
EXTERNAL_GROUPS = YES
EXTERNAL_PAGES = YES
PERL_PATH =
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
CLASS_DIAGRAMS = YES
MSCGEN_PATH =
DIA_PATH =
HIDE_UNDOC_RELATIONS = YES
HAVE_DOT = NO
DOT_NUM_THREADS = 0
@@ -261,6 +290,7 @@ CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES
GROUP_GRAPHS = YES
UML_LOOK = NO
UML_LIMIT_NUM_FIELDS = 10
TEMPLATE_RELATIONS = NO
INCLUDE_GRAPH = YES
INCLUDED_BY_GRAPH = YES
@@ -269,9 +299,12 @@ CALLER_GRAPH = NO
GRAPHICAL_HIERARCHY = YES
DIRECTORY_GRAPH = YES
DOT_IMAGE_FORMAT = png
INTERACTIVE_SVG = NO
DOT_PATH =
DOTFILE_DIRS =
MSCFILE_DIRS =
DIAFILE_DIRS =
PLANTUML_JAR_PATH =
DOT_GRAPH_MAX_NODES = 50
MAX_DOT_GRAPH_DEPTH = 0
DOT_TRANSPARENT = NO

View File

@@ -1,8 +1,9 @@
/**
* @mainpage Cryptsetup API
/*! \mainpage Cryptsetup API
*
* The documentation covers public parts of cryptsetup API. In the following sections you'll find
* <b>The</b> documentation covers public parts of cryptsetup API. In the following sections you'll find
* the examples that describe some features of cryptsetup API.
* For more info about libcryptsetup API versions see
* <a href="https://gitlab.com/cryptsetup/cryptsetup/wikis/ABI-tracker/timeline/libcryptsetup/index.html">API Tracker</a>.
*
* <OL type="A">
* <LI>@ref cexamples "Cryptsetup API examples"</LI>
@@ -30,15 +31,13 @@
* @section cexamples Cryptsetup API examples
* @section cluks crypt_luks_usage - cryptsetup LUKS device type usage
* @subsection cinit crypt_init()
*
* Every time you need to do something with cryptsetup or dmcrypt device
* Every time you need to do something with cryptsetup or dmcrypt device
* you need a valid context. The first step to start your work is
* @ref crypt_init call. You can call it either with path
* to the block device or path to the regular file. If you don't supply the path,
* empty context is initialized.
*
* @subsection cformat crypt_format() - header and payload on mutual device
*
* This section covers basic use cases for formatting LUKS devices. Format operation
* sets device type in context and in case of LUKS header is written at the beginning
* of block device. In the example bellow we use the scenario where LUKS header and data
@@ -49,42 +48,35 @@
* overwrites part of the backing block device.
*
* @subsection ckeys Keyslot operations examples
*
* After successful @ref crypt_format of LUKS device, volume key is not stored
* 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()
*
* Creates a new keyslot directly by encrypting volume_key stored in the device
* context. Passphrase should be supplied or user is prompted if passphrase param is
* NULL.
*
* @subsection ckeyslot_pass crypt_keyslot_add_by_passphrase()
*
* Creates a new keyslot for the volume key by opening existing active keyslot,
* extracting volume key from it and storing it into a new keyslot
* protected by a new passphrase
*
* @subsection cload crypt_load()
*
* Function loads header from backing block device into device context.
*
* @subsection cactivate crypt_activate_by_passphrase()
*
* Activates crypt device by user supplied password for keyslot containing the volume_key.
* If <I>keyslot</I> parameter is set to <I>CRYPT_ANY_SLOT</I> then all active keyslots
* are tried one by one until the volume key is found.
*
* @subsection cactive_pars crypt_get_active_device()
*
* This call returns structure containing runtime attributes of active device.
*
* @subsection cinit_by_name crypt_init_by_name()
*
* In case you need to do operations with active device (device which already
* has its corresponding mapping) and you miss valid device context stored in
* *crypt_device reference, you should use this call. Function tries to
@@ -92,22 +84,18 @@
* header.
*
* @subsection cdeactivate crypt_deactivate()
*
* Deactivates crypt device (removes DM mapping and safely erases volume key from kernel).
*
* @subsection cluks_ex crypt_luks_usage.c - Complex example
*
* To compile and run use following commands in examples directory:
*
* @code
* make
* ./crypt_luks_usage _path_to_[block_device]_file
* @endcode
*
* Note that you need to have the cryptsetup library compiled. @include crypt_luks_usage.c
*
* @section clog crypt_log_usage - cryptsetup logging API example
*
* Example describes basic use case for cryptsetup logging. To compile and run
* use following commands in examples directory:
*
@@ -115,7 +103,6 @@
* make
* ./crypt_log_usage
* @endcode
*
* Note that you need to have the cryptsetup library compiled. @include crypt_log_usage.c
*
* @example crypt_luks_usage.c

View File

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

View File

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

Binary file not shown.

241
docs/v1.5.0-ReleaseNotes Normal file
View File

@@ -0,0 +1,241 @@
Cryptsetup 1.5.0 Release Notes
==============================
This release covers mainly inclusion of:
* Veritysetup tool (and related libcryptsetup extensions for dm-verity).
* Experimental cryptsetup-reencrypt tool (LUKS offline reencryption).
Changes since version 1.5.0-rc2
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Add --device-size option for reencryption tool.
* Switch to use unit suffix for --reduce-device-size option.
* Remove open device debugging feature (no longer needed).
* Fix library name for FIPS check.
* Add example of using reencryption inside dracut (see misc/dracut).
Changes since version 1.5.0-rc1
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Introduce cryptsetup-reencrypt - experimental offline LUKS reencryption tool.
! cryptsetup-reencrypt tool is EXPERIMENTAL
! ALWAYS BE SURE YOU HAVE RELIABLE BACKUP BEFORE USING THIS TOOL
This tool tries to simplify situation when you need to re-encrypt the whole
LUKS device in situ (without need to move data elsewhere).
This can happen for example when you want to change volume (master) key,
encryption algorithm, or other encryption parameter.
Cryptsetup-reencrypt can even optionally shift data on device
(reducing data device size - you need some free space at the end of device).
In general, cryptsetup-reencrypt can be used to
- re-generate volume key
- change arbitrary encryption parameters
- add encryption to not yet encrypted drive
Side effect of reencryption is that final device will contain
only ciphertext (for all sectors) so even if device was not properly
wiped by random data, after reencryption you cannot distinguish
which sectors are used.
(Reecryption is done always for the whole device.)
There are for sure bugs, please TEST IT IN TEST ENVIRONMENT before
use for your data.
This tool is not resistant to HW and kernel failures - hw crash
will cause serious data corruption.
You can enable compilation of this tool with --enable-cryptsetup-reencrypt
configure option (it is switched off by default).
(Tool requires libcryptsetup 1.4.3 and later.)
You have to provide all keyslot passphrases or use --keyslot-option
(then all other keyslots will be disabled).
EXAMPLES (from man page)
Reencrypt /dev/sdb1 (change volume key)
# cryptsetup-reencrypt /dev/sdb1
Reencrypt and also change cipher and cipher mode
# cryptsetup-reencrypt /dev/sdb1 -c aes-xts-plain64
Note: if you are changing key size, there must be enough space
for keyslots in header or you have to use --reduce-device size and
reduce fs in advance.
Add LUKS encryption to not yet encrypted device
First, be sure you have space added to disk.
Or, alternatively, shrink filesystem in advance.
Here we need 4096 512-bytes sectors (enough for 2x128 bit key).
# fdisk -u /dev/sdb # move sdb1 partition end + 4096 sectors
# cryptsetup-reencrypt /dev/sdb1 --new --reduce-device-size 4096
There are some options which can improve performance (depends on system),
namely --use-directio (use direct IO for all operations) can be faster
on some systems. See man page.
Progress and estimated time is printed during reencryption.
You can suspend reencryption (using ctrl+c or term signal).
To continue reencryption you have to provide only
the device parameter (offset is stored in temporary log file).
Please note LUKS device is marked invalid during reencryption and
you have to retain tool temporary files until reencryption finishes.
Temporary files are LUKS-<uuid>.[log|org|new]
Other changes
~~~~~~~~~~~~~
* Fix luks-header-from-active script (do not use LUKS header on-disk, add UUID).
* Add --test-passphrase option for luksOpen (check passphrase only).
* Fix parsing of hexadecimal string (salt or root hash) in veritysetup.
Changes since version 1.4.3
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Introduce veritysetup tool for dm-verity target management.
The dm-verity device-mapper target was added to Linux kernel 3.4 and
provides transparent integrity checking of block devices using a cryptographic
digest provided by the kernel crypto API. This target is read-only.
It is meant to be setup as part of a verified boot path (it was originally
developed by Chrome OS authors as part of verified boot infrastructure).
For deeper description please see http://code.google.com/p/cryptsetup/wiki/DMVerity
and kernel dm-verity documentation.
The libcryptsetup library was extended to support manipulation
with dm-verity kernel module and new veritysetup CLI tool is added.
There are no additional library requirements (it uses the same crypto
backend as cryptsetup).
If you want compile cryptsetup without veritysetup tool,
use --disable-veritysetup configure option.
For other configuration option see configure --help and veritysetup --help
(e.g. default parameters).
Supported libcryptsetup functions new CRYPT_VERITY type:
crypt_init
crypt_init_by_name
crypt_set_data device
crypt_get_type
crypt_format
crypt_load
crypt_get_active_device
crypt_activate_by_volume_key (volume key == root hash here)
crypt_dump
and new introduced function
crypt_get_verity_info
Please see comments in libcryptsetup.h and veritysetup.c as an code example
how to use CRYPT_VERITY API.
The veritysetup tool supports these operations:
veritysetup format <data_device> <hash_device>
Formats <hash_device> (calculates all hash areas according to <data_device>).
This is initial command to prepare device <hash_device> for later verification.
veritysetup create <name> <data_device> <hash_device> <root_hash>
Creates (activates) a dm-verity mapping with <name> backed by device <data_device>
and using <hash_device> for in-kernel verification.
veritysetup verify <data_device> <hash_device> <root_hash>
Verifies data in userspace (no kernel device is activated).
veritysetup remove <name>
Removes activated device from kernel (similar to dmsetup remove).
veritysetup status <name>
Reports status for the active kernel dm-verity device.
veritysetup dump <hash_device>
Reports parameters of verity device from on-disk stored superblock.
For more info see veritysetup --help and veritysetup man page.
Other changes
~~~~~~~~~~~~~
* Both data and header device can now be a file and
loop device is automatically allocated.
* Require only up to last keyslot area for header device, previously
backup (and activation) required device/file of size up to data start
offset (data payload).
* Fix header backup and restore to work on files with large data offset.
Backup and restore now works even if backup file is smaller than data offset.
Appendix: Examples of veritysetup use
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Format device using default parameters, info and final root hash is printed:
# veritysetup format /dev/sdb /dev/sdc
VERITY header information for /dev/sdc
UUID: fad30431-0c59-4fa6-9b57-732a90501f75
Hash type: 1
Data blocks: 52224
Data block size: 4096
Hash block size: 4096
Hash algorithm: sha256
Salt: 5cc52759af76a092e0c21829cd0ef6938f69831bf86926525106f92a7e9e3aa9
Root hash: 7aefa4506f7af497ac491a27f862cf8005ea782a5d97f6426945a6896ab557a1
Activation of device in-kernel:
# veritysetup create vr /dev/sdb /dev/sdc 7aefa4506f7af497ac491a27f862cf8005ea782a5d97f6426945a6896ab557a1
Note - if device is corrupted, kernel mapping is created but will report failure:
Verity device detected corruption after activation.
Userspace verification:
# veritysetup verify /dev/sdb /dev/sdc 7aefa4506f7af497ac491a27f862cf8005ea782a5d97f6426945a6896ab557a1
Verification failed at position 8192.
Verification of data area failed.
Active device status report:
# veritysetup status vr
/dev/mapper/vr is active.
type: VERITY
status: verified
hash type: 1
data block: 4096
hash block: 4096
hash name: sha256
salt: 5cc52759af76a092e0c21829cd0ef6938f69831bf86926525106f92a7e9e3aa9
data device: /dev/sdb
size: 417792 sectors
mode: readonly
hash device: /dev/sdc
hash offset: 8 sectors
Dump of on-disk superblock information:
# veritysetup dump /dev/sdc
VERITY header information for /dev/sdc
UUID: fad30431-0c59-4fa6-9b57-732a90501f75
Hash type: 1
Data blocks: 52224
Data block size: 4096
Hash block size: 4096
Hash algorithm: sha256
Salt: 5cc52759af76a092e0c21829cd0ef6938f69831bf86926525106f92a7e9e3aa9
Remove mapping:
# veritysetup remove vr

32
docs/v1.5.1-ReleaseNotes Normal file
View File

@@ -0,0 +1,32 @@
Cryptsetup 1.5.1 Release Notes
==============================
Changes since version 1.5.0
* The libcryptsetup library now tries to initialize device-mapper backend and
loop devices only if they are really needed (lazy initializations).
This allows some operations to be run by a non-root user.
(Unfortunately LUKS header keyslot operations still require temporary dm-crypt
device and device-mapper subsystem is available only to superuser.)
Also clear error messages are provided if running as non-root user and
operation requires privileged user.
* Veritysetup can be now used by a normal user for creating hash image to file
and also it can create hash image if doesn't exist.
(Previously it required pre-allocated space.)
* Added crypt_keyslot_area() API call which allows external tools
to get exact keyslot offsets and analyse content.
An example of a tool that searches the keyslot area of a LUKS container
for positions where entropy is low and hence there is a high probability
of damage is in misc/kesylot_checker.
(Thanks to Arno Wagner for the code.)
* Optimized seek to keyfile-offset if key offset is large.
* Fixed luksHeaderBackup for very old v1.0 unaligned LUKS headers.
* Various fixes for problems found by a several static analysis tools.

261
docs/v1.6.0-ReleaseNotes Normal file
View File

@@ -0,0 +1,261 @@
Cryptsetup 1.6.0 Release Notes
==============================
Changes since version 1.6.0-rc1
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Change LUKS default cipher to to use XTS encryption mode,
aes-xts-plain64 (i.e. using AES128-XTS).
XTS mode becomes standard in hard disk encryption.
You can still use any old mode:
- compile cryptsetup with old default:
configure --with-luks1-cipher=aes --with-luks1-mode=cbc-essiv:sha256 --with-luks1-keybits=256
- format LUKS device with old default:
cryptsetup luksFormat -c aes-cbc-essiv:sha256 -s 256 <device>
* Skip tests and fix error messages if running on old systems (or with old kernel).
* Rename configure.in to configure.ac and fix issues with new automake and pkgconfig
and --disable-kernel_crypto option to allow compilation with old kernel headers.
* Allow repair of 512 bits key header.
* Fix status of device if path argument is used and fix double path prefix
for non-existent device path.
Changes since version 1.5.1
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Important changes
~~~~~~~~~~~~~~~~~
* Cryptsetup and libcryptsetup is now released under GPLv2+
(GPL version 2 or any later).
Some internal code handling files (loopaes, verity, tcrypt
and crypto backend wrapper) are LGPLv2+.
Previously code was GPL version 2 only.
* Introducing new unified command open and close.
Example:
cryptsetup open --type plain|luks|loopaes|tcrypt <device> <name>
(type defaults to luks)
with backward-compatible aliases plainOpen, luksOpen, loopaesOpen,
tcryptOpen. Basically "open --type xyz" has alias "xyzOpen".
The "create" command (plain device create) is DEPRECATED but will
be still supported.
(This command is confusing because of switched arguments order.)
The close command is generic command to remove mapping and have
backward compatible aliases (remove, luksClose, ...) which behaves
exactly the same.
While all old syntax is still supported, I strongly suggest to use
new command syntax which is common for all device types (and possible
new formats added in future).
* cryptsetup now support directly TCRYPT (TrueCrypt and compatible tc-play)
on-disk format
(Code is independent implementation not related to original project).
Only dump (tcryptDump command) and activation (open --type tcrypt or tcryptOpen)
of TCRYPT device are supported. No header changes are supported.
It is intended to easily access containers shared with other operating systems
without need to install 3rd party software. For native Linux installations LUKS
is the preferred format.
WARNING: TCRYPT extension requires kernel userspace crypto API to be
available (introduced in Linux kernel 2.6.38).
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).
Because TCRYPT header is encrypted, you have to always provide valid
passphrase and keyfiles. Keyfiles are handled exactly the same as in original
format (basically, first 1MB of every keyfile is mixed using CRC32 into pool).
Cryptsetup should recognize all TCRYPT header variants ever released, 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).
Device activation is supported only for LRW/XTS modes (again, limitation
of kernel dmcrypt which do not implements TCRYPT extensions to CBC mode).
(So old containers cannot be activated, but you can use libcryptsetup
for lost password search, example of such code is included in misc directory.)
Hidden header are supported using --tcrypt-hidden option, system encryption
using --tcrypt-system option.
For detailed description see man page.
EXAMPLE:
* Dump device parameters of container in file:
# cryptsetup tcryptDump tst
Enter passphrase:
TCRYPT header information for tst
Version: 5
Driver req.: 7
Sector size: 512
MK offset: 131072
PBKDF2 hash: sha512
Cipher chain: serpent-twofish-aes
Cipher mode: xts-plain64
MK bits: 1536
You can also dump master key using --dump-master-key.
Dump does not require superuser privilege.
* Activation of this container
# cryptsetup tcryptOpen tst tcrypt_dev
Enter passphrase:
(Chain of dmcrypt devices is activated as /dev/mapper/tcrypt_dev.)
* See status of active TCRYPT device
# cryptsetup status tcrypt_dev
/dev/mapper/tcrypt_dev is active.
type: TCRYPT
cipher: serpent-twofish-aes-xts-plain64
keysize: 1536 bits
device: /dev/loop0
loop: /tmp/tst
offset: 256 sectors
size: 65024 sectors
skipped: 256 sectors
mode: read/write
* And plaintext filesystem now ready to mount
# blkid /dev/mapper/tcrypt_dev
/dev/mapper/tcrypt_dev: SEC_TYPE="msdos" UUID="9F33-2954" TYPE="vfat"
* Add (optional) support for lipwquality for new LUKS passwords.
If password is entered through terminal (no keyfile specified)
and cryptsetup is compiled with --enable-pwquality, default
system pwquality settings are used to check password quality.
You can always override this check by using new --force-password option.
For more info about pwquality project see http://libpwquality.fedorahosted.org/
* Proper handle interrupt signals (ctrl+c and TERM signal) in tools
Code should now handle interrupt properly, release and explicitly wipe
in-memory key materials on interrupt.
(Direct users of libcryptsetup should always call crypt_free() when
code is interrupted to wipe all resources. There is no signal handling
in library, it is up to the tool using it.)
* Add new benchmark command
The "benchmark" command now tries to benchmark PBKDF2 and some block
cipher variants. You can specify you own parameters (--cipher/--key-size
for block ciphers, --hash for PBKDF2).
See man page for detailed description.
WARNING: benchmark command requires kernel userspace crypto API to be
available (introduced in Linux kernel 2.6.38).
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).
EXAMPLE:
# cryptsetup benchmark
# Tests are approximate using memory only (no storage IO).
PBKDF2-sha1 111077 iterations per second
PBKDF2-sha256 53718 iterations per second
PBKDF2-sha512 18832 iterations per second
PBKDF2-ripemd160 89775 iterations per second
PBKDF2-whirlpool 23918 iterations per second
# Algorithm | Key | Encryption | Decryption
aes-cbc 128b 212.0 MiB/s 428.0 MiB/s
serpent-cbc 128b 23.1 MiB/s 66.0 MiB/s
twofish-cbc 128b 46.1 MiB/s 50.5 MiB/s
aes-cbc 256b 163.0 MiB/s 350.0 MiB/s
serpent-cbc 256b 23.1 MiB/s 66.0 MiB/s
twofish-cbc 256b 47.0 MiB/s 50.0 MiB/s
aes-xts 256b 190.0 MiB/s 190.0 MiB/s
serpent-xts 256b 58.4 MiB/s 58.0 MiB/s
twofish-xts 256b 49.0 MiB/s 49.5 MiB/s
aes-xts 512b 175.0 MiB/s 175.0 MiB/s
serpent-xts 512b 59.0 MiB/s 58.0 MiB/s
twofish-xts 512b 48.5 MiB/s 49.5 MiB/s
Or you can specify cipher yourself:
# cryptsetup benchmark --cipher cast5-cbc-essiv:sha256 -s 128
# Tests are approximate using memory only (no storage IO).
# Algorithm | Key | Encryption | Decryption
cast5-cbc 128b 32.4 MiB/s 35.0 MiB/s
WARNING: these tests do not use dmcrypt, only crypto API.
You have to benchmark the whole device stack and you can get completely
different results. But is is usable for basic comparison.
(Note for example AES-NI decryption optimization effect in example above.)
Features
~~~~~~~~
* Do not maintain ChangeLog file anymore, see git log for detailed changes,
e.g. here http://code.google.com/p/cryptsetup/source/list
* Move change key into library, add crypt_keyslot_change_by_passphrase().
This change is useful mainly in FIPS mode, where we cannot
extract volume key directly from libcryptsetup.
* Add verbose messages during reencryption.
* Default LUKS PBKDF2 iteration time is now configurable.
* Add simple cipher benchmarking API.
* Add kernel skcipher backend.
* Add CRC32 implementation (for TCRYPT).
* Move PBKDF2 into crypto backend wrapper.
This allows use it in other formats, use library implementations and
also possible use of different KDF function in future.
* New PBKDF2 benchmark using getrusage().
Fixes
~~~~~
* Avoid O_DIRECT open if underlying storage doesn't support it.
* Fix some non-translated messages.
* Fix regression in header backup (1.5.1) with container in file.
* Fix blockwise read/write for end writes near end of device.
(was not used in previous versions)
* Ignore setpriority failure.
* Code changes to fix/ignore problems found by Coverity static analysis, including
- Get page size should never fail.
- Fix time of check/use (TOCTOU test) in tools
- Fix time of check/use in loop/wipe utils.
- Fix time of check/use in device utils.
* Disallow header restore if context is non-LUKS device.

32
docs/v1.6.1-ReleaseNotes Normal file
View File

@@ -0,0 +1,32 @@
Cryptsetup 1.6.1 Release Notes
==============================
Changes since version 1.6.0
* Fix loop-AES keyfile parsing.
Loop-AES keyfile should be text keyfile, reject keyfiles which
are not properly terminated.
* Fix passphrase pool overflow for too long TCRYPT passphrase.
(Maximal TCRYPT passphrase length is 64 characters.)
* Return EPERM (translated to exit code 2) for too long TCRYPT passphrase.
* Fix deactivation of device when failed underlying node disappeared.
* Fix API deactivate call for TCRYPT format and NULL context parameter.
* Improve keyslot checker example documentation.
* Report error message if deactivation fails and device is still busy.
* Make passphrase prompts more consistent (and remove "LUKS" form prompt).
* Fix some missing headers (compilation failed with alternative libc).
* Remove not functional API UUID support for plain & loopaes devices.
(not persistent activation UUID).
* Properly cleanup devices on interrupt in api-test.
* Support all tests run if kernel is in FIPS mode.

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.

47
docs/v1.6.8-ReleaseNotes Normal file
View File

@@ -0,0 +1,47 @@
Cryptsetup 1.6.8 Release Notes
==============================
Changes since version 1.6.7
* If the null cipher (no encryption) is used, allow only empty password for LUKS.
(Previously cryptsetup accepted any password in this case.)
The null cipher can be used only for testing and it is used temporarily during
offline encrypting not yet encrypted device (cryptsetup-reencrypt tool).
Accepting only empty password prevents situation when someone adds another
LUKS device using the same UUID (UUID of existing LUKS device) with faked
header containing null cipher.
This could force user to use different LUKS device (with no encryption)
without noticing.
(IOW it prevents situation when attacker intentionally forces
user to boot into different system just by LUKS header manipulation.)
Properly configured systems should have an additional integrity protection
in place here (LUKS here provides only confidentiality) but it is better
to not allow this situation in the first place.
(For more info see QubesOS Security Bulletin QSB-019-2015.)
* Properly support stdin "-" handling for luksAddKey for both new and old
keyfile parameters.
* If encrypted device is file-backed (it uses underlying loop device),
cryptsetup resize will try to resize underlying loop device as well.
(It can be used to grow up file-backed device in one step.)
* Cryptsetup now allows to use empty password through stdin pipe.
(Intended only for testing in scripts.)
Cryptsetup API NOTE:
Direct terminal handling and password calling callback for passphrase
entry will be removed from libcryptsetup in next major (2.x) version
(application should handle it itself).
It means that application have to always provide password in API calls.
Functions returning last error will be removed in next major version (2.x).
These functions did not work properly for early initialization errors
and application can implement better function easily using own error callback.
See comments in libcryptsetup.h for more info about deprecated functions.

81
docs/v1.7.0-ReleaseNotes Normal file
View File

@@ -0,0 +1,81 @@
Cryptsetup 1.7.0 Release Notes
==============================
The cryptsetup 1.7 release changes defaults for LUKS,
there are no API changes.
Changes since version 1.6.8
* Default hash function is now SHA256 (used in key derivation function
and anti-forensic splitter).
Note that replacing SHA1 with SHA256 is not for security reasons.
(LUKS does not have problems even if collisions are found for SHA1,
for details see FAQ item 5.20).
Using SHA256 as default is mainly to prevent compatibility problems
on hardened systems where SHA1 is already be phased out.
Note that all checks (kernel crypto API availability check) now uses
SHA256 as well.
* Default iteration time for PBKDF2 is now 2 seconds.
Increasing iteration time is in combination with PBKDF2 benchmark
fixes a try to keep PBKDF2 iteration count still high enough and
also still acceptable for users.
N.B. Long term is to replace PBKDF2 algorithm with Password Hashing
Competition winner - Argon2.
Distributions can still change these defaults in compilation time.
You can change iteration time and used hash function in existing LUKS
header with cryptsetup-reencrypt utility even without full reencryption
of device (see --keep-key option).
* Fix PBKDF2 iteration benchmark for longer key sizes.
The previous PBKDF2 benchmark code did not take into account
output key length properly.
For SHA1 (with 160-bits output) and 256-bit keys (and longer)
it means that the final iteration value was higher than it should be.
For other hash algorithms (like SHA256 or SHA512) it caused
that iteration count was lower (in comparison to SHA1) than
expected for the requested time period.
The PBKDF2 benchmark code is now fixed to use the key size for
the formatted device (or default LUKS key size if running in informational
benchmark mode).
Thanks to A.Visconti, S.Bossi, A.Calo and H.Ragab
(http://www.club.di.unimi.it/) for point this out.
(Based on "What users should know about Full Disk Encryption
based on LUKS" paper to be presented on CANS2015).
* Remove experimental warning for reencrypt tool.
The strong request for full backup before using reencryption utility
still applies :)
* Add optional libpasswdqc support for new LUKS passwords.
If password is entered through terminal (no keyfile specified) and
cryptsetup is compiled with --enable-passwdqc[=/etc/passwdqc.conf],
configured system passwdqc settings are used to check password quality.
* Update FAQ document.
Cryptsetup API NOTE:
Direct terminal handling and password calling callback for passphrase
entry will be removed from libcryptsetup in next major (2.x) version
(application should handle it itself).
It means that application have to always provide password in API calls.
Functions returning last error will be removed in next major version (2.x).
These functions did not work properly for early initialization errors
and application can implement better function easily using own error callback.
See comments in libcryptsetup.h for more info about deprecated functions.

36
docs/v1.7.1-ReleaseNotes Normal file
View File

@@ -0,0 +1,36 @@
Cryptsetup 1.7.1 Release Notes
==============================
Changes since version 1.7.0
* Code now uses kernel crypto API backend according to new
changes introduced in mainline kernel
While mainline kernel should contain backward compatible
changes, some stable series kernels do not contain fully
backported compatibility patches.
Without these patches most of cryptsetup operations
(like unlocking device) fail.
This change in cryptsetup ensures that all operations using
kernel crypto API works even on these kernels.
* The cryptsetup-reencrypt utility now properly detects removal
of underlying link to block device and does not remove
ongoing re-encryption log.
This allows proper recovery (resume) of reencrypt operation later.
NOTE: Never use /dev/disk/by-uuid/ path for reencryption utility,
this link disappears once the device metadata is temporarily
removed from device.
* Cryptsetup now allows special "-" (standard input) keyfile handling
even for TCRYPT (TrueCrypt and VeraCrypt compatible) devices.
* Cryptsetup now fails if there are more keyfiles specified
for non-TCRYPT device.
* The luksKillSlot command now does not suppress provided password
in batch mode (if password is wrong slot is not destroyed).
Note that not providing password in batch mode means that keyslot
is destroyed unconditionally.

37
docs/v1.7.2-ReleaseNotes Normal file
View File

@@ -0,0 +1,37 @@
Cryptsetup 1.7.2 Release Notes
==============================
Changes since version 1.7.1
* Update LUKS documentation format.
Clarify fixed sector size and keyslots alignment.
* Support activation options for error handling modes in Linux kernel
dm-verity module:
--ignore-corruption - dm-verity just logs detected corruption
--restart-on-corruption - dm-verity restarts the kernel if corruption is detected
If the options above are not specified, default behavior for dm-verity remains.
Default is that I/O operation fails with I/O error if corrupted block is detected.
--ignore-zero-blocks - Instructs dm-verity to not verify blocks that are expected
to contain zeroes and always return zeroes directly instead.
NOTE that these options could have security or functional impacts,
do not use them without assessing the risks!
* Fix help text for cipher benchmark specification (mention --cipher option).
* Fix off-by-one error in maximum keyfile size.
Allow keyfiles up to compiled-in default and not that value minus one.
* Support resume of interrupted decryption in cryptsetup-reencrypt utility.
To resume decryption, LUKS device UUID (--uuid option) option must be used.
* Do not use direct-io for LUKS header with unaligned keyslots.
Such headers were used only by the first cryptsetup-luks-1.0.0 release (2005).
* Fix device block size detection to properly work on particular file-based
containers over underlying devices with 4k sectors.

20
docs/v1.7.3-ReleaseNotes Normal file
View File

@@ -0,0 +1,20 @@
Cryptsetup 1.7.3 Release Notes
==============================
Changes since version 1.7.2
* Fix device access to hash offsets located beyond the 2GB device boundary in veritysetup.
* Set configured (compile-time) default iteration time for devices created directly through
libcryptsetup (default was hardcoded 1 second, the configured value applied only
for cryptsetup application).
* Fix PBKDF2 benchmark to not double iteration count for specific corner case.
If the measurement function returns exactly 500 ms, the iteration calculation loop
doubled iteration count but instead of repeating measurement it used this value directly.
* OpenSSL backend: fix memory leak if hash context was repeatedly reused.
* OpenSSL backend: add support for OpenSSL 1.1.0.
* Fix several minor spelling errors.

22
docs/v1.7.4-ReleaseNotes Normal file
View File

@@ -0,0 +1,22 @@
Cryptsetup 1.7.4 Release Notes
==============================
Changes since version 1.7.3
* Allow to specify LUKS1 hash algorithm in Python luksFormat wrapper.
* Use LUKS1 compiled-in defaults also in Python wrapper.
* OpenSSL backend: Fix OpenSSL 1.1.0 support without backward compatible API.
* OpenSSL backend: Fix LibreSSL compatibility.
* Check for data device and hash device area overlap in veritysetup.
* Fix a possible race while allocating a free loop device.
* Fix possible file descriptor leaks if libcryptsetup is run from a forked process.
* Fix missing same_cpu_crypt flag in status command.
* Various updates to FAQ and man pages.

22
docs/v1.7.5-ReleaseNotes Normal file
View File

@@ -0,0 +1,22 @@
Cryptsetup 1.7.5 Release Notes
==============================
Changes since version 1.7.4
* Fixes to luksFormat to properly support recent kernel running in FIPS mode.
Cryptsetup must never use a weak key even if it is just used for testing
of algorithm availability. In FIPS mode, weak keys are always rejected.
A weak key is for example detected if the XTS encryption mode use
the same key for the tweak and the encryption part.
* Fixes accesses to unaligned hidden legacy TrueCrypt header.
On a native 4k-sector device the old hidden TrueCrypt header is not
aligned with the hw sector size (this problem was fixed in later TrueCrypt
on-disk format versions).
Cryptsetup now properly aligns the read so it does not fail.
* Fixes to optional dracut ramdisk scripts for offline re-encryption on initial boot.

View File

@@ -0,0 +1,566 @@
Cryptsetup 2.0.0 RC0 Release Notes
==================================
Release candidate with experimental features.
This version introduces a new on-disk LUKS2 format.
The legacy LUKS (referenced as LUKS1) will be fully supported
forever as well as a traditional and fully backward compatible format.
NOTE: This version changes soname of libcryptsetup library and increases
major version for all public symbols.
Most of the old functions are fully backward compatible, so only
recompilation of programs should be needed.
Please note that authenticated disk encryption, noncryptographic
data integrity protection (dm-integrity), use of Argon2 Password-Based
Key Derivation Function and the LUKS2 on-disk format itself are new
features and can contain some bugs.
Please do not use it without properly configured backup or in
production systems.
Until final 2.0 version is released, the new API calls or LUKS2 format
could still change if a major problem is found.
Important features
~~~~~~~~~~~~~~~~~~
* New command integritysetup: support for the new dm-integrity kernel target.
The dm-integrity is a new kernel device-mapper target that introduces
software emulation of per-sector integrity fields on the disk sector level.
It is available since Linux kernel version 4.12.
The provided per-sector metadata fields can be used for storing a data
integrity checksum (for example CRC32).
The dm-integrity implements data journal that enforces atomic update
of a sector and its integrity metadata.
Integritysetup is a CLI utility that can setup standalone dm-integrity
devices (that internally check integrity of data).
Integritysetup is intended to be used for settings that require
non-cryptographic data integrity protection with no data encryption.
Fo setting integrity protected encrypted devices, see disk authenticated
encryption below.
Note that after formatting the checksums need to be initialized;
otherwise device reads will fail because of integrity errors.
Integritysetup by default tries to wipe the device with zero blocks
to avoid this problem. Device wipe can be time-consuming, you can skip
this step by specifying --no-wipe option.
(But note that not wiping device can cause some operations to fail
if a write is not multiple of page size and kernel page cache tries
to read sectors with not yet initialized checksums.)
The default setting is tag size 4 bytes per-sector and CRC32C protection.
To format device with these defaults:
$ integritysetup format <device>
$ integritysetup open <device> <name>
Note that used algorithm (unlike tag size) is NOT stored in device
kernel superblock and if you use different algorithm, you MUST specify
it in every open command, for example:
$ integritysetup format <device> --tag-size 32 --integrity sha256
$ integritysetup open <device> <name> --integrity sha256
For more info, see integrity man page.
* Veritysetup command can now format and activate dm-verity devices
that contain Forward Error Correction (FEC) (Reed-Solomon code is used).
This feature is used on most of Android devices already (available since
Linux kernel 4.5).
There are new options --fec-device, --fec-offset to specify data area
with correction code and --fec-roots that set Redd-Solomon generator roots.
This setting can be used for format command (veritysetup will calculate
and store RS codes) or open command (veritysetup configures kernel
dm-verity to use RS codes).
For more info see veritysetup man page.
* Support for larger sector sizes for crypt devices.
LUKS2 and plain crypt devices can be now configured with larger encryption
sector (typically 4096 bytes, sector size must be the power of two,
maximal sector size is 4096 bytes for portability).
Large sector size can decrease encryption overhead and can also help
with some specific crypto hardware accelerators that perform very
badly with 512 bytes sectors.
Note that if you configure such a larger sector of the device that does use
smaller physical sector, there is a possibility of a data corruption during
power fail (partial sector writes).
WARNING: If you use different sector size for a plain device after data were
stored, the decryption will produce garbage.
For LUKS2, the sector size is stored in metadata and cannot be changed later.
LUKS2 format and features
~~~~~~~~~~~~~~~~~~~~~~~~~
The LUKS2 is an on-disk storage format designed to provide simple key
management, primarily intended for Full Disk Encryption based on dm-crypt.
The LUKS2 is inspired by LUKS1 format and in some specific situations (most
of the default configurations) can be converted in-place from LUKS1.
The LUKS2 format is designed to allow future updates of various
parts without the need to modify binary structures and internally
uses JSON text format for metadata. Compilation now requires the json-c library
that is used for JSON data processing.
On-disk format provides redundancy of metadata, detection
of metadata corruption and automatic repair from metadata copy.
NOTE: For security reasons, there is no redundancy in keyslots binary data
(encrypted keys) but the format allows adding such a feature in future.
NOTE: to operate correctly, LUKS2 requires locking of metadata.
Locking is performed by using flock() system call for images in file
and for block device by using a specific lock file in /run/lock/cryptsetup.
This directory must be created by distribution (do not rely on internal
fallback). For systemd-based distribution, you can simply install
scripts/cryptsetup_tmpfiles.conf into tmpfiles.d directory.
For more details see LUKS2-format.txt and LUKS2-locking.txt in the docs
directory. (Please note this is just overview, there will be more formal
documentation later.)
LUKS2 use
~~~~~~~~~
LUKS2 allows using all possible configurations as LUKS1.
To format device as LUKS2, you have to add "--type luks2" during format:
$ cryptsetup luksFormat --type luks2 <device>
All commands issued later will recognize the new format automatically.
The newly added features in LUKS2 include:
* Authenticated disk (sector) encryption (EXPERIMENTAL)
Legacy Full disk encryption (FDE), for example, LUKS1, is a length-preserving
encryption (plaintext is the same size as a ciphertext).
Such FDE can provide data confidentiality, but cannot provide sound data
integrity protection.
Full disk authenticated encryption is a way how to provide both
confidentiality and data integrity protection. Integrity protection here means
not only detection of random data corruption (silent data corruption) but also
prevention of an unauthorized intentional change of disk sector content.
NOTE: Integrity protection of this type cannot prevent a replay attack.
An attacker can replace the device or its part of the old content, and it
cannot be detected.
If you need such protection, better use integrity protection on a higher layer.
For data integrity protection on the sector level, we need additional
per-sector metadata space. In LUKS2 this space is provided by a new
device-mapper dm-integrity target (available since kernel 4.12).
Here the integrity target provides only reliable per-sector metadata store,
and the whole authenticated encryption is performed inside dm-crypt stacked
over the dm-integrity device.
For encryption, Authenticated Encryption with Additional Data (AEAD) is used.
Every sector is processed as a encryption request of this format:
|----- AAD -------|------ DATA -------|-- AUTH TAG --|
| (authenticated) | (auth+encryption) | |
| sector_LE | IV | sector in/out | tag in/out |
AEAD encrypts the whole sector and also authenticates sector number
(to detect sector relocation) and also authenticates Initialization Vector.
AEAD encryption produces encrypted data and authentication tag.
The authenticated tag is then stored in per-sector metadata space provided
by dm-integrity.
Most of the current AEAD algorithms requires IV as a nonce, value that is
never reused. Because sector number, as an IV, cannot be used in this
environment, we use a new random IV (IV is a random value generated by system
RNG on every write). This random IV is then stored in the per-sector metadata
as well.
Because the authentication tag (and IV) requires additional space, the device
provided for a user has less capacity. Also, the data journalling means that
writes are performed twice, decreasing throughput.
This integrity protection works better with SSDs. If you want to ignore
dm-integrity data journal (because journalling is performed on some higher
layer or you just want to trade-off performance to safe recovery), you can
switch journal off with --integrity-no-journal option.
(This flag can be stored persistently as well.)
Note that (similar to integritysetup) the device read will fail if
authentication tag is not initialized (no previous write).
By default cryptsetup run wipe of a device (writing zeroes) to initialize
authentication tags. This operation can be very time-consuming.
You can skip device wipe using --integrity-no-wipe option.
To format LUKS2 device with integrity protection, use new --integrity option.
For now, there are very few AEAD algorithms that can be used, and some
of them are known to be problematic. In this release we support only
a few of AEAD algorithms (options are for now hard coded), later this
extension will be completely algorithm-agnostic.
For testing of authenticated encryption, these algorithms work for now:
1) aes-xts-random with hmac-sha256 or hmac-sha512 as the authentication tag.
(Authentication key for HMAC is independently generated. This mode is very slow.)
$ cryptsetup luksFormat --type luks2 <device> --cipher aes-xts-random --integrity hmac-sha256
2) aes-gcm-random (native AEAD mode)
DO NOT USE in production. The GCM mode uses only 96-bit nonce,
and possible collision means fatal security problem.
GCM mode has very good hardware support through AES-NI, so it is useful
for performance testing.
$ cryptsetup luksFormat --type luks2 <device> --cipher aes-gcm-random --integrity aead
3) ChaCha20 with Poly1305 authenticator (according to RFC7539)
$ cryptsetup luksFormat --type luks2 <device> --cipher chacha20-random --integrity poly1305
To specify AES128/AES256 just specify proper key size (without possible
authentication key). Other symmetric ciphers, like Serpent or Twofish,
should work as well. The mode 1) and 2) should be compatible with IEEE 1619.1
standard recommendation.
You can also store only random IV in tag without integrity protection.
Note that using random IV forces the system to pseudorandomly change the whole
sector on every write without removing parallel processing of XTS mode.
In cryptography, we can say that this will provide indistinguishability under
chosen plaintext attack (IND-CPA) that cannot be achieved in legacy
FDE systems. On the other side, if stored random IV is corrupted, the sector
is no longer decrypted properly.
To use only random IV (no integrity protection), just specify "none" integrity.
$ cryptsetup luksFormat --type luks2 <device> --cipher aes-xts-random --integrity none
FDE authenticated encryption is not a replacement for filesystem layer
authenticated encryption. The goal is to provide at least something because
data integrity protection is often completely ignored in today systems.
* New memory-hard PBKDF
LUKS1 introduced Password-Based Key Derivation Function v2 as a tool to
increase attacker cost for a dictionary and brute force attacks.
The PBKDF2 uses iteration count to increase time of key derivation.
Unfortunately, with modern GPUs, the PBKDF2 calculations can be run
in parallel and PBKDF2 can no longer provide the best available protection.
Increasing iteration count just cannot prevent massive parallel dictionary
password attacks in long-term.
To solve this problem, a new PBKDF, based on so-called memory-hard functions
can be used. Key derivation with memory-hard function requires a certain
amount of memory to compute its output. The memory requirement is very
costly for GPUs and prevents these systems to operate ineffectively,
increasing cost for attackers.
LUKS2 introduces support for Argon2i and Argon2id as a PBKDF.
Argon2 is the winner of Password Hashing Competition and is currently
in final RFC draft specification.
For now, libcryptsetup contains the embedded copy of reference implementation
of Argon2 (that is easily portable to all architectures).
Later, once this function is available in common crypto libraries, it will
switch to external implementation. (This happened for LUKS1 and PBKDF2
as well years ago.)
With using reference implementation (that is not optimized for speed), there
is some performance penalty. However, using memory-hard PBKDF should still
significantly complicate GPU-optimized dictionary and brute force attacks.
The Argon2 uses three costs: memory, time (number of iterations) and parallel
(number of threads).
Note that time and memory cost highly influences each other (accessing a lot
of memory takes more time).
There is a new benchmark that tries to calculate costs to take similar way as
in LUKS1 (where iteration is measured to take 1-2 seconds on user system).
Because now there are more cost variables, it prefers time cost (iterations)
and tries to find required memory that fits. (IOW required memory cost can be
lower if the benchmarks are not able to find required parameters.)
The benchmark cannot run too long, so it tries to approximate next step
for benchmarking.
For now, default LUKS2 PBKDF algorithm is Argon2i (data independent variant)
with memory cost set to 128MB, time to 800ms and parallel thread according
to available CPU cores but no more than 4.
All default parameters can be set during compile time and also set on
the command line by using --pbkdf, --pbkdf-memory, --pbkdf-parallel and
--iter-time options.
(Or without benchmark directly by using --pbkdf-force-iterations, see below.)
You can still use PBKDF2 even for LUKS2 by specifying --pbkdf pbkdf2 option.
(Then only iteration count is applied.)
* Use of kernel keyring
Kernel keyring is a storage for sensitive material (like cryptographic keys)
inside Linux kernel.
LUKS2 uses keyring for two major functions:
- To store volume key for dm-crypt where it avoids sending volume key in
every device-mapper ioctl structure. Volume key is also no longer directly
visible in a dm-crypt mapping table. The key is not available for the user
after dm-crypt configuration (obviously except direct memory scan).
Use of kernel keyring can be disabled in runtime by --disable-keyring option.
- As a tool to automatically unlock LUKS device if a passphrase is put into
kernel keyring and proper keyring token is configured.
This allows storing a secret (passphrase) to kernel per-user keyring by
some external tool (for example some TPM handler) and LUKS2, if configured,
will automatically search in the keyring and unlock the system.
For more info see Tokens section below.
* Persistent flags
The activation flags (like allow-discards) can be stored in metadata and used
automatically by all later activations (even without using crypttab).
To store activation flags permanently, use activation command with required
flags and add --persistent option.
For example, to mark device to always activate with TRIM enabled,
use (for LUKS2 type):
$ cryptsetup open <device> <name> --allow-discards --persistent
You can check persistent flags in dump command output:
$ cryptsetup luksDump <device>
* Tokens and auto-activation
A LUKS2 token is an object that can be described "how to get passphrase or key"
to unlock particular keyslot.
(Also it can be used to store any additional metadata, and with
the libcryptsetup interface it can be used to define user token types.)
Cryptsetup internally implements keyring token. Cryptsetup tries to use
available tokens before asking for the passphrase. For keyring token,
it means that if the passphrase is available under specified identifier
inside kernel keyring, the device is automatically activated using this
stored passphrase.
Example of using LUKS2 keyring token:
# Adding token to metadata with "my_token" identifier (by default it applies to all keyslots).
$ cryptsetup token add --key-description "my_token" <device>
# Storing passphrase to user keyring (this can be done by an external application)
$ echo -n <passphrase> | keyctl padd user my_token @u
# Now cryptsetup activates automatically if it finds correct passphrase
$ cryptsetup open <device> <name>
The main reason to use tokens this way is to separate possible hardware
handlers from cryptsetup code.
* Keyslot priorities
LUKS2 keyslot can have a new priority attribute.
The default is "normal". The "prefer" priority tell the keyslot to be tried
before other keyslots. Priority "ignore" means that keyslot will never be
used if not specified explicitly (it can be used for backup administrator
passwords that are used only situations when a user forgets own passphrase).
The priority of keyslot can be set with new config command, for example
$ cryptsetup config <device> --key-slot 1 --priority prefer
Setting priority to normal will reset slot to normal state.
* LUKS2 label and subsystem
The header now contains additional fields for label and subsystem (additional
label). These fields can be used similar to filesystem label and will be
visible in udev rules to possible filtering. (Note that blkid do not yet
contain the LUKS scanning code).
By default both labels are empty. Label and subsystem are always set together
(no option means clear the label) with the config command:
$ cryptsetup config <device> --label my_device --subsystem ""
* In-place conversion form LUKS1
To allow easy testing and transition to the new LUKS2 format, there is a new
convert command that allows in-place conversion from the LUKS1 format and,
if there are no incompatible options, also conversion back from LUKS2
to LUKS1 format.
Note this command can be used only on some LUKS1 devices (some device header
sizes are not supported).
This command is dangerous, never run it without header backup!
If something fails in the middle of conversion (IO error), the header
is destroyed. (Note that conversion requires move of keyslot data area to
a different offset.)
To convert header in-place to LUKS2 format, use
$ cryptsetup convert <device> --type luks2
To convert it back to LUKS1 format, use
$ cryptsetup convert <device> --type luks1
You can verify LUKS version with luksDump command.
$ cryptsetup luksDump <device>
Note that some LUKS2 features will make header incompatible with LUKS1 and
conversion will be rejected (for example using new Argon2 PBKDF or integrity
extensions). Some minor attributes can be lost in conversion.
Other changes
~~~~~~~~~~~~~
* Explicit KDF iterations count setting
With new PBKDF interface, there is also the possibility to setup PBKDF costs
directly, avoiding benchmarks. This can be useful if device is formatted to be
primarily used on a different system.
The option --pbkdf-force-iterations is available for both LUKS1 and LUKS2
format. Using this option can cause device to have either very low or very
high PBKDF costs.
In the first case it means bad protection to dictionary attacks, in the second
case, it can mean extremely high unlocking time or memory requirements.
Use only if you are sure what you are doing!
Not that this setting also affects iteration count for the key digest.
For LUKS1 iteration count for digest will be approximately 1/8 of requested
value, for LUKS2 and "pbkdf2" digest minimal PBKDF2 iteration count (1000)
will be used. You cannot set lower iteration count than the internal minimum
(1000 for PBKDF2).
To format LUKS1 device with forced iteration count (and no benchmarking), use
$ cryptsetup luksFormat <device> --pbkdf-force-iterations 22222
For LUKS2 it is always better to specify full settings (do not rely on default
cost values).
For example, we can set to use Argon2id with iteration cost 5, memory 128000
and paralell set 1:
$ cryptsetup luksFormat --type luks2 <device> \
--pbkdf argon2id --pbkdf-force-iterations 5 --pbkdf-memory 128000 --pbkdf-parallel 1
* VeraCrypt PIM
Cryptsetup can now also open VeraCrypt device that uses Personal Iteration
Multiplier (PIM). PIM is an integer value that user must remember additionally
to passphrase and influences PBKDF2 iteration count (without it VeraCrypt uses
a fixed number of iterations).
To open VeraCrypt device with PIM settings, use --veracrypt-pim (to specify
PIM on the command line) or --veracrypt-query-pim to query PIM interactively.
* Support for plain64be IV
The plain64be is big-endian variant of plain64 Initialization Vector. It is
used in some images of hardware-based disk encryption systems. Supporting this
variant allows using dm-crypt to map such images through cryptsetup.
* Deferral removal
Cryptsetup now can mark device for deferred removal by using a new option
--deferred. This means that close command will not fail if the device is still
in use, but will instruct the kernel to remove the device automatically after
use count drops to zero (for example, once the filesystem is unmounted).
* A lot of updates to man pages and many minor changes that would make this
release notes too long ;-)
Libcryptsetup API changes
~~~~~~~~~~~~~~~~~~~~~~~~~
These API functions were removed, libcryptsetup no longer handles password
retries from terminal (application should handle terminal operations itself):
crypt_set_password_callback;
crypt_set_timeout;
crypt_set_password_retry;
crypt_set_password_verify;
This call is removed (no need to keep typo backward compatibility,
the proper function is crypt_set_iteration_time :-)
crypt_set_iterarion_time;
These calls were removed because are not safe, use per-context
error callbacks instead:
crypt_last_error;
crypt_get_error;
The PBKDF benchmark was replaced by a new function that uses new KDF structure
crypt_benchmark_kdf; (removed)
crypt_benchmark_pbkdf; (new API call)
These new calls are now exported, for details see libcryptsetup.h:
crypt_keyslot_add_by_key;
crypt_keyslot_set_priority;
crypt_keyslot_get_priority;
crypt_token_json_get;
crypt_token_json_set;
crypt_token_status;
crypt_token_luks2_keyring_get;
crypt_token_luks2_keyring_set;
crypt_token_assign_keyslot;
crypt_token_unassign_keyslot;
crypt_token_register;
crypt_activate_by_token;
crypt_activate_by_keyring;
crypt_deactivate_by_name;
crypt_metadata_locking;
crypt_volume_key_keyring;
crypt_get_integrity_info;
crypt_get_sector_size;
crypt_persistent_flags_set;
crypt_persistent_flags_get;
crypt_set_pbkdf_type;
crypt_get_pbkdf_type;
crypt_convert;
crypt_keyfile_read;
crypt_wipe;
Unfinished things & TODO for next RC or future
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* There will be better documentation and examples.
* There will be some more formal definition of the threat model for integrity
protection. (And a link to some papers discussing integrity protection,
once it is, hopefully, accepted and published.)
* Offline re-encrypt tool supports only LUKS1 format for now (patches are
on the way).
* There will be online LUKS2 re-encryption tool in future.
* Authenticated encryption will use new algorithms from CAESAR competition,
once these algorithms are available in kernel.
* Authenticated encryption do not set encryption for dm-integrity journal.
While it does not influence data confidentiality or integrity protection,
an attacker can get some more information from data journal or cause that
system will corrupt sectors after journal replay. (That corruption will be
detected though.)
* Some utilities (blkid, systemd-cryptsetup) will need small updates to support
LUKS2 format.
* There are some examples of user-defined tokens inside misc/luks2_keyslot_example
directory (like a simple external program that uses libssh to unlock LUKS2
using remote keyfile).
We will document these examples later in release notes for next RC.
* The distribution archive is now very big because of some testing images that do not compress
well. Some cleaning is needed here.
* A lot of ideas are hidden inside the LUKS2 design that is not yet used or
described here, let's try if the basics work first :-)

View File

@@ -1,67 +1,81 @@
SUBDIRS = crypto_backend luks1 loopaes
SUBDIRS = crypto_backend luks1 luks2 loopaes verity tcrypt integrity
moduledir = $(libdir)/cryptsetup
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libcryptsetup.pc
INCLUDES = \
AM_CPPFLAGS = -include config.h \
-I$(top_srcdir) \
-I$(top_srcdir)/lib/crypto_backend \
-I$(top_srcdir)/lib/luks1 \
-I$(top_srcdir)/lib/luks2 \
-I$(top_srcdir)/lib/loopaes \
-I$(top_srcdir)/lib/verity \
-I$(top_srcdir)/lib/tcrypt \
-I$(top_srcdir)/lib/integrity \
-DDATADIR=\""$(datadir)"\" \
-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
common_ldadd = \
crypto_backend/libcrypto_backend.la \
luks1/libluks1.la \
loopaes/libloopaes.la
luks2/libluks2.la \
loopaes/libloopaes.la \
verity/libverity.la \
tcrypt/libtcrypt.la \
integrity/libintegrity.la
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@ \
@JSON_C_LIBS@ \
$(common_ldadd)
libcryptsetup_la_SOURCES = \
setup.c \
internal.h \
bitops.h \
nls.h \
libcryptsetup.h \
utils.c \
utils_benchmark.c \
utils_crypt.c \
utils_crypt.h \
utils_debug.c \
utils_loop.c \
utils_loop.h \
utils_devpath.c \
utils_wipe.c \
utils_fips.c \
utils_fips.h \
utils_device.c \
utils_keyring.c \
utils_keyring.h \
utils_device_locking.c \
utils_device_locking.h \
utils_pbkdf.c \
libdevmapper.c \
utils_dm.h \
volumekey.c \
random.c \
crypt_plain.c
crypt_plain.c \
base64.h \
base64.c
include_HEADERS = libcryptsetup.h

605
lib/base64.c Normal file
View File

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

68
lib/base64.h Normal file
View File

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

123
lib/bitops.h Normal file
View File

@@ -0,0 +1,123 @@
/*
* No copyright is claimed. This code is in the public domain; do with
* it what you wish.
*
* Written by Karel Zak <kzak@redhat.com>
*/
#ifndef BITOPS_H
#define BITOPS_H
#include <stdint.h>
#include <sys/param.h>
#if defined(HAVE_BYTESWAP_H)
# include <byteswap.h>
#endif
#if defined(HAVE_ENDIAN_H)
# include <endian.h>
#elif defined(HAVE_SYS_ENDIAN_H) /* BSDs have them here */
# include <sys/endian.h>
#endif
#if defined(__OpenBSD__)
# include <sys/types.h>
# define be16toh(x) betoh16(x)
# define be32toh(x) betoh32(x)
# define be64toh(x) betoh64(x)
#endif
/*
* Fallbacks
*/
#ifndef bswap_16
# define bswap_16(x) ((((x) & 0x00FF) << 8) | \
(((x) & 0xFF00) >> 8))
#endif
#ifndef bswap_32
# define bswap_32(x) ((((x) & 0x000000FF) << 24) | \
(((x) & 0x0000FF00) << 8) | \
(((x) & 0x00FF0000) >> 8) | \
(((x) & 0xFF000000) >> 24))
#endif
#ifndef bswap_64
# define bswap_64(x) ((((x) & 0x00000000000000FFULL) << 56) | \
(((x) & 0x000000000000FF00ULL) << 40) | \
(((x) & 0x0000000000FF0000ULL) << 24) | \
(((x) & 0x00000000FF000000ULL) << 8) | \
(((x) & 0x000000FF00000000ULL) >> 8) | \
(((x) & 0x0000FF0000000000ULL) >> 24) | \
(((x) & 0x00FF000000000000ULL) >> 40) | \
(((x) & 0xFF00000000000000ULL) >> 56))
#endif
#ifndef htobe16
# if !defined(WORDS_BIGENDIAN)
# define htobe16(x) bswap_16 (x)
# define htole16(x) (x)
# define be16toh(x) bswap_16 (x)
# define le16toh(x) (x)
# define htobe32(x) bswap_32 (x)
# define htole32(x) (x)
# define be32toh(x) bswap_32 (x)
# define le32toh(x) (x)
# define htobe64(x) bswap_64 (x)
# define htole64(x) (x)
# define be64toh(x) bswap_64 (x)
# define le64toh(x) (x)
# else
# define htobe16(x) (x)
# define htole16(x) bswap_16 (x)
# define be16toh(x) (x)
# define le16toh(x) bswap_16 (x)
# define htobe32(x) (x)
# define htole32(x) bswap_32 (x)
# define be32toh(x) (x)
# define le32toh(x) bswap_32 (x)
# define htobe64(x) (x)
# define htole64(x) bswap_64 (x)
# define be64toh(x) (x)
# define le64toh(x) bswap_64 (x)
# endif
#endif
/*
* Byte swab macros (based on linux/byteorder/swab.h)
*/
#define swab16(x) bswap_16(x)
#define swab32(x) bswap_32(x)
#define swab64(x) bswap_64(x)
#define cpu_to_le16(x) ((uint16_t) htole16(x))
#define cpu_to_le32(x) ((uint32_t) htole32(x))
#define cpu_to_le64(x) ((uint64_t) htole64(x))
#define cpu_to_be16(x) ((uint16_t) htobe16(x))
#define cpu_to_be32(x) ((uint32_t) htobe32(x))
#define cpu_to_be64(x) ((uint64_t) htobe64(x))
#define le16_to_cpu(x) ((uint16_t) le16toh(x))
#define le32_to_cpu(x) ((uint32_t) le32toh(x))
#define le64_to_cpu(x) ((uint64_t) le64toh(x))
#define be16_to_cpu(x) ((uint16_t) be16toh(x))
#define be32_to_cpu(x) ((uint32_t) be32toh(x))
#define be64_to_cpu(x) ((uint64_t) be64toh(x))
/*
* Bit map related macros. Usually provided by libc.
*/
#ifndef NBBY
# define NBBY CHAR_BIT
#endif
#ifndef setbit
# define setbit(a,i) ((a)[(i)/NBBY] |= 1<<((i)%NBBY))
# define clrbit(a,i) ((a)[(i)/NBBY] &= ~(1<<((i)%NBBY)))
# define isset(a,i) ((a)[(i)/NBBY] & (1<<((i)%NBBY)))
# define isclr(a,i) (((a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0)
#endif
#endif /* BITOPS_H */

View File

@@ -1,12 +1,14 @@
/*
* cryptsetup plain device helper functions
*
* Copyright (C) 2004, Christophe Saout <christophe@saout.de>
* Copyright (C) 2010-2011 Red Hat, Inc. All rights reserved.
* Copyright (C) 2004, Jana Saout <jana@saout.de>
* Copyright (C) 2010-2017 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2017, Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -19,7 +21,7 @@
*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include "libcryptsetup.h"
@@ -81,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);
@@ -93,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,9 +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
libcrypto_backend_la_SOURCES = crypto_backend.h \
crypto_cipher_kernel.c crypto_storage.c pbkdf_check.c crc32.c
if CRYPTO_BACKEND_GCRYPT
libcrypto_backend_la_SOURCES += crypto_gcrypt.c
@@ -22,4 +23,15 @@ if CRYPTO_BACKEND_NETTLE
libcrypto_backend_la_SOURCES += crypto_nettle.c
endif
INCLUDES = -D_GNU_SOURCE -I$(top_srcdir)/lib
if CRYPTO_INTERNAL_PBKDF2
libcrypto_backend_la_SOURCES += pbkdf2_generic.c
endif
if CRYPTO_INTERNAL_ARGON2
SUBDIRS = argon2
libcrypto_backend_la_DEPENDENCIES = argon2/libargon2.la
libcrypto_backend_la_LIBADD = argon2/libargon2.la
libcrypto_backend_la_SOURCES += argon2_generic.c
endif
AM_CPPFLAGS = -include config.h -I$(top_srcdir)/lib

View File

@@ -0,0 +1,30 @@
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER.
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer exclusive Copyright and Related Rights (defined below) upon the creator and subsequent owner(s) (each and all, an "owner") of an original work of authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for the purpose of contributing to a commons of creative, cultural and scientific works ("Commons") that the public can reliably and without fear of later claims of infringement build upon, modify, incorporate in other works, reuse and redistribute as freely as possible in any form whatsoever and for any purposes, including without limitation commercial purposes. These owners may contribute to the Commons to promote the ideal of a free culture and the further production of creative, cultural and scientific works, or to gain reputation or greater distribution for their Work in part through the use and efforts of others.
For these and/or other purposes and motivations, and without any expectation of additional consideration or compensation, the person associating CC0 with a Work (the "Affirmer"), to the extent that he or she is an owner of Copyright and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and publicly distribute the Work under its terms, with knowledge of his or her Copyright and Related Rights in the Work and the meaning and intended legal effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be protected by copyright and related or neighboring rights ("Copyright and Related Rights"). Copyright and Related Rights include, but are not limited to, the following:
the right to reproduce, adapt, distribute, perform, display, communicate, and translate a Work;
moral rights retained by the original author(s) and/or performer(s);
publicity and privacy rights pertaining to a person's image or likeness depicted in a Work;
rights protecting against unfair competition in regards to a Work, subject to the limitations in paragraph 4(a), below;
rights protecting the extraction, dissemination, use and reuse of data in a Work;
database rights (such as those arising under Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, and under any national implementation thereof, including any amended or successor version of such directive); and
other similar, equivalent or corresponding rights throughout the world based on applicable law or treaty, and any national implementations thereof.
2. Waiver. To the greatest extent permitted by, but not in contravention of, applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, and surrenders all of Affirmer's Copyright and Related Rights and associated claims and causes of action, whether now known or unknown (including existing as well as future claims and causes of action), in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each member of the public at large and to the detriment of Affirmer's heirs and successors, fully intending that such Waiver shall not be subject to revocation, rescission, cancellation, termination, or any other legal or equitable action to disrupt the quiet enjoyment of the Work by the public as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason be judged legally invalid or ineffective under applicable law, then the Waiver shall be preserved to the maximum extent permitted taking into account Affirmer's express Statement of Purpose. In addition, to the extent the Waiver is so judged Affirmer hereby grants to each affected person a royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and unconditional license to exercise Affirmer's Copyright and Related Rights in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "License"). The License shall be deemed effective as of the date CC0 was applied by Affirmer to the Work. Should any part of the License for any reason be judged legally invalid or ineffective under applicable law, such partial invalidity or ineffectiveness shall not invalidate the remainder of the License, and in such case Affirmer hereby affirms that he or she will not (i) exercise any of his or her remaining Copyright and Related Rights in the Work or (ii) assert any associated claims and causes of action with respect to the Work, in either case contrary to Affirmer's express Statement of Purpose.
4. Limitations and Disclaimers.
No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, licensed or otherwise affected by this document.
Affirmer offers the Work as-is and makes no representations or warranties of any kind concerning the Work, express, implied, statutory or otherwise, including without limitation warranties of title, merchantability, fitness for a particular purpose, non infringement, or the absence of latent or other defects, accuracy, or the present or absence of errors, whether or not discoverable, all to the greatest extent permissible under applicable law.
Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work.
Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work.

View File

@@ -0,0 +1,13 @@
moduledir = $(libdir)/cryptsetup
noinst_LTLIBRARIES = libargon2.la
libargon2_la_CFLAGS = $(AM_CFLAGS) -std=c89 -pthread -O3 -Wall
libargon2_la_SOURCES = \
blake2/blake2b.c blake2/blake2.h blake2/blake2-impl.h blake2/blamka-round-ref.h \
argon2.c argon2.h core.c core.h encoding.c encoding.h ref.c thread.c thread.h
AM_CPPFLAGS = -Iblake2
EXTRA_DIST = LICENSE

View File

@@ -0,0 +1,5 @@
This is bundled Argon2 algorithm library, copied from
https://github.com/P-H-C/phc-winner-argon2
For more info see Password Hashing Competition site:
https://password-hashing.net/

View File

@@ -0,0 +1,452 @@
/*
* Argon2 reference source code package - reference C implementations
*
* Copyright 2015
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
*
* You may use this work under the terms of a Creative Commons CC0 1.0
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
* these licenses can be found at:
*
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
*
* You should have received a copy of both of these licenses along with this
* software. If not, they may be obtained at the above URLs.
*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "argon2.h"
#include "encoding.h"
#include "core.h"
const char *argon2_type2string(argon2_type type, int uppercase) {
switch (type) {
case Argon2_d:
return uppercase ? "Argon2d" : "argon2d";
case Argon2_i:
return uppercase ? "Argon2i" : "argon2i";
case Argon2_id:
return uppercase ? "Argon2id" : "argon2id";
}
return NULL;
}
int argon2_ctx(argon2_context *context, argon2_type type) {
/* 1. Validate all inputs */
int result = validate_inputs(context);
uint32_t memory_blocks, segment_length;
argon2_instance_t instance;
if (ARGON2_OK != result) {
return result;
}
if (Argon2_d != type && Argon2_i != type && Argon2_id != type) {
return ARGON2_INCORRECT_TYPE;
}
/* 2. Align memory size */
/* Minimum memory_blocks = 8L blocks, where L is the number of lanes */
memory_blocks = context->m_cost;
if (memory_blocks < 2 * ARGON2_SYNC_POINTS * context->lanes) {
memory_blocks = 2 * ARGON2_SYNC_POINTS * context->lanes;
}
segment_length = memory_blocks / (context->lanes * ARGON2_SYNC_POINTS);
/* Ensure that all segments have equal length */
memory_blocks = segment_length * (context->lanes * ARGON2_SYNC_POINTS);
instance.version = context->version;
instance.memory = NULL;
instance.passes = context->t_cost;
instance.memory_blocks = memory_blocks;
instance.segment_length = segment_length;
instance.lane_length = segment_length * ARGON2_SYNC_POINTS;
instance.lanes = context->lanes;
instance.threads = context->threads;
instance.type = type;
if (instance.threads > instance.lanes) {
instance.threads = instance.lanes;
}
/* 3. Initialization: Hashing inputs, allocating memory, filling first
* blocks
*/
result = initialize(&instance, context);
if (ARGON2_OK != result) {
return result;
}
/* 4. Filling memory */
result = fill_memory_blocks(&instance);
if (ARGON2_OK != result) {
return result;
}
/* 5. Finalization */
finalize(context, &instance);
return ARGON2_OK;
}
int argon2_hash(const uint32_t t_cost, const uint32_t m_cost,
const uint32_t parallelism, const void *pwd,
const size_t pwdlen, const void *salt, const size_t saltlen,
void *hash, const size_t hashlen, char *encoded,
const size_t encodedlen, argon2_type type,
const uint32_t version){
argon2_context context;
int result;
uint8_t *out;
if (pwdlen > ARGON2_MAX_PWD_LENGTH) {
return ARGON2_PWD_TOO_LONG;
}
if (saltlen > ARGON2_MAX_SALT_LENGTH) {
return ARGON2_SALT_TOO_LONG;
}
if (hashlen > ARGON2_MAX_OUTLEN) {
return ARGON2_OUTPUT_TOO_LONG;
}
if (hashlen < ARGON2_MIN_OUTLEN) {
return ARGON2_OUTPUT_TOO_SHORT;
}
out = malloc(hashlen);
if (!out) {
return ARGON2_MEMORY_ALLOCATION_ERROR;
}
context.out = (uint8_t *)out;
context.outlen = (uint32_t)hashlen;
context.pwd = CONST_CAST(uint8_t *)pwd;
context.pwdlen = (uint32_t)pwdlen;
context.salt = CONST_CAST(uint8_t *)salt;
context.saltlen = (uint32_t)saltlen;
context.secret = NULL;
context.secretlen = 0;
context.ad = NULL;
context.adlen = 0;
context.t_cost = t_cost;
context.m_cost = m_cost;
context.lanes = parallelism;
context.threads = parallelism;
context.allocate_cbk = NULL;
context.free_cbk = NULL;
context.flags = ARGON2_DEFAULT_FLAGS;
context.version = version;
result = argon2_ctx(&context, type);
if (result != ARGON2_OK) {
clear_internal_memory(out, hashlen);
free(out);
return result;
}
/* if raw hash requested, write it */
if (hash) {
memcpy(hash, out, hashlen);
}
/* if encoding requested, write it */
if (encoded && encodedlen) {
if (encode_string(encoded, encodedlen, &context, type) != ARGON2_OK) {
clear_internal_memory(out, hashlen); /* wipe buffers if error */
clear_internal_memory(encoded, encodedlen);
free(out);
return ARGON2_ENCODING_FAIL;
}
}
clear_internal_memory(out, hashlen);
free(out);
return ARGON2_OK;
}
int argon2i_hash_encoded(const uint32_t t_cost, const uint32_t m_cost,
const uint32_t parallelism, const void *pwd,
const size_t pwdlen, const void *salt,
const size_t saltlen, const size_t hashlen,
char *encoded, const size_t encodedlen) {
return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
NULL, hashlen, encoded, encodedlen, Argon2_i,
ARGON2_VERSION_NUMBER);
}
int argon2i_hash_raw(const uint32_t t_cost, const uint32_t m_cost,
const uint32_t parallelism, const void *pwd,
const size_t pwdlen, const void *salt,
const size_t saltlen, void *hash, const size_t hashlen) {
return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
hash, hashlen, NULL, 0, Argon2_i, ARGON2_VERSION_NUMBER);
}
int argon2d_hash_encoded(const uint32_t t_cost, const uint32_t m_cost,
const uint32_t parallelism, const void *pwd,
const size_t pwdlen, const void *salt,
const size_t saltlen, const size_t hashlen,
char *encoded, const size_t encodedlen) {
return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
NULL, hashlen, encoded, encodedlen, Argon2_d,
ARGON2_VERSION_NUMBER);
}
int argon2d_hash_raw(const uint32_t t_cost, const uint32_t m_cost,
const uint32_t parallelism, const void *pwd,
const size_t pwdlen, const void *salt,
const size_t saltlen, void *hash, const size_t hashlen) {
return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
hash, hashlen, NULL, 0, Argon2_d, ARGON2_VERSION_NUMBER);
}
int argon2id_hash_encoded(const uint32_t t_cost, const uint32_t m_cost,
const uint32_t parallelism, const void *pwd,
const size_t pwdlen, const void *salt,
const size_t saltlen, const size_t hashlen,
char *encoded, const size_t encodedlen) {
return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
NULL, hashlen, encoded, encodedlen, Argon2_id,
ARGON2_VERSION_NUMBER);
}
int argon2id_hash_raw(const uint32_t t_cost, const uint32_t m_cost,
const uint32_t parallelism, const void *pwd,
const size_t pwdlen, const void *salt,
const size_t saltlen, void *hash, const size_t hashlen) {
return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
hash, hashlen, NULL, 0, Argon2_id,
ARGON2_VERSION_NUMBER);
}
static int argon2_compare(const uint8_t *b1, const uint8_t *b2, size_t len) {
size_t i;
uint8_t d = 0U;
for (i = 0U; i < len; i++) {
d |= b1[i] ^ b2[i];
}
return (int)((1 & ((d - 1) >> 8)) - 1);
}
int argon2_verify(const char *encoded, const void *pwd, const size_t pwdlen,
argon2_type type) {
argon2_context ctx;
uint8_t *desired_result = NULL;
int ret = ARGON2_OK;
size_t encoded_len;
uint32_t max_field_len;
if (pwdlen > ARGON2_MAX_PWD_LENGTH) {
return ARGON2_PWD_TOO_LONG;
}
if (encoded == NULL) {
return ARGON2_DECODING_FAIL;
}
encoded_len = strlen(encoded);
if (encoded_len > UINT32_MAX) {
return ARGON2_DECODING_FAIL;
}
/* No field can be longer than the encoded length */
max_field_len = (uint32_t)encoded_len;
ctx.saltlen = max_field_len;
ctx.outlen = max_field_len;
ctx.salt = malloc(ctx.saltlen);
ctx.out = malloc(ctx.outlen);
if (!ctx.salt || !ctx.out) {
ret = ARGON2_MEMORY_ALLOCATION_ERROR;
goto fail;
}
ctx.pwd = (uint8_t *)pwd;
ctx.pwdlen = (uint32_t)pwdlen;
ret = decode_string(&ctx, encoded, type);
if (ret != ARGON2_OK) {
goto fail;
}
/* Set aside the desired result, and get a new buffer. */
desired_result = ctx.out;
ctx.out = malloc(ctx.outlen);
if (!ctx.out) {
ret = ARGON2_MEMORY_ALLOCATION_ERROR;
goto fail;
}
ret = argon2_verify_ctx(&ctx, (char *)desired_result, type);
if (ret != ARGON2_OK) {
goto fail;
}
fail:
free(ctx.salt);
free(ctx.out);
free(desired_result);
return ret;
}
int argon2i_verify(const char *encoded, const void *pwd, const size_t pwdlen) {
return argon2_verify(encoded, pwd, pwdlen, Argon2_i);
}
int argon2d_verify(const char *encoded, const void *pwd, const size_t pwdlen) {
return argon2_verify(encoded, pwd, pwdlen, Argon2_d);
}
int argon2id_verify(const char *encoded, const void *pwd, const size_t pwdlen) {
return argon2_verify(encoded, pwd, pwdlen, Argon2_id);
}
int argon2d_ctx(argon2_context *context) {
return argon2_ctx(context, Argon2_d);
}
int argon2i_ctx(argon2_context *context) {
return argon2_ctx(context, Argon2_i);
}
int argon2id_ctx(argon2_context *context) {
return argon2_ctx(context, Argon2_id);
}
int argon2_verify_ctx(argon2_context *context, const char *hash,
argon2_type type) {
int ret = argon2_ctx(context, type);
if (ret != ARGON2_OK) {
return ret;
}
if (argon2_compare((uint8_t *)hash, context->out, context->outlen)) {
return ARGON2_VERIFY_MISMATCH;
}
return ARGON2_OK;
}
int argon2d_verify_ctx(argon2_context *context, const char *hash) {
return argon2_verify_ctx(context, hash, Argon2_d);
}
int argon2i_verify_ctx(argon2_context *context, const char *hash) {
return argon2_verify_ctx(context, hash, Argon2_i);
}
int argon2id_verify_ctx(argon2_context *context, const char *hash) {
return argon2_verify_ctx(context, hash, Argon2_id);
}
const char *argon2_error_message(int error_code) {
switch (error_code) {
case ARGON2_OK:
return "OK";
case ARGON2_OUTPUT_PTR_NULL:
return "Output pointer is NULL";
case ARGON2_OUTPUT_TOO_SHORT:
return "Output is too short";
case ARGON2_OUTPUT_TOO_LONG:
return "Output is too long";
case ARGON2_PWD_TOO_SHORT:
return "Password is too short";
case ARGON2_PWD_TOO_LONG:
return "Password is too long";
case ARGON2_SALT_TOO_SHORT:
return "Salt is too short";
case ARGON2_SALT_TOO_LONG:
return "Salt is too long";
case ARGON2_AD_TOO_SHORT:
return "Associated data is too short";
case ARGON2_AD_TOO_LONG:
return "Associated data is too long";
case ARGON2_SECRET_TOO_SHORT:
return "Secret is too short";
case ARGON2_SECRET_TOO_LONG:
return "Secret is too long";
case ARGON2_TIME_TOO_SMALL:
return "Time cost is too small";
case ARGON2_TIME_TOO_LARGE:
return "Time cost is too large";
case ARGON2_MEMORY_TOO_LITTLE:
return "Memory cost is too small";
case ARGON2_MEMORY_TOO_MUCH:
return "Memory cost is too large";
case ARGON2_LANES_TOO_FEW:
return "Too few lanes";
case ARGON2_LANES_TOO_MANY:
return "Too many lanes";
case ARGON2_PWD_PTR_MISMATCH:
return "Password pointer is NULL, but password length is not 0";
case ARGON2_SALT_PTR_MISMATCH:
return "Salt pointer is NULL, but salt length is not 0";
case ARGON2_SECRET_PTR_MISMATCH:
return "Secret pointer is NULL, but secret length is not 0";
case ARGON2_AD_PTR_MISMATCH:
return "Associated data pointer is NULL, but ad length is not 0";
case ARGON2_MEMORY_ALLOCATION_ERROR:
return "Memory allocation error";
case ARGON2_FREE_MEMORY_CBK_NULL:
return "The free memory callback is NULL";
case ARGON2_ALLOCATE_MEMORY_CBK_NULL:
return "The allocate memory callback is NULL";
case ARGON2_INCORRECT_PARAMETER:
return "Argon2_Context context is NULL";
case ARGON2_INCORRECT_TYPE:
return "There is no such version of Argon2";
case ARGON2_OUT_PTR_MISMATCH:
return "Output pointer mismatch";
case ARGON2_THREADS_TOO_FEW:
return "Not enough threads";
case ARGON2_THREADS_TOO_MANY:
return "Too many threads";
case ARGON2_MISSING_ARGS:
return "Missing arguments";
case ARGON2_ENCODING_FAIL:
return "Encoding failed";
case ARGON2_DECODING_FAIL:
return "Decoding failed";
case ARGON2_THREAD_FAIL:
return "Threading failure";
case ARGON2_DECODING_LENGTH_FAIL:
return "Some of encoded parameters are too long or too short";
case ARGON2_VERIFY_MISMATCH:
return "The password does not match the supplied hash";
default:
return "Unknown error code";
}
}
size_t argon2_encodedlen(uint32_t t_cost, uint32_t m_cost, uint32_t parallelism,
uint32_t saltlen, uint32_t hashlen, argon2_type type) {
return strlen("$$v=$m=,t=,p=$$") + strlen(argon2_type2string(type, 0)) +
numlen(t_cost) + numlen(m_cost) + numlen(parallelism) +
b64len(saltlen) + b64len(hashlen) + numlen(ARGON2_VERSION_NUMBER) + 1;
}

View File

@@ -0,0 +1,434 @@
/*
* Argon2 reference source code package - reference C implementations
*
* Copyright 2015
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
*
* You may use this work under the terms of a Creative Commons CC0 1.0
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
* these licenses can be found at:
*
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
*
* You should have received a copy of both of these licenses along with this
* software. If not, they may be obtained at the above URLs.
*/
#ifndef ARGON2_H
#define ARGON2_H
#include <stdint.h>
#include <stddef.h>
#include <limits.h>
#if defined(__cplusplus)
extern "C" {
#endif
/* Symbols visibility control */
#ifdef A2_VISCTL
#define ARGON2_PUBLIC __attribute__((visibility("default")))
#elif _MSC_VER
#define ARGON2_PUBLIC __declspec(dllexport)
#else
#define ARGON2_PUBLIC
#endif
/*
* Argon2 input parameter restrictions
*/
/* Minimum and maximum number of lanes (degree of parallelism) */
#define ARGON2_MIN_LANES UINT32_C(1)
#define ARGON2_MAX_LANES UINT32_C(0xFFFFFF)
/* Minimum and maximum number of threads */
#define ARGON2_MIN_THREADS UINT32_C(1)
#define ARGON2_MAX_THREADS UINT32_C(0xFFFFFF)
/* Number of synchronization points between lanes per pass */
#define ARGON2_SYNC_POINTS UINT32_C(4)
/* Minimum and maximum digest size in bytes */
#define ARGON2_MIN_OUTLEN UINT32_C(4)
#define ARGON2_MAX_OUTLEN UINT32_C(0xFFFFFFFF)
/* Minimum and maximum number of memory blocks (each of BLOCK_SIZE bytes) */
#define ARGON2_MIN_MEMORY (2 * ARGON2_SYNC_POINTS) /* 2 blocks per slice */
#define ARGON2_MIN(a, b) ((a) < (b) ? (a) : (b))
/* Max memory size is addressing-space/2, topping at 2^32 blocks (4 TB) */
#define ARGON2_MAX_MEMORY_BITS \
ARGON2_MIN(UINT32_C(32), (sizeof(void *) * CHAR_BIT - 10 - 1))
#define ARGON2_MAX_MEMORY \
ARGON2_MIN(UINT32_C(0xFFFFFFFF), UINT64_C(1) << ARGON2_MAX_MEMORY_BITS)
/* Minimum and maximum number of passes */
#define ARGON2_MIN_TIME UINT32_C(1)
#define ARGON2_MAX_TIME UINT32_C(0xFFFFFFFF)
/* Minimum and maximum password length in bytes */
#define ARGON2_MIN_PWD_LENGTH UINT32_C(0)
#define ARGON2_MAX_PWD_LENGTH UINT32_C(0xFFFFFFFF)
/* Minimum and maximum associated data length in bytes */
#define ARGON2_MIN_AD_LENGTH UINT32_C(0)
#define ARGON2_MAX_AD_LENGTH UINT32_C(0xFFFFFFFF)
/* Minimum and maximum salt length in bytes */
#define ARGON2_MIN_SALT_LENGTH UINT32_C(8)
#define ARGON2_MAX_SALT_LENGTH UINT32_C(0xFFFFFFFF)
/* Minimum and maximum key length in bytes */
#define ARGON2_MIN_SECRET UINT32_C(0)
#define ARGON2_MAX_SECRET UINT32_C(0xFFFFFFFF)
/* Flags to determine which fields are securely wiped (default = no wipe). */
#define ARGON2_DEFAULT_FLAGS UINT32_C(0)
#define ARGON2_FLAG_CLEAR_PASSWORD (UINT32_C(1) << 0)
#define ARGON2_FLAG_CLEAR_SECRET (UINT32_C(1) << 1)
/* Global flag to determine if we are wiping internal memory buffers. This flag
* is defined in core.c and deafults to 1 (wipe internal memory). */
extern int FLAG_clear_internal_memory;
/* Error codes */
typedef enum Argon2_ErrorCodes {
ARGON2_OK = 0,
ARGON2_OUTPUT_PTR_NULL = -1,
ARGON2_OUTPUT_TOO_SHORT = -2,
ARGON2_OUTPUT_TOO_LONG = -3,
ARGON2_PWD_TOO_SHORT = -4,
ARGON2_PWD_TOO_LONG = -5,
ARGON2_SALT_TOO_SHORT = -6,
ARGON2_SALT_TOO_LONG = -7,
ARGON2_AD_TOO_SHORT = -8,
ARGON2_AD_TOO_LONG = -9,
ARGON2_SECRET_TOO_SHORT = -10,
ARGON2_SECRET_TOO_LONG = -11,
ARGON2_TIME_TOO_SMALL = -12,
ARGON2_TIME_TOO_LARGE = -13,
ARGON2_MEMORY_TOO_LITTLE = -14,
ARGON2_MEMORY_TOO_MUCH = -15,
ARGON2_LANES_TOO_FEW = -16,
ARGON2_LANES_TOO_MANY = -17,
ARGON2_PWD_PTR_MISMATCH = -18, /* NULL ptr with non-zero length */
ARGON2_SALT_PTR_MISMATCH = -19, /* NULL ptr with non-zero length */
ARGON2_SECRET_PTR_MISMATCH = -20, /* NULL ptr with non-zero length */
ARGON2_AD_PTR_MISMATCH = -21, /* NULL ptr with non-zero length */
ARGON2_MEMORY_ALLOCATION_ERROR = -22,
ARGON2_FREE_MEMORY_CBK_NULL = -23,
ARGON2_ALLOCATE_MEMORY_CBK_NULL = -24,
ARGON2_INCORRECT_PARAMETER = -25,
ARGON2_INCORRECT_TYPE = -26,
ARGON2_OUT_PTR_MISMATCH = -27,
ARGON2_THREADS_TOO_FEW = -28,
ARGON2_THREADS_TOO_MANY = -29,
ARGON2_MISSING_ARGS = -30,
ARGON2_ENCODING_FAIL = -31,
ARGON2_DECODING_FAIL = -32,
ARGON2_THREAD_FAIL = -33,
ARGON2_DECODING_LENGTH_FAIL = -34,
ARGON2_VERIFY_MISMATCH = -35
} argon2_error_codes;
/* Memory allocator types --- for external allocation */
typedef int (*allocate_fptr)(uint8_t **memory, size_t bytes_to_allocate);
typedef void (*deallocate_fptr)(uint8_t *memory, size_t bytes_to_allocate);
/* Argon2 external data structures */
/*
*****
* Context: structure to hold Argon2 inputs:
* output array and its length,
* password and its length,
* salt and its length,
* secret and its length,
* associated data and its length,
* number of passes, amount of used memory (in KBytes, can be rounded up a bit)
* number of parallel threads that will be run.
* All the parameters above affect the output hash value.
* Additionally, two function pointers can be provided to allocate and
* deallocate the memory (if NULL, memory will be allocated internally).
* Also, three flags indicate whether to erase password, secret as soon as they
* are pre-hashed (and thus not needed anymore), and the entire memory
*****
* Simplest situation: you have output array out[8], password is stored in
* pwd[32], salt is stored in salt[16], you do not have keys nor associated
* data. You need to spend 1 GB of RAM and you run 5 passes of Argon2d with
* 4 parallel lanes.
* You want to erase the password, but you're OK with last pass not being
* erased. You want to use the default memory allocator.
* Then you initialize:
Argon2_Context(out,8,pwd,32,salt,16,NULL,0,NULL,0,5,1<<20,4,4,NULL,NULL,true,false,false,false)
*/
typedef struct Argon2_Context {
uint8_t *out; /* output array */
uint32_t outlen; /* digest length */
uint8_t *pwd; /* password array */
uint32_t pwdlen; /* password length */
uint8_t *salt; /* salt array */
uint32_t saltlen; /* salt length */
uint8_t *secret; /* key array */
uint32_t secretlen; /* key length */
uint8_t *ad; /* associated data array */
uint32_t adlen; /* associated data length */
uint32_t t_cost; /* number of passes */
uint32_t m_cost; /* amount of memory requested (KB) */
uint32_t lanes; /* number of lanes */
uint32_t threads; /* maximum number of threads */
uint32_t version; /* version number */
allocate_fptr allocate_cbk; /* pointer to memory allocator */
deallocate_fptr free_cbk; /* pointer to memory deallocator */
uint32_t flags; /* array of bool options */
} argon2_context;
/* Argon2 primitive type */
typedef enum Argon2_type {
Argon2_d = 0,
Argon2_i = 1,
Argon2_id = 2
} argon2_type;
/* Version of the algorithm */
typedef enum Argon2_version {
ARGON2_VERSION_10 = 0x10,
ARGON2_VERSION_13 = 0x13,
ARGON2_VERSION_NUMBER = ARGON2_VERSION_13
} argon2_version;
/*
* Function that gives the string representation of an argon2_type.
* @param type The argon2_type that we want the string for
* @param uppercase Whether the string should have the first letter uppercase
* @return NULL if invalid type, otherwise the string representation.
*/
ARGON2_PUBLIC const char *argon2_type2string(argon2_type type, int uppercase);
/*
* Function that performs memory-hard hashing with certain degree of parallelism
* @param context Pointer to the Argon2 internal structure
* @return Error code if smth is wrong, ARGON2_OK otherwise
*/
ARGON2_PUBLIC int argon2_ctx(argon2_context *context, argon2_type type);
/**
* Hashes a password with Argon2i, producing an encoded hash
* @param t_cost Number of iterations
* @param m_cost Sets memory usage to m_cost kibibytes
* @param parallelism Number of threads and compute lanes
* @param pwd Pointer to password
* @param pwdlen Password size in bytes
* @param salt Pointer to salt
* @param saltlen Salt size in bytes
* @param hashlen Desired length of the hash in bytes
* @param encoded Buffer where to write the encoded hash
* @param encodedlen Size of the buffer (thus max size of the encoded hash)
* @pre Different parallelism levels will give different results
* @pre Returns ARGON2_OK if successful
*/
ARGON2_PUBLIC int argon2i_hash_encoded(const uint32_t t_cost,
const uint32_t m_cost,
const uint32_t parallelism,
const void *pwd, const size_t pwdlen,
const void *salt, const size_t saltlen,
const size_t hashlen, char *encoded,
const size_t encodedlen);
/**
* Hashes a password with Argon2i, producing a raw hash at @hash
* @param t_cost Number of iterations
* @param m_cost Sets memory usage to m_cost kibibytes
* @param parallelism Number of threads and compute lanes
* @param pwd Pointer to password
* @param pwdlen Password size in bytes
* @param salt Pointer to salt
* @param saltlen Salt size in bytes
* @param hash Buffer where to write the raw hash - updated by the function
* @param hashlen Desired length of the hash in bytes
* @pre Different parallelism levels will give different results
* @pre Returns ARGON2_OK if successful
*/
ARGON2_PUBLIC int argon2i_hash_raw(const uint32_t t_cost, const uint32_t m_cost,
const uint32_t parallelism, const void *pwd,
const size_t pwdlen, const void *salt,
const size_t saltlen, void *hash,
const size_t hashlen);
ARGON2_PUBLIC int argon2d_hash_encoded(const uint32_t t_cost,
const uint32_t m_cost,
const uint32_t parallelism,
const void *pwd, const size_t pwdlen,
const void *salt, const size_t saltlen,
const size_t hashlen, char *encoded,
const size_t encodedlen);
ARGON2_PUBLIC int argon2d_hash_raw(const uint32_t t_cost, const uint32_t m_cost,
const uint32_t parallelism, const void *pwd,
const size_t pwdlen, const void *salt,
const size_t saltlen, void *hash,
const size_t hashlen);
ARGON2_PUBLIC int argon2id_hash_encoded(const uint32_t t_cost,
const uint32_t m_cost,
const uint32_t parallelism,
const void *pwd, const size_t pwdlen,
const void *salt, const size_t saltlen,
const size_t hashlen, char *encoded,
const size_t encodedlen);
ARGON2_PUBLIC int argon2id_hash_raw(const uint32_t t_cost,
const uint32_t m_cost,
const uint32_t parallelism, const void *pwd,
const size_t pwdlen, const void *salt,
const size_t saltlen, void *hash,
const size_t hashlen);
/* generic function underlying the above ones */
ARGON2_PUBLIC int argon2_hash(const uint32_t t_cost, const uint32_t m_cost,
const uint32_t parallelism, const void *pwd,
const size_t pwdlen, const void *salt,
const size_t saltlen, void *hash,
const size_t hashlen, char *encoded,
const size_t encodedlen, argon2_type type,
const uint32_t version);
/**
* Verifies a password against an encoded string
* Encoded string is restricted as in validate_inputs()
* @param encoded String encoding parameters, salt, hash
* @param pwd Pointer to password
* @pre Returns ARGON2_OK if successful
*/
ARGON2_PUBLIC int argon2i_verify(const char *encoded, const void *pwd,
const size_t pwdlen);
ARGON2_PUBLIC int argon2d_verify(const char *encoded, const void *pwd,
const size_t pwdlen);
ARGON2_PUBLIC int argon2id_verify(const char *encoded, const void *pwd,
const size_t pwdlen);
/* generic function underlying the above ones */
ARGON2_PUBLIC int argon2_verify(const char *encoded, const void *pwd,
const size_t pwdlen, argon2_type type);
/**
* Argon2d: Version of Argon2 that picks memory blocks depending
* on the password and salt. Only for side-channel-free
* environment!!
*****
* @param context Pointer to current Argon2 context
* @return Zero if successful, a non zero error code otherwise
*/
ARGON2_PUBLIC int argon2d_ctx(argon2_context *context);
/**
* Argon2i: Version of Argon2 that picks memory blocks
* independent on the password and salt. Good for side-channels,
* but worse w.r.t. tradeoff attacks if only one pass is used.
*****
* @param context Pointer to current Argon2 context
* @return Zero if successful, a non zero error code otherwise
*/
ARGON2_PUBLIC int argon2i_ctx(argon2_context *context);
/**
* Argon2id: Version of Argon2 where the first half-pass over memory is
* password-independent, the rest are password-dependent (on the password and
* salt). OK against side channels (they reduce to 1/2-pass Argon2i), and
* better with w.r.t. tradeoff attacks (similar to Argon2d).
*****
* @param context Pointer to current Argon2 context
* @return Zero if successful, a non zero error code otherwise
*/
ARGON2_PUBLIC int argon2id_ctx(argon2_context *context);
/**
* Verify if a given password is correct for Argon2d hashing
* @param context Pointer to current Argon2 context
* @param hash The password hash to verify. The length of the hash is
* specified by the context outlen member
* @return Zero if successful, a non zero error code otherwise
*/
ARGON2_PUBLIC int argon2d_verify_ctx(argon2_context *context, const char *hash);
/**
* Verify if a given password is correct for Argon2i hashing
* @param context Pointer to current Argon2 context
* @param hash The password hash to verify. The length of the hash is
* specified by the context outlen member
* @return Zero if successful, a non zero error code otherwise
*/
ARGON2_PUBLIC int argon2i_verify_ctx(argon2_context *context, const char *hash);
/**
* Verify if a given password is correct for Argon2id hashing
* @param context Pointer to current Argon2 context
* @param hash The password hash to verify. The length of the hash is
* specified by the context outlen member
* @return Zero if successful, a non zero error code otherwise
*/
ARGON2_PUBLIC int argon2id_verify_ctx(argon2_context *context,
const char *hash);
/* generic function underlying the above ones */
ARGON2_PUBLIC int argon2_verify_ctx(argon2_context *context, const char *hash,
argon2_type type);
/**
* Get the associated error message for given error code
* @return The error message associated with the given error code
*/
ARGON2_PUBLIC const char *argon2_error_message(int error_code);
/**
* Returns the encoded hash length for the given input parameters
* @param t_cost Number of iterations
* @param m_cost Memory usage in kibibytes
* @param parallelism Number of threads; used to compute lanes
* @param saltlen Salt size in bytes
* @param hashlen Hash size in bytes
* @param type The argon2_type that we want the encoded length for
* @return The encoded hash length in bytes
*/
ARGON2_PUBLIC size_t argon2_encodedlen(uint32_t t_cost, uint32_t m_cost,
uint32_t parallelism, uint32_t saltlen,
uint32_t hashlen, argon2_type type);
#if defined(__cplusplus)
}
#endif
#endif

View File

@@ -0,0 +1,156 @@
/*
* Argon2 reference source code package - reference C implementations
*
* Copyright 2015
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
*
* You may use this work under the terms of a Creative Commons CC0 1.0
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
* these licenses can be found at:
*
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
*
* You should have received a copy of both of these licenses along with this
* software. If not, they may be obtained at the above URLs.
*/
#ifndef PORTABLE_BLAKE2_IMPL_H
#define PORTABLE_BLAKE2_IMPL_H
#include <stdint.h>
#include <string.h>
#if defined(_MSC_VER)
#define BLAKE2_INLINE __inline
#elif defined(__GNUC__) || defined(__clang__)
#define BLAKE2_INLINE __inline__
#else
#define BLAKE2_INLINE
#endif
/* Argon2 Team - Begin Code */
/*
Not an exhaustive list, but should cover the majority of modern platforms
Additionally, the code will always be correct---this is only a performance
tweak.
*/
#if (defined(__BYTE_ORDER__) && \
(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) || \
defined(__LITTLE_ENDIAN__) || defined(__ARMEL__) || defined(__MIPSEL__) || \
defined(__AARCH64EL__) || defined(__amd64__) || defined(__i386__) || \
defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) || \
defined(_M_ARM)
#define NATIVE_LITTLE_ENDIAN
#endif
/* Argon2 Team - End Code */
static BLAKE2_INLINE uint32_t load32(const void *src) {
#if defined(NATIVE_LITTLE_ENDIAN)
uint32_t w;
memcpy(&w, src, sizeof w);
return w;
#else
const uint8_t *p = (const uint8_t *)src;
uint32_t w = *p++;
w |= (uint32_t)(*p++) << 8;
w |= (uint32_t)(*p++) << 16;
w |= (uint32_t)(*p++) << 24;
return w;
#endif
}
static BLAKE2_INLINE uint64_t load64(const void *src) {
#if defined(NATIVE_LITTLE_ENDIAN)
uint64_t w;
memcpy(&w, src, sizeof w);
return w;
#else
const uint8_t *p = (const uint8_t *)src;
uint64_t w = *p++;
w |= (uint64_t)(*p++) << 8;
w |= (uint64_t)(*p++) << 16;
w |= (uint64_t)(*p++) << 24;
w |= (uint64_t)(*p++) << 32;
w |= (uint64_t)(*p++) << 40;
w |= (uint64_t)(*p++) << 48;
w |= (uint64_t)(*p++) << 56;
return w;
#endif
}
static BLAKE2_INLINE void store32(void *dst, uint32_t w) {
#if defined(NATIVE_LITTLE_ENDIAN)
memcpy(dst, &w, sizeof w);
#else
uint8_t *p = (uint8_t *)dst;
*p++ = (uint8_t)w;
w >>= 8;
*p++ = (uint8_t)w;
w >>= 8;
*p++ = (uint8_t)w;
w >>= 8;
*p++ = (uint8_t)w;
#endif
}
static BLAKE2_INLINE void store64(void *dst, uint64_t w) {
#if defined(NATIVE_LITTLE_ENDIAN)
memcpy(dst, &w, sizeof w);
#else
uint8_t *p = (uint8_t *)dst;
*p++ = (uint8_t)w;
w >>= 8;
*p++ = (uint8_t)w;
w >>= 8;
*p++ = (uint8_t)w;
w >>= 8;
*p++ = (uint8_t)w;
w >>= 8;
*p++ = (uint8_t)w;
w >>= 8;
*p++ = (uint8_t)w;
w >>= 8;
*p++ = (uint8_t)w;
w >>= 8;
*p++ = (uint8_t)w;
#endif
}
static BLAKE2_INLINE uint64_t load48(const void *src) {
const uint8_t *p = (const uint8_t *)src;
uint64_t w = *p++;
w |= (uint64_t)(*p++) << 8;
w |= (uint64_t)(*p++) << 16;
w |= (uint64_t)(*p++) << 24;
w |= (uint64_t)(*p++) << 32;
w |= (uint64_t)(*p++) << 40;
return w;
}
static BLAKE2_INLINE void store48(void *dst, uint64_t w) {
uint8_t *p = (uint8_t *)dst;
*p++ = (uint8_t)w;
w >>= 8;
*p++ = (uint8_t)w;
w >>= 8;
*p++ = (uint8_t)w;
w >>= 8;
*p++ = (uint8_t)w;
w >>= 8;
*p++ = (uint8_t)w;
w >>= 8;
*p++ = (uint8_t)w;
}
static BLAKE2_INLINE uint32_t rotr32(const uint32_t w, const unsigned c) {
return (w >> c) | (w << (32 - c));
}
static BLAKE2_INLINE uint64_t rotr64(const uint64_t w, const unsigned c) {
return (w >> c) | (w << (64 - c));
}
void clear_internal_memory(void *v, size_t n);
#endif

View File

@@ -0,0 +1,91 @@
/*
* Argon2 reference source code package - reference C implementations
*
* Copyright 2015
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
*
* You may use this work under the terms of a Creative Commons CC0 1.0
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
* these licenses can be found at:
*
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
*
* You should have received a copy of both of these licenses along with this
* software. If not, they may be obtained at the above URLs.
*/
#ifndef PORTABLE_BLAKE2_H
#define PORTABLE_BLAKE2_H
#include <stddef.h>
#include <stdint.h>
#include <limits.h>
#if defined(__cplusplus)
extern "C" {
#endif
enum blake2b_constant {
BLAKE2B_BLOCKBYTES = 128,
BLAKE2B_OUTBYTES = 64,
BLAKE2B_KEYBYTES = 64,
BLAKE2B_SALTBYTES = 16,
BLAKE2B_PERSONALBYTES = 16
};
#pragma pack(push, 1)
typedef struct __blake2b_param {
uint8_t digest_length; /* 1 */
uint8_t key_length; /* 2 */
uint8_t fanout; /* 3 */
uint8_t depth; /* 4 */
uint32_t leaf_length; /* 8 */
uint64_t node_offset; /* 16 */
uint8_t node_depth; /* 17 */
uint8_t inner_length; /* 18 */
uint8_t reserved[14]; /* 32 */
uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */
uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */
} blake2b_param;
#pragma pack(pop)
typedef struct __blake2b_state {
uint64_t h[8];
uint64_t t[2];
uint64_t f[2];
uint8_t buf[BLAKE2B_BLOCKBYTES];
unsigned buflen;
unsigned outlen;
uint8_t last_node;
} blake2b_state;
/* Ensure param structs have not been wrongly padded */
/* Poor man's static_assert */
enum {
blake2_size_check_0 = 1 / !!(CHAR_BIT == 8),
blake2_size_check_2 =
1 / !!(sizeof(blake2b_param) == sizeof(uint64_t) * CHAR_BIT)
};
/* Streaming API */
int blake2b_init(blake2b_state *S, size_t outlen);
int blake2b_init_key(blake2b_state *S, size_t outlen, const void *key,
size_t keylen);
int blake2b_init_param(blake2b_state *S, const blake2b_param *P);
int blake2b_update(blake2b_state *S, const void *in, size_t inlen);
int blake2b_final(blake2b_state *S, void *out, size_t outlen);
/* Simple API */
int blake2b(void *out, size_t outlen, const void *in, size_t inlen,
const void *key, size_t keylen);
/* Argon2 Team - Begin Code */
int blake2b_long(void *out, size_t outlen, const void *in, size_t inlen);
/* Argon2 Team - End Code */
#if defined(__cplusplus)
}
#endif
#endif

View File

@@ -0,0 +1,390 @@
/*
* Argon2 reference source code package - reference C implementations
*
* Copyright 2015
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
*
* You may use this work under the terms of a Creative Commons CC0 1.0
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
* these licenses can be found at:
*
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
*
* You should have received a copy of both of these licenses along with this
* software. If not, they may be obtained at the above URLs.
*/
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include "blake2.h"
#include "blake2-impl.h"
static const uint64_t blake2b_IV[8] = {
UINT64_C(0x6a09e667f3bcc908), UINT64_C(0xbb67ae8584caa73b),
UINT64_C(0x3c6ef372fe94f82b), UINT64_C(0xa54ff53a5f1d36f1),
UINT64_C(0x510e527fade682d1), UINT64_C(0x9b05688c2b3e6c1f),
UINT64_C(0x1f83d9abfb41bd6b), UINT64_C(0x5be0cd19137e2179)};
static const unsigned int blake2b_sigma[12][16] = {
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
{14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3},
{11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4},
{7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8},
{9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13},
{2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9},
{12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11},
{13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10},
{6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5},
{10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0},
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
{14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3},
};
static BLAKE2_INLINE void blake2b_set_lastnode(blake2b_state *S) {
S->f[1] = (uint64_t)-1;
}
static BLAKE2_INLINE void blake2b_set_lastblock(blake2b_state *S) {
if (S->last_node) {
blake2b_set_lastnode(S);
}
S->f[0] = (uint64_t)-1;
}
static BLAKE2_INLINE void blake2b_increment_counter(blake2b_state *S,
uint64_t inc) {
S->t[0] += inc;
S->t[1] += (S->t[0] < inc);
}
static BLAKE2_INLINE void blake2b_invalidate_state(blake2b_state *S) {
clear_internal_memory(S, sizeof(*S)); /* wipe */
blake2b_set_lastblock(S); /* invalidate for further use */
}
static BLAKE2_INLINE void blake2b_init0(blake2b_state *S) {
memset(S, 0, sizeof(*S));
memcpy(S->h, blake2b_IV, sizeof(S->h));
}
int blake2b_init_param(blake2b_state *S, const blake2b_param *P) {
const unsigned char *p = (const unsigned char *)P;
unsigned int i;
if (NULL == P || NULL == S) {
return -1;
}
blake2b_init0(S);
/* IV XOR Parameter Block */
for (i = 0; i < 8; ++i) {
S->h[i] ^= load64(&p[i * sizeof(S->h[i])]);
}
S->outlen = P->digest_length;
return 0;
}
/* Sequential blake2b initialization */
int blake2b_init(blake2b_state *S, size_t outlen) {
blake2b_param P;
if (S == NULL) {
return -1;
}
if ((outlen == 0) || (outlen > BLAKE2B_OUTBYTES)) {
blake2b_invalidate_state(S);
return -1;
}
/* Setup Parameter Block for unkeyed BLAKE2 */
P.digest_length = (uint8_t)outlen;
P.key_length = 0;
P.fanout = 1;
P.depth = 1;
P.leaf_length = 0;
P.node_offset = 0;
P.node_depth = 0;
P.inner_length = 0;
memset(P.reserved, 0, sizeof(P.reserved));
memset(P.salt, 0, sizeof(P.salt));
memset(P.personal, 0, sizeof(P.personal));
return blake2b_init_param(S, &P);
}
int blake2b_init_key(blake2b_state *S, size_t outlen, const void *key,
size_t keylen) {
blake2b_param P;
if (S == NULL) {
return -1;
}
if ((outlen == 0) || (outlen > BLAKE2B_OUTBYTES)) {
blake2b_invalidate_state(S);
return -1;
}
if ((key == 0) || (keylen == 0) || (keylen > BLAKE2B_KEYBYTES)) {
blake2b_invalidate_state(S);
return -1;
}
/* Setup Parameter Block for keyed BLAKE2 */
P.digest_length = (uint8_t)outlen;
P.key_length = (uint8_t)keylen;
P.fanout = 1;
P.depth = 1;
P.leaf_length = 0;
P.node_offset = 0;
P.node_depth = 0;
P.inner_length = 0;
memset(P.reserved, 0, sizeof(P.reserved));
memset(P.salt, 0, sizeof(P.salt));
memset(P.personal, 0, sizeof(P.personal));
if (blake2b_init_param(S, &P) < 0) {
blake2b_invalidate_state(S);
return -1;
}
{
uint8_t block[BLAKE2B_BLOCKBYTES];
memset(block, 0, BLAKE2B_BLOCKBYTES);
memcpy(block, key, keylen);
blake2b_update(S, block, BLAKE2B_BLOCKBYTES);
/* Burn the key from stack */
clear_internal_memory(block, BLAKE2B_BLOCKBYTES);
}
return 0;
}
static void blake2b_compress(blake2b_state *S, const uint8_t *block) {
uint64_t m[16];
uint64_t v[16];
unsigned int i, r;
for (i = 0; i < 16; ++i) {
m[i] = load64(block + i * sizeof(m[i]));
}
for (i = 0; i < 8; ++i) {
v[i] = S->h[i];
}
v[8] = blake2b_IV[0];
v[9] = blake2b_IV[1];
v[10] = blake2b_IV[2];
v[11] = blake2b_IV[3];
v[12] = blake2b_IV[4] ^ S->t[0];
v[13] = blake2b_IV[5] ^ S->t[1];
v[14] = blake2b_IV[6] ^ S->f[0];
v[15] = blake2b_IV[7] ^ S->f[1];
#define G(r, i, a, b, c, d) \
do { \
a = a + b + m[blake2b_sigma[r][2 * i + 0]]; \
d = rotr64(d ^ a, 32); \
c = c + d; \
b = rotr64(b ^ c, 24); \
a = a + b + m[blake2b_sigma[r][2 * i + 1]]; \
d = rotr64(d ^ a, 16); \
c = c + d; \
b = rotr64(b ^ c, 63); \
} while ((void)0, 0)
#define ROUND(r) \
do { \
G(r, 0, v[0], v[4], v[8], v[12]); \
G(r, 1, v[1], v[5], v[9], v[13]); \
G(r, 2, v[2], v[6], v[10], v[14]); \
G(r, 3, v[3], v[7], v[11], v[15]); \
G(r, 4, v[0], v[5], v[10], v[15]); \
G(r, 5, v[1], v[6], v[11], v[12]); \
G(r, 6, v[2], v[7], v[8], v[13]); \
G(r, 7, v[3], v[4], v[9], v[14]); \
} while ((void)0, 0)
for (r = 0; r < 12; ++r) {
ROUND(r);
}
for (i = 0; i < 8; ++i) {
S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
}
#undef G
#undef ROUND
}
int blake2b_update(blake2b_state *S, const void *in, size_t inlen) {
const uint8_t *pin = (const uint8_t *)in;
if (inlen == 0) {
return 0;
}
/* Sanity check */
if (S == NULL || in == NULL) {
return -1;
}
/* Is this a reused state? */
if (S->f[0] != 0) {
return -1;
}
if (S->buflen + inlen > BLAKE2B_BLOCKBYTES) {
/* Complete current block */
size_t left = S->buflen;
size_t fill = BLAKE2B_BLOCKBYTES - left;
memcpy(&S->buf[left], pin, fill);
blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
blake2b_compress(S, S->buf);
S->buflen = 0;
inlen -= fill;
pin += fill;
/* Avoid buffer copies when possible */
while (inlen > BLAKE2B_BLOCKBYTES) {
blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
blake2b_compress(S, pin);
inlen -= BLAKE2B_BLOCKBYTES;
pin += BLAKE2B_BLOCKBYTES;
}
}
memcpy(&S->buf[S->buflen], pin, inlen);
S->buflen += (unsigned int)inlen;
return 0;
}
int blake2b_final(blake2b_state *S, void *out, size_t outlen) {
uint8_t buffer[BLAKE2B_OUTBYTES] = {0};
unsigned int i;
/* Sanity checks */
if (S == NULL || out == NULL || outlen < S->outlen) {
return -1;
}
/* Is this a reused state? */
if (S->f[0] != 0) {
return -1;
}
blake2b_increment_counter(S, S->buflen);
blake2b_set_lastblock(S);
memset(&S->buf[S->buflen], 0, BLAKE2B_BLOCKBYTES - S->buflen); /* Padding */
blake2b_compress(S, S->buf);
for (i = 0; i < 8; ++i) { /* Output full hash to temp buffer */
store64(buffer + sizeof(S->h[i]) * i, S->h[i]);
}
memcpy(out, buffer, S->outlen);
clear_internal_memory(buffer, sizeof(buffer));
clear_internal_memory(S->buf, sizeof(S->buf));
clear_internal_memory(S->h, sizeof(S->h));
return 0;
}
int blake2b(void *out, size_t outlen, const void *in, size_t inlen,
const void *key, size_t keylen) {
blake2b_state S;
int ret = -1;
/* Verify parameters */
if (NULL == in && inlen > 0) {
goto fail;
}
if (NULL == out || outlen == 0 || outlen > BLAKE2B_OUTBYTES) {
goto fail;
}
if ((NULL == key && keylen > 0) || keylen > BLAKE2B_KEYBYTES) {
goto fail;
}
if (keylen > 0) {
if (blake2b_init_key(&S, outlen, key, keylen) < 0) {
goto fail;
}
} else {
if (blake2b_init(&S, outlen) < 0) {
goto fail;
}
}
if (blake2b_update(&S, in, inlen) < 0) {
goto fail;
}
ret = blake2b_final(&S, out, outlen);
fail:
clear_internal_memory(&S, sizeof(S));
return ret;
}
/* Argon2 Team - Begin Code */
int blake2b_long(void *pout, size_t outlen, const void *in, size_t inlen) {
uint8_t *out = (uint8_t *)pout;
blake2b_state blake_state;
uint8_t outlen_bytes[sizeof(uint32_t)] = {0};
int ret = -1;
if (outlen > UINT32_MAX) {
goto fail;
}
/* Ensure little-endian byte order! */
store32(outlen_bytes, (uint32_t)outlen);
#define TRY(statement) \
do { \
ret = statement; \
if (ret < 0) { \
goto fail; \
} \
} while ((void)0, 0)
if (outlen <= BLAKE2B_OUTBYTES) {
TRY(blake2b_init(&blake_state, outlen));
TRY(blake2b_update(&blake_state, outlen_bytes, sizeof(outlen_bytes)));
TRY(blake2b_update(&blake_state, in, inlen));
TRY(blake2b_final(&blake_state, out, outlen));
} else {
uint32_t toproduce;
uint8_t out_buffer[BLAKE2B_OUTBYTES];
uint8_t in_buffer[BLAKE2B_OUTBYTES];
TRY(blake2b_init(&blake_state, BLAKE2B_OUTBYTES));
TRY(blake2b_update(&blake_state, outlen_bytes, sizeof(outlen_bytes)));
TRY(blake2b_update(&blake_state, in, inlen));
TRY(blake2b_final(&blake_state, out_buffer, BLAKE2B_OUTBYTES));
memcpy(out, out_buffer, BLAKE2B_OUTBYTES / 2);
out += BLAKE2B_OUTBYTES / 2;
toproduce = (uint32_t)outlen - BLAKE2B_OUTBYTES / 2;
while (toproduce > BLAKE2B_OUTBYTES) {
memcpy(in_buffer, out_buffer, BLAKE2B_OUTBYTES);
TRY(blake2b(out_buffer, BLAKE2B_OUTBYTES, in_buffer,
BLAKE2B_OUTBYTES, NULL, 0));
memcpy(out, out_buffer, BLAKE2B_OUTBYTES / 2);
out += BLAKE2B_OUTBYTES / 2;
toproduce -= BLAKE2B_OUTBYTES / 2;
}
memcpy(in_buffer, out_buffer, BLAKE2B_OUTBYTES);
TRY(blake2b(out_buffer, toproduce, in_buffer, BLAKE2B_OUTBYTES, NULL,
0));
memcpy(out, out_buffer, toproduce);
}
fail:
clear_internal_memory(&blake_state, sizeof(blake_state));
return ret;
#undef TRY
}
/* Argon2 Team - End Code */

View File

@@ -0,0 +1,56 @@
/*
* Argon2 reference source code package - reference C implementations
*
* Copyright 2015
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
*
* You may use this work under the terms of a Creative Commons CC0 1.0
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
* these licenses can be found at:
*
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
*
* You should have received a copy of both of these licenses along with this
* software. If not, they may be obtained at the above URLs.
*/
#ifndef BLAKE_ROUND_MKA_H
#define BLAKE_ROUND_MKA_H
#include "blake2.h"
#include "blake2-impl.h"
/*designed by the Lyra PHC team */
static BLAKE2_INLINE uint64_t fBlaMka(uint64_t x, uint64_t y) {
const uint64_t m = UINT64_C(0xFFFFFFFF);
const uint64_t xy = (x & m) * (y & m);
return x + y + 2 * xy;
}
#define G(a, b, c, d) \
do { \
a = fBlaMka(a, b); \
d = rotr64(d ^ a, 32); \
c = fBlaMka(c, d); \
b = rotr64(b ^ c, 24); \
a = fBlaMka(a, b); \
d = rotr64(d ^ a, 16); \
c = fBlaMka(c, d); \
b = rotr64(b ^ c, 63); \
} while ((void)0, 0)
#define BLAKE2_ROUND_NOMSG(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, \
v12, v13, v14, v15) \
do { \
G(v0, v4, v8, v12); \
G(v1, v5, v9, v13); \
G(v2, v6, v10, v14); \
G(v3, v7, v11, v15); \
G(v0, v5, v10, v15); \
G(v1, v6, v11, v12); \
G(v2, v7, v8, v13); \
G(v3, v4, v9, v14); \
} while ((void)0, 0)
#endif

View File

@@ -0,0 +1,635 @@
/*
* Argon2 reference source code package - reference C implementations
*
* Copyright 2015
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
*
* You may use this work under the terms of a Creative Commons CC0 1.0
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
* these licenses can be found at:
*
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
*
* You should have received a copy of both of these licenses along with this
* software. If not, they may be obtained at the above URLs.
*/
/*For memory wiping*/
#ifdef _MSC_VER
#include <windows.h>
#include <winbase.h> /* For SecureZeroMemory */
#endif
#if defined __STDC_LIB_EXT1__
#define __STDC_WANT_LIB_EXT1__ 1
#endif
#define VC_GE_2005(version) (version >= 1400)
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "core.h"
#include "thread.h"
#include "blake2/blake2.h"
#include "blake2/blake2-impl.h"
#ifdef GENKAT
#include "genkat.h"
#endif
#if defined(__clang__)
#if __has_attribute(optnone)
#define NOT_OPTIMIZED __attribute__((optnone))
#endif
#elif defined(__GNUC__)
#define GCC_VERSION \
(__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
#if GCC_VERSION >= 40400
#define NOT_OPTIMIZED __attribute__((optimize("O0")))
#endif
#endif
#ifndef NOT_OPTIMIZED
#define NOT_OPTIMIZED
#endif
/***************Instance and Position constructors**********/
void init_block_value(block *b, uint8_t in) { memset(b->v, in, sizeof(b->v)); }
void copy_block(block *dst, const block *src) {
memcpy(dst->v, src->v, sizeof(uint64_t) * ARGON2_QWORDS_IN_BLOCK);
}
void xor_block(block *dst, const block *src) {
int i;
for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) {
dst->v[i] ^= src->v[i];
}
}
static void load_block(block *dst, const void *input) {
unsigned i;
for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) {
dst->v[i] = load64((const uint8_t *)input + i * sizeof(dst->v[i]));
}
}
static void store_block(void *output, const block *src) {
unsigned i;
for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) {
store64((uint8_t *)output + i * sizeof(src->v[i]), src->v[i]);
}
}
/***************Memory functions*****************/
int allocate_memory(const argon2_context *context, uint8_t **memory,
size_t num, size_t size) {
size_t memory_size = num*size;
if (memory == NULL) {
return ARGON2_MEMORY_ALLOCATION_ERROR;
}
/* 1. Check for multiplication overflow */
if (size != 0 && memory_size / size != num) {
return ARGON2_MEMORY_ALLOCATION_ERROR;
}
/* 2. Try to allocate with appropriate allocator */
if (context->allocate_cbk) {
(context->allocate_cbk)(memory, memory_size);
} else {
*memory = malloc(memory_size);
}
if (*memory == NULL) {
return ARGON2_MEMORY_ALLOCATION_ERROR;
}
return ARGON2_OK;
}
void free_memory(const argon2_context *context, uint8_t *memory,
size_t num, size_t size) {
size_t memory_size = num*size;
clear_internal_memory(memory, memory_size);
if (context->free_cbk) {
(context->free_cbk)(memory, memory_size);
} else {
free(memory);
}
}
void NOT_OPTIMIZED secure_wipe_memory(void *v, size_t n) {
#if defined(_MSC_VER) && VC_GE_2005(_MSC_VER)
SecureZeroMemory(v, n);
#elif defined memset_s
memset_s(v, n, 0, n);
#elif defined(__OpenBSD__)
explicit_bzero(v, n);
#else
static void *(*const volatile memset_sec)(void *, int, size_t) = &memset;
memset_sec(v, 0, n);
#endif
}
/* Memory clear flag defaults to true. */
int FLAG_clear_internal_memory = 1;
void clear_internal_memory(void *v, size_t n) {
if (FLAG_clear_internal_memory && v) {
secure_wipe_memory(v, n);
}
}
void finalize(const argon2_context *context, argon2_instance_t *instance) {
if (context != NULL && instance != NULL) {
block blockhash;
uint32_t l;
copy_block(&blockhash, instance->memory + instance->lane_length - 1);
/* XOR the last blocks */
for (l = 1; l < instance->lanes; ++l) {
uint32_t last_block_in_lane =
l * instance->lane_length + (instance->lane_length - 1);
xor_block(&blockhash, instance->memory + last_block_in_lane);
}
/* Hash the result */
{
uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE];
store_block(blockhash_bytes, &blockhash);
blake2b_long(context->out, context->outlen, blockhash_bytes,
ARGON2_BLOCK_SIZE);
/* clear blockhash and blockhash_bytes */
clear_internal_memory(blockhash.v, ARGON2_BLOCK_SIZE);
clear_internal_memory(blockhash_bytes, ARGON2_BLOCK_SIZE);
}
#ifdef GENKAT
print_tag(context->out, context->outlen);
#endif
free_memory(context, (uint8_t *)instance->memory,
instance->memory_blocks, sizeof(block));
}
}
uint32_t index_alpha(const argon2_instance_t *instance,
const argon2_position_t *position, uint32_t pseudo_rand,
int same_lane) {
/*
* Pass 0:
* This lane : all already finished segments plus already constructed
* blocks in this segment
* Other lanes : all already finished segments
* Pass 1+:
* This lane : (SYNC_POINTS - 1) last segments plus already constructed
* blocks in this segment
* Other lanes : (SYNC_POINTS - 1) last segments
*/
uint32_t reference_area_size;
uint64_t relative_position;
uint32_t start_position, absolute_position;
if (0 == position->pass) {
/* First pass */
if (0 == position->slice) {
/* First slice */
reference_area_size =
position->index - 1; /* all but the previous */
} else {
if (same_lane) {
/* The same lane => add current segment */
reference_area_size =
position->slice * instance->segment_length +
position->index - 1;
} else {
reference_area_size =
position->slice * instance->segment_length +
((position->index == 0) ? (-1) : 0);
}
}
} else {
/* Second pass */
if (same_lane) {
reference_area_size = instance->lane_length -
instance->segment_length + position->index -
1;
} else {
reference_area_size = instance->lane_length -
instance->segment_length +
((position->index == 0) ? (-1) : 0);
}
}
/* 1.2.4. Mapping pseudo_rand to 0..<reference_area_size-1> and produce
* relative position */
relative_position = pseudo_rand;
relative_position = relative_position * relative_position >> 32;
relative_position = reference_area_size - 1 -
(reference_area_size * relative_position >> 32);
/* 1.2.5 Computing starting position */
start_position = 0;
if (0 != position->pass) {
start_position = (position->slice == ARGON2_SYNC_POINTS - 1)
? 0
: (position->slice + 1) * instance->segment_length;
}
/* 1.2.6. Computing absolute position */
absolute_position = (start_position + relative_position) %
instance->lane_length; /* absolute position */
return absolute_position;
}
/* Single-threaded version for p=1 case */
static int fill_memory_blocks_st(argon2_instance_t *instance) {
uint32_t r, s, l;
for (r = 0; r < instance->passes; ++r) {
for (s = 0; s < ARGON2_SYNC_POINTS; ++s) {
for (l = 0; l < instance->lanes; ++l) {
argon2_position_t position = {r, l, (uint8_t)s, 0};
fill_segment(instance, position);
}
}
#ifdef GENKAT
internal_kat(instance, r); /* Print all memory blocks */
#endif
}
return ARGON2_OK;
}
#if !defined(ARGON2_NO_THREADS)
#ifdef _WIN32
static unsigned __stdcall fill_segment_thr(void *thread_data)
#else
static void *fill_segment_thr(void *thread_data)
#endif
{
argon2_thread_data *my_data = thread_data;
fill_segment(my_data->instance_ptr, my_data->pos);
argon2_thread_exit();
return 0;
}
/* Multi-threaded version for p > 1 case */
static int fill_memory_blocks_mt(argon2_instance_t *instance) {
uint32_t r, s;
argon2_thread_handle_t *thread = NULL;
argon2_thread_data *thr_data = NULL;
int rc = ARGON2_OK;
/* 1. Allocating space for threads */
thread = calloc(instance->lanes, sizeof(argon2_thread_handle_t));
if (thread == NULL) {
rc = ARGON2_MEMORY_ALLOCATION_ERROR;
goto fail;
}
thr_data = calloc(instance->lanes, sizeof(argon2_thread_data));
if (thr_data == NULL) {
rc = ARGON2_MEMORY_ALLOCATION_ERROR;
goto fail;
}
for (r = 0; r < instance->passes; ++r) {
for (s = 0; s < ARGON2_SYNC_POINTS; ++s) {
uint32_t l;
/* 2. Calling threads */
for (l = 0; l < instance->lanes; ++l) {
argon2_position_t position;
/* 2.1 Join a thread if limit is exceeded */
if (l >= instance->threads) {
if (argon2_thread_join(thread[l - instance->threads])) {
rc = ARGON2_THREAD_FAIL;
goto fail;
}
}
/* 2.2 Create thread */
position.pass = r;
position.lane = l;
position.slice = (uint8_t)s;
position.index = 0;
thr_data[l].instance_ptr =
instance; /* preparing the thread input */
memcpy(&(thr_data[l].pos), &position,
sizeof(argon2_position_t));
if (argon2_thread_create(&thread[l], &fill_segment_thr,
(void *)&thr_data[l])) {
rc = ARGON2_THREAD_FAIL;
goto fail;
}
/* fill_segment(instance, position); */
/*Non-thread equivalent of the lines above */
}
/* 3. Joining remaining threads */
for (l = instance->lanes - instance->threads; l < instance->lanes;
++l) {
if (argon2_thread_join(thread[l])) {
rc = ARGON2_THREAD_FAIL;
goto fail;
}
}
}
#ifdef GENKAT
internal_kat(instance, r); /* Print all memory blocks */
#endif
}
fail:
if (thread != NULL) {
free(thread);
}
if (thr_data != NULL) {
free(thr_data);
}
return rc;
}
#endif /* ARGON2_NO_THREADS */
int fill_memory_blocks(argon2_instance_t *instance) {
if (instance == NULL || instance->lanes == 0) {
return ARGON2_INCORRECT_PARAMETER;
}
#if defined(ARGON2_NO_THREADS)
return fill_memory_blocks_st(instance);
#else
return instance->threads == 1 ?
fill_memory_blocks_st(instance) : fill_memory_blocks_mt(instance);
#endif
}
int validate_inputs(const argon2_context *context) {
if (NULL == context) {
return ARGON2_INCORRECT_PARAMETER;
}
if (NULL == context->out) {
return ARGON2_OUTPUT_PTR_NULL;
}
/* Validate output length */
if (ARGON2_MIN_OUTLEN > context->outlen) {
return ARGON2_OUTPUT_TOO_SHORT;
}
if (ARGON2_MAX_OUTLEN < context->outlen) {
return ARGON2_OUTPUT_TOO_LONG;
}
/* Validate password (required param) */
if (NULL == context->pwd) {
if (0 != context->pwdlen) {
return ARGON2_PWD_PTR_MISMATCH;
}
}
if (ARGON2_MIN_PWD_LENGTH > context->pwdlen) {
return ARGON2_PWD_TOO_SHORT;
}
if (ARGON2_MAX_PWD_LENGTH < context->pwdlen) {
return ARGON2_PWD_TOO_LONG;
}
/* Validate salt (required param) */
if (NULL == context->salt) {
if (0 != context->saltlen) {
return ARGON2_SALT_PTR_MISMATCH;
}
}
if (ARGON2_MIN_SALT_LENGTH > context->saltlen) {
return ARGON2_SALT_TOO_SHORT;
}
if (ARGON2_MAX_SALT_LENGTH < context->saltlen) {
return ARGON2_SALT_TOO_LONG;
}
/* Validate secret (optional param) */
if (NULL == context->secret) {
if (0 != context->secretlen) {
return ARGON2_SECRET_PTR_MISMATCH;
}
} else {
if (ARGON2_MIN_SECRET > context->secretlen) {
return ARGON2_SECRET_TOO_SHORT;
}
if (ARGON2_MAX_SECRET < context->secretlen) {
return ARGON2_SECRET_TOO_LONG;
}
}
/* Validate associated data (optional param) */
if (NULL == context->ad) {
if (0 != context->adlen) {
return ARGON2_AD_PTR_MISMATCH;
}
} else {
if (ARGON2_MIN_AD_LENGTH > context->adlen) {
return ARGON2_AD_TOO_SHORT;
}
if (ARGON2_MAX_AD_LENGTH < context->adlen) {
return ARGON2_AD_TOO_LONG;
}
}
/* Validate memory cost */
if (ARGON2_MIN_MEMORY > context->m_cost) {
return ARGON2_MEMORY_TOO_LITTLE;
}
if (ARGON2_MAX_MEMORY < context->m_cost) {
return ARGON2_MEMORY_TOO_MUCH;
}
if (context->m_cost < 8 * context->lanes) {
return ARGON2_MEMORY_TOO_LITTLE;
}
/* Validate time cost */
if (ARGON2_MIN_TIME > context->t_cost) {
return ARGON2_TIME_TOO_SMALL;
}
if (ARGON2_MAX_TIME < context->t_cost) {
return ARGON2_TIME_TOO_LARGE;
}
/* Validate lanes */
if (ARGON2_MIN_LANES > context->lanes) {
return ARGON2_LANES_TOO_FEW;
}
if (ARGON2_MAX_LANES < context->lanes) {
return ARGON2_LANES_TOO_MANY;
}
/* Validate threads */
if (ARGON2_MIN_THREADS > context->threads) {
return ARGON2_THREADS_TOO_FEW;
}
if (ARGON2_MAX_THREADS < context->threads) {
return ARGON2_THREADS_TOO_MANY;
}
if (NULL != context->allocate_cbk && NULL == context->free_cbk) {
return ARGON2_FREE_MEMORY_CBK_NULL;
}
if (NULL == context->allocate_cbk && NULL != context->free_cbk) {
return ARGON2_ALLOCATE_MEMORY_CBK_NULL;
}
return ARGON2_OK;
}
void fill_first_blocks(uint8_t *blockhash, const argon2_instance_t *instance) {
uint32_t l;
/* Make the first and second block in each lane as G(H0||0||i) or
G(H0||1||i) */
uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE];
for (l = 0; l < instance->lanes; ++l) {
store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 0);
store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH + 4, l);
blake2b_long(blockhash_bytes, ARGON2_BLOCK_SIZE, blockhash,
ARGON2_PREHASH_SEED_LENGTH);
load_block(&instance->memory[l * instance->lane_length + 0],
blockhash_bytes);
store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 1);
blake2b_long(blockhash_bytes, ARGON2_BLOCK_SIZE, blockhash,
ARGON2_PREHASH_SEED_LENGTH);
load_block(&instance->memory[l * instance->lane_length + 1],
blockhash_bytes);
}
clear_internal_memory(blockhash_bytes, ARGON2_BLOCK_SIZE);
}
void initial_hash(uint8_t *blockhash, argon2_context *context,
argon2_type type) {
blake2b_state BlakeHash;
uint8_t value[sizeof(uint32_t)];
if (NULL == context || NULL == blockhash) {
return;
}
blake2b_init(&BlakeHash, ARGON2_PREHASH_DIGEST_LENGTH);
store32(&value, context->lanes);
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
store32(&value, context->outlen);
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
store32(&value, context->m_cost);
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
store32(&value, context->t_cost);
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
store32(&value, context->version);
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
store32(&value, (uint32_t)type);
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
store32(&value, context->pwdlen);
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
if (context->pwd != NULL) {
blake2b_update(&BlakeHash, (const uint8_t *)context->pwd,
context->pwdlen);
if (context->flags & ARGON2_FLAG_CLEAR_PASSWORD) {
secure_wipe_memory(context->pwd, context->pwdlen);
context->pwdlen = 0;
}
}
store32(&value, context->saltlen);
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
if (context->salt != NULL) {
blake2b_update(&BlakeHash, (const uint8_t *)context->salt,
context->saltlen);
}
store32(&value, context->secretlen);
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
if (context->secret != NULL) {
blake2b_update(&BlakeHash, (const uint8_t *)context->secret,
context->secretlen);
if (context->flags & ARGON2_FLAG_CLEAR_SECRET) {
secure_wipe_memory(context->secret, context->secretlen);
context->secretlen = 0;
}
}
store32(&value, context->adlen);
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
if (context->ad != NULL) {
blake2b_update(&BlakeHash, (const uint8_t *)context->ad,
context->adlen);
}
blake2b_final(&BlakeHash, blockhash, ARGON2_PREHASH_DIGEST_LENGTH);
}
int initialize(argon2_instance_t *instance, argon2_context *context) {
uint8_t blockhash[ARGON2_PREHASH_SEED_LENGTH];
int result = ARGON2_OK;
if (instance == NULL || context == NULL)
return ARGON2_INCORRECT_PARAMETER;
instance->context_ptr = context;
/* 1. Memory allocation */
result = allocate_memory(context, (uint8_t **)&(instance->memory),
instance->memory_blocks, sizeof(block));
if (result != ARGON2_OK) {
return result;
}
/* 2. Initial hashing */
/* H_0 + 8 extra bytes to produce the first blocks */
/* uint8_t blockhash[ARGON2_PREHASH_SEED_LENGTH]; */
/* Hashing all inputs */
initial_hash(blockhash, context, instance->type);
/* Zeroing 8 extra bytes */
clear_internal_memory(blockhash + ARGON2_PREHASH_DIGEST_LENGTH,
ARGON2_PREHASH_SEED_LENGTH -
ARGON2_PREHASH_DIGEST_LENGTH);
#ifdef GENKAT
initial_kat(blockhash, context, instance->type);
#endif
/* 3. Creating first blocks, we always have at least two blocks in a slice
*/
fill_first_blocks(blockhash, instance);
/* Clearing the hash */
clear_internal_memory(blockhash, ARGON2_PREHASH_SEED_LENGTH);
return ARGON2_OK;
}

View File

@@ -0,0 +1,227 @@
/*
* Argon2 reference source code package - reference C implementations
*
* Copyright 2015
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
*
* You may use this work under the terms of a Creative Commons CC0 1.0
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
* these licenses can be found at:
*
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
*
* You should have received a copy of both of these licenses along with this
* software. If not, they may be obtained at the above URLs.
*/
#ifndef ARGON2_CORE_H
#define ARGON2_CORE_H
#include "argon2.h"
#define CONST_CAST(x) (x)(uintptr_t)
/**********************Argon2 internal constants*******************************/
enum argon2_core_constants {
/* Memory block size in bytes */
ARGON2_BLOCK_SIZE = 1024,
ARGON2_QWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 8,
ARGON2_OWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 16,
ARGON2_HWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 32,
/* Number of pseudo-random values generated by one call to Blake in Argon2i
to
generate reference block positions */
ARGON2_ADDRESSES_IN_BLOCK = 128,
/* Pre-hashing digest length and its extension*/
ARGON2_PREHASH_DIGEST_LENGTH = 64,
ARGON2_PREHASH_SEED_LENGTH = 72
};
/*************************Argon2 internal data types***********************/
/*
* Structure for the (1KB) memory block implemented as 128 64-bit words.
* Memory blocks can be copied, XORed. Internal words can be accessed by [] (no
* bounds checking).
*/
typedef struct block_ { uint64_t v[ARGON2_QWORDS_IN_BLOCK]; } block;
/*****************Functions that work with the block******************/
/* Initialize each byte of the block with @in */
void init_block_value(block *b, uint8_t in);
/* Copy block @src to block @dst */
void copy_block(block *dst, const block *src);
/* XOR @src onto @dst bytewise */
void xor_block(block *dst, const block *src);
/*
* Argon2 instance: memory pointer, number of passes, amount of memory, type,
* and derived values.
* Used to evaluate the number and location of blocks to construct in each
* thread
*/
typedef struct Argon2_instance_t {
block *memory; /* Memory pointer */
uint32_t version;
uint32_t passes; /* Number of passes */
uint32_t memory_blocks; /* Number of blocks in memory */
uint32_t segment_length;
uint32_t lane_length;
uint32_t lanes;
uint32_t threads;
argon2_type type;
int print_internals; /* whether to print the memory blocks */
argon2_context *context_ptr; /* points back to original context */
} argon2_instance_t;
/*
* Argon2 position: where we construct the block right now. Used to distribute
* work between threads.
*/
typedef struct Argon2_position_t {
uint32_t pass;
uint32_t lane;
uint8_t slice;
uint32_t index;
} argon2_position_t;
/*Struct that holds the inputs for thread handling FillSegment*/
typedef struct Argon2_thread_data {
argon2_instance_t *instance_ptr;
argon2_position_t pos;
} argon2_thread_data;
/*************************Argon2 core functions********************************/
/* Allocates memory to the given pointer, uses the appropriate allocator as
* specified in the context. Total allocated memory is num*size.
* @param context argon2_context which specifies the allocator
* @param memory pointer to the pointer to the memory
* @param size the size in bytes for each element to be allocated
* @param num the number of elements to be allocated
* @return ARGON2_OK if @memory is a valid pointer and memory is allocated
*/
int allocate_memory(const argon2_context *context, uint8_t **memory,
size_t num, size_t size);
/*
* Frees memory at the given pointer, uses the appropriate deallocator as
* specified in the context. Also cleans the memory using clear_internal_memory.
* @param context argon2_context which specifies the deallocator
* @param memory pointer to buffer to be freed
* @param size the size in bytes for each element to be deallocated
* @param num the number of elements to be deallocated
*/
void free_memory(const argon2_context *context, uint8_t *memory,
size_t num, size_t size);
/* Function that securely cleans the memory. This ignores any flags set
* regarding clearing memory. Usually one just calls clear_internal_memory.
* @param mem Pointer to the memory
* @param s Memory size in bytes
*/
void secure_wipe_memory(void *v, size_t n);
/* Function that securely clears the memory if FLAG_clear_internal_memory is
* set. If the flag isn't set, this function does nothing.
* @param mem Pointer to the memory
* @param s Memory size in bytes
*/
void clear_internal_memory(void *v, size_t n);
/*
* Computes absolute position of reference block in the lane following a skewed
* distribution and using a pseudo-random value as input
* @param instance Pointer to the current instance
* @param position Pointer to the current position
* @param pseudo_rand 32-bit pseudo-random value used to determine the position
* @param same_lane Indicates if the block will be taken from the current lane.
* If so we can reference the current segment
* @pre All pointers must be valid
*/
uint32_t index_alpha(const argon2_instance_t *instance,
const argon2_position_t *position, uint32_t pseudo_rand,
int same_lane);
/*
* Function that validates all inputs against predefined restrictions and return
* an error code
* @param context Pointer to current Argon2 context
* @return ARGON2_OK if everything is all right, otherwise one of error codes
* (all defined in <argon2.h>
*/
int validate_inputs(const argon2_context *context);
/*
* Hashes all the inputs into @a blockhash[PREHASH_DIGEST_LENGTH], clears
* password and secret if needed
* @param context Pointer to the Argon2 internal structure containing memory
* pointer, and parameters for time and space requirements.
* @param blockhash Buffer for pre-hashing digest
* @param type Argon2 type
* @pre @a blockhash must have at least @a PREHASH_DIGEST_LENGTH bytes
* allocated
*/
void initial_hash(uint8_t *blockhash, argon2_context *context,
argon2_type type);
/*
* Function creates first 2 blocks per lane
* @param instance Pointer to the current instance
* @param blockhash Pointer to the pre-hashing digest
* @pre blockhash must point to @a PREHASH_SEED_LENGTH allocated values
*/
void fill_first_blocks(uint8_t *blockhash, const argon2_instance_t *instance);
/*
* Function allocates memory, hashes the inputs with Blake, and creates first
* two blocks. Returns the pointer to the main memory with 2 blocks per lane
* initialized
* @param context Pointer to the Argon2 internal structure containing memory
* pointer, and parameters for time and space requirements.
* @param instance Current Argon2 instance
* @return Zero if successful, -1 if memory failed to allocate. @context->state
* will be modified if successful.
*/
int initialize(argon2_instance_t *instance, argon2_context *context);
/*
* XORing the last block of each lane, hashing it, making the tag. Deallocates
* the memory.
* @param context Pointer to current Argon2 context (use only the out parameters
* from it)
* @param instance Pointer to current instance of Argon2
* @pre instance->state must point to necessary amount of memory
* @pre context->out must point to outlen bytes of memory
* @pre if context->free_cbk is not NULL, it should point to a function that
* deallocates memory
*/
void finalize(const argon2_context *context, argon2_instance_t *instance);
/*
* Function that fills the segment using previous segments also from other
* threads
* @param context current context
* @param instance Pointer to the current instance
* @param position Current position
* @pre all block pointers must be valid
*/
void fill_segment(const argon2_instance_t *instance,
argon2_position_t position);
/*
* Function that fills the entire memory t_cost times based on the first two
* blocks in each lane
* @param instance Pointer to the current instance
* @return ARGON2_OK if successful, @context->state
*/
int fill_memory_blocks(argon2_instance_t *instance);
#endif

View File

@@ -0,0 +1,462 @@
/*
* Argon2 reference source code package - reference C implementations
*
* Copyright 2015
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
*
* You may use this work under the terms of a Creative Commons CC0 1.0
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
* these licenses can be found at:
*
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
*
* You should have received a copy of both of these licenses along with this
* software. If not, they may be obtained at the above URLs.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include "encoding.h"
#include "core.h"
/*
* Example code for a decoder and encoder of "hash strings", with Argon2
* parameters.
*
* This code comprises three sections:
*
* -- The first section contains generic Base64 encoding and decoding
* functions. It is conceptually applicable to any hash function
* implementation that uses Base64 to encode and decode parameters,
* salts and outputs. It could be made into a library, provided that
* the relevant functions are made public (non-static) and be given
* reasonable names to avoid collisions with other functions.
*
* -- The second section is specific to Argon2. It encodes and decodes
* the parameters, salts and outputs. It does not compute the hash
* itself.
*
* The code was originally written by Thomas Pornin <pornin@bolet.org>,
* to whom comments and remarks may be sent. It is released under what
* should amount to Public Domain or its closest equivalent; the
* following mantra is supposed to incarnate that fact with all the
* proper legal rituals:
*
* ---------------------------------------------------------------------
* This file is provided under the terms of Creative Commons CC0 1.0
* Public Domain Dedication. To the extent possible under law, the
* author (Thomas Pornin) has waived all copyright and related or
* neighboring rights to this file. This work is published from: Canada.
* ---------------------------------------------------------------------
*
* Copyright (c) 2015 Thomas Pornin
*/
/* ==================================================================== */
/*
* Common code; could be shared between different hash functions.
*
* Note: the Base64 functions below assume that uppercase letters (resp.
* lowercase letters) have consecutive numerical codes, that fit on 8
* bits. All modern systems use ASCII-compatible charsets, where these
* properties are true. If you are stuck with a dinosaur of a system
* that still defaults to EBCDIC then you already have much bigger
* interoperability issues to deal with.
*/
/*
* Some macros for constant-time comparisons. These work over values in
* the 0..255 range. Returned value is 0x00 on "false", 0xFF on "true".
*/
#define EQ(x, y) ((((0U - ((unsigned)(x) ^ (unsigned)(y))) >> 8) & 0xFF) ^ 0xFF)
#define GT(x, y) ((((unsigned)(y) - (unsigned)(x)) >> 8) & 0xFF)
#define GE(x, y) (GT(y, x) ^ 0xFF)
#define LT(x, y) GT(y, x)
#define LE(x, y) GE(y, x)
/*
* Convert value x (0..63) to corresponding Base64 character.
*/
static int b64_byte_to_char(unsigned x) {
return (LT(x, 26) & (x + 'A')) |
(GE(x, 26) & LT(x, 52) & (x + ('a' - 26))) |
(GE(x, 52) & LT(x, 62) & (x + ('0' - 52))) | (EQ(x, 62) & '+') |
(EQ(x, 63) & '/');
}
/*
* Convert character c to the corresponding 6-bit value. If character c
* is not a Base64 character, then 0xFF (255) is returned.
*/
static unsigned b64_char_to_byte(int c) {
unsigned x;
x = (GE(c, 'A') & LE(c, 'Z') & (c - 'A')) |
(GE(c, 'a') & LE(c, 'z') & (c - ('a' - 26))) |
(GE(c, '0') & LE(c, '9') & (c - ('0' - 52))) | (EQ(c, '+') & 62) |
(EQ(c, '/') & 63);
return x | (EQ(x, 0) & (EQ(c, 'A') ^ 0xFF));
}
/*
* Convert some bytes to Base64. 'dst_len' is the length (in characters)
* of the output buffer 'dst'; if that buffer is not large enough to
* receive the result (including the terminating 0), then (size_t)-1
* is returned. Otherwise, the zero-terminated Base64 string is written
* in the buffer, and the output length (counted WITHOUT the terminating
* zero) is returned.
*/
static size_t to_base64(char *dst, size_t dst_len, const void *src,
size_t src_len) {
size_t olen;
const unsigned char *buf;
unsigned acc, acc_len;
olen = (src_len / 3) << 2;
switch (src_len % 3) {
case 2:
olen++;
/* fall through */
case 1:
olen += 2;
break;
}
if (dst_len <= olen) {
return (size_t)-1;
}
acc = 0;
acc_len = 0;
buf = (const unsigned char *)src;
while (src_len-- > 0) {
acc = (acc << 8) + (*buf++);
acc_len += 8;
while (acc_len >= 6) {
acc_len -= 6;
*dst++ = (char)b64_byte_to_char((acc >> acc_len) & 0x3F);
}
}
if (acc_len > 0) {
*dst++ = (char)b64_byte_to_char((acc << (6 - acc_len)) & 0x3F);
}
*dst++ = 0;
return olen;
}
/*
* Decode Base64 chars into bytes. The '*dst_len' value must initially
* contain the length of the output buffer '*dst'; when the decoding
* ends, the actual number of decoded bytes is written back in
* '*dst_len'.
*
* Decoding stops when a non-Base64 character is encountered, or when
* the output buffer capacity is exceeded. If an error occurred (output
* buffer is too small, invalid last characters leading to unprocessed
* buffered bits), then NULL is returned; otherwise, the returned value
* points to the first non-Base64 character in the source stream, which
* may be the terminating zero.
*/
static const char *from_base64(void *dst, size_t *dst_len, const char *src) {
size_t len;
unsigned char *buf;
unsigned acc, acc_len;
buf = (unsigned char *)dst;
len = 0;
acc = 0;
acc_len = 0;
for (;;) {
unsigned d;
d = b64_char_to_byte(*src);
if (d == 0xFF) {
break;
}
src++;
acc = (acc << 6) + d;
acc_len += 6;
if (acc_len >= 8) {
acc_len -= 8;
if ((len++) >= *dst_len) {
return NULL;
}
*buf++ = (acc >> acc_len) & 0xFF;
}
}
/*
* If the input length is equal to 1 modulo 4 (which is
* invalid), then there will remain 6 unprocessed bits;
* otherwise, only 0, 2 or 4 bits are buffered. The buffered
* bits must also all be zero.
*/
if (acc_len > 4 || (acc & (((unsigned)1 << acc_len) - 1)) != 0) {
return NULL;
}
*dst_len = len;
return src;
}
/*
* Decode decimal integer from 'str'; the value is written in '*v'.
* Returned value is a pointer to the next non-decimal character in the
* string. If there is no digit at all, or the value encoding is not
* minimal (extra leading zeros), or the value does not fit in an
* 'unsigned long', then NULL is returned.
*/
static const char *decode_decimal(const char *str, unsigned long *v) {
const char *orig;
unsigned long acc;
acc = 0;
for (orig = str;; str++) {
int c;
c = *str;
if (c < '0' || c > '9') {
break;
}
c -= '0';
if (acc > (ULONG_MAX / 10)) {
return NULL;
}
acc *= 10;
if ((unsigned long)c > (ULONG_MAX - acc)) {
return NULL;
}
acc += (unsigned long)c;
}
if (str == orig || (*orig == '0' && str != (orig + 1))) {
return NULL;
}
*v = acc;
return str;
}
/* ==================================================================== */
/*
* Code specific to Argon2.
*
* The code below applies the following format:
*
* $argon2<T>[$v=<num>]$m=<num>,t=<num>,p=<num>$<bin>$<bin>
*
* where <T> is either 'd', 'id', or 'i', <num> is a decimal integer (positive,
* fits in an 'unsigned long'), and <bin> is Base64-encoded data (no '=' padding
* characters, no newline or whitespace).
*
* The last two binary chunks (encoded in Base64) are, in that order,
* the salt and the output. Both are required. The binary salt length and the
* output length must be in the allowed ranges defined in argon2.h.
*
* The ctx struct must contain buffers large enough to hold the salt and pwd
* when it is fed into decode_string.
*/
int decode_string(argon2_context *ctx, const char *str, argon2_type type) {
/* check for prefix */
#define CC(prefix) \
do { \
size_t cc_len = strlen(prefix); \
if (strncmp(str, prefix, cc_len) != 0) { \
return ARGON2_DECODING_FAIL; \
} \
str += cc_len; \
} while ((void)0, 0)
/* optional prefix checking with supplied code */
#define CC_opt(prefix, code) \
do { \
size_t cc_len = strlen(prefix); \
if (strncmp(str, prefix, cc_len) == 0) { \
str += cc_len; \
{ code; } \
} \
} while ((void)0, 0)
/* Decoding prefix into decimal */
#define DECIMAL(x) \
do { \
unsigned long dec_x; \
str = decode_decimal(str, &dec_x); \
if (str == NULL) { \
return ARGON2_DECODING_FAIL; \
} \
(x) = dec_x; \
} while ((void)0, 0)
/* Decoding prefix into uint32_t decimal */
#define DECIMAL_U32(x) \
do { \
unsigned long dec_x; \
str = decode_decimal(str, &dec_x); \
if (str == NULL || dec_x > UINT32_MAX) { \
return ARGON2_DECODING_FAIL; \
} \
(x) = (uint32_t)dec_x; \
} while ((void)0, 0)
/* Decoding base64 into a binary buffer */
#define BIN(buf, max_len, len) \
do { \
size_t bin_len = (max_len); \
str = from_base64(buf, &bin_len, str); \
if (str == NULL || bin_len > UINT32_MAX) { \
return ARGON2_DECODING_FAIL; \
} \
(len) = (uint32_t)bin_len; \
} while ((void)0, 0)
size_t maxsaltlen = ctx->saltlen;
size_t maxoutlen = ctx->outlen;
int validation_result;
const char* type_string;
/* We should start with the argon2_type we are using */
type_string = argon2_type2string(type, 0);
if (!type_string) {
return ARGON2_INCORRECT_TYPE;
}
CC("$");
CC(type_string);
/* Reading the version number if the default is suppressed */
ctx->version = ARGON2_VERSION_10;
CC_opt("$v=", DECIMAL_U32(ctx->version));
CC("$m=");
DECIMAL_U32(ctx->m_cost);
CC(",t=");
DECIMAL_U32(ctx->t_cost);
CC(",p=");
DECIMAL_U32(ctx->lanes);
ctx->threads = ctx->lanes;
CC("$");
BIN(ctx->salt, maxsaltlen, ctx->saltlen);
CC("$");
BIN(ctx->out, maxoutlen, ctx->outlen);
/* The rest of the fields get the default values */
ctx->secret = NULL;
ctx->secretlen = 0;
ctx->ad = NULL;
ctx->adlen = 0;
ctx->allocate_cbk = NULL;
ctx->free_cbk = NULL;
ctx->flags = ARGON2_DEFAULT_FLAGS;
/* On return, must have valid context */
validation_result = validate_inputs(ctx);
if (validation_result != ARGON2_OK) {
return validation_result;
}
/* Can't have any additional characters */
if (*str == 0) {
return ARGON2_OK;
} else {
return ARGON2_DECODING_FAIL;
}
#undef CC
#undef CC_opt
#undef DECIMAL
#undef BIN
}
int encode_string(char *dst, size_t dst_len, argon2_context *ctx,
argon2_type type) {
#define SS(str) \
do { \
size_t pp_len = strlen(str); \
if (pp_len >= dst_len) { \
return ARGON2_ENCODING_FAIL; \
} \
memcpy(dst, str, pp_len + 1); \
dst += pp_len; \
dst_len -= pp_len; \
} while ((void)0, 0)
#define SX(x) \
do { \
char tmp[30]; \
sprintf(tmp, "%lu", (unsigned long)(x)); \
SS(tmp); \
} while ((void)0, 0)
#define SB(buf, len) \
do { \
size_t sb_len = to_base64(dst, dst_len, buf, len); \
if (sb_len == (size_t)-1) { \
return ARGON2_ENCODING_FAIL; \
} \
dst += sb_len; \
dst_len -= sb_len; \
} while ((void)0, 0)
const char* type_string = argon2_type2string(type, 0);
int validation_result = validate_inputs(ctx);
if (!type_string) {
return ARGON2_ENCODING_FAIL;
}
if (validation_result != ARGON2_OK) {
return validation_result;
}
SS("$");
SS(type_string);
SS("$v=");
SX(ctx->version);
SS("$m=");
SX(ctx->m_cost);
SS(",t=");
SX(ctx->t_cost);
SS(",p=");
SX(ctx->lanes);
SS("$");
SB(ctx->salt, ctx->saltlen);
SS("$");
SB(ctx->out, ctx->outlen);
return ARGON2_OK;
#undef SS
#undef SX
#undef SB
}
size_t b64len(uint32_t len) {
size_t olen = ((size_t)len / 3) << 2;
switch (len % 3) {
case 2:
olen++;
/* fall through */
case 1:
olen += 2;
break;
}
return olen;
}
size_t numlen(uint32_t num) {
size_t len = 1;
while (num >= 10) {
++len;
num = num / 10;
}
return len;
}

View File

@@ -0,0 +1,57 @@
/*
* Argon2 reference source code package - reference C implementations
*
* Copyright 2015
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
*
* You may use this work under the terms of a Creative Commons CC0 1.0
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
* these licenses can be found at:
*
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
*
* You should have received a copy of both of these licenses along with this
* software. If not, they may be obtained at the above URLs.
*/
#ifndef ENCODING_H
#define ENCODING_H
#include "argon2.h"
#define ARGON2_MAX_DECODED_LANES UINT32_C(255)
#define ARGON2_MIN_DECODED_SALT_LEN UINT32_C(8)
#define ARGON2_MIN_DECODED_OUT_LEN UINT32_C(12)
/*
* encode an Argon2 hash string into the provided buffer. 'dst_len'
* contains the size, in characters, of the 'dst' buffer; if 'dst_len'
* is less than the number of required characters (including the
* terminating 0), then this function returns ARGON2_ENCODING_ERROR.
*
* on success, ARGON2_OK is returned.
*/
int encode_string(char *dst, size_t dst_len, argon2_context *ctx,
argon2_type type);
/*
* Decodes an Argon2 hash string into the provided structure 'ctx'.
* The only fields that must be set prior to this call are ctx.saltlen and
* ctx.outlen (which must be the maximal salt and out length values that are
* allowed), ctx.salt and ctx.out (which must be buffers of the specified
* length), and ctx.pwd and ctx.pwdlen which must hold a valid password.
*
* Invalid input string causes an error. On success, the ctx is valid and all
* fields have been initialized.
*
* Returned value is ARGON2_OK on success, other ARGON2_ codes on error.
*/
int decode_string(argon2_context *ctx, const char *str, argon2_type type);
/* Returns the length of the encoded byte stream with length len */
size_t b64len(uint32_t len);
/* Returns the length of the encoded number num */
size_t numlen(uint32_t num);
#endif

View File

@@ -0,0 +1,194 @@
/*
* Argon2 reference source code package - reference C implementations
*
* Copyright 2015
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
*
* You may use this work under the terms of a Creative Commons CC0 1.0
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
* these licenses can be found at:
*
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
*
* You should have received a copy of both of these licenses along with this
* software. If not, they may be obtained at the above URLs.
*/
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include "argon2.h"
#include "core.h"
#include "blake2/blamka-round-ref.h"
#include "blake2/blake2-impl.h"
#include "blake2/blake2.h"
/*
* Function fills a new memory block and optionally XORs the old block over the new one.
* @next_block must be initialized.
* @param prev_block Pointer to the previous block
* @param ref_block Pointer to the reference block
* @param next_block Pointer to the block to be constructed
* @param with_xor Whether to XOR into the new block (1) or just overwrite (0)
* @pre all block pointers must be valid
*/
static void fill_block(const block *prev_block, const block *ref_block,
block *next_block, int with_xor) {
block blockR, block_tmp;
unsigned i;
copy_block(&blockR, ref_block);
xor_block(&blockR, prev_block);
copy_block(&block_tmp, &blockR);
/* Now blockR = ref_block + prev_block and block_tmp = ref_block + prev_block */
if (with_xor) {
/* Saving the next block contents for XOR over: */
xor_block(&block_tmp, next_block);
/* Now blockR = ref_block + prev_block and
block_tmp = ref_block + prev_block + next_block */
}
/* Apply Blake2 on columns of 64-bit words: (0,1,...,15) , then
(16,17,..31)... finally (112,113,...127) */
for (i = 0; i < 8; ++i) {
BLAKE2_ROUND_NOMSG(
blockR.v[16 * i], blockR.v[16 * i + 1], blockR.v[16 * i + 2],
blockR.v[16 * i + 3], blockR.v[16 * i + 4], blockR.v[16 * i + 5],
blockR.v[16 * i + 6], blockR.v[16 * i + 7], blockR.v[16 * i + 8],
blockR.v[16 * i + 9], blockR.v[16 * i + 10], blockR.v[16 * i + 11],
blockR.v[16 * i + 12], blockR.v[16 * i + 13], blockR.v[16 * i + 14],
blockR.v[16 * i + 15]);
}
/* Apply Blake2 on rows of 64-bit words: (0,1,16,17,...112,113), then
(2,3,18,19,...,114,115).. finally (14,15,30,31,...,126,127) */
for (i = 0; i < 8; i++) {
BLAKE2_ROUND_NOMSG(
blockR.v[2 * i], blockR.v[2 * i + 1], blockR.v[2 * i + 16],
blockR.v[2 * i + 17], blockR.v[2 * i + 32], blockR.v[2 * i + 33],
blockR.v[2 * i + 48], blockR.v[2 * i + 49], blockR.v[2 * i + 64],
blockR.v[2 * i + 65], blockR.v[2 * i + 80], blockR.v[2 * i + 81],
blockR.v[2 * i + 96], blockR.v[2 * i + 97], blockR.v[2 * i + 112],
blockR.v[2 * i + 113]);
}
copy_block(next_block, &block_tmp);
xor_block(next_block, &blockR);
}
static void next_addresses(block *address_block, block *input_block,
const block *zero_block) {
input_block->v[6]++;
fill_block(zero_block, input_block, address_block, 0);
fill_block(zero_block, address_block, address_block, 0);
}
void fill_segment(const argon2_instance_t *instance,
argon2_position_t position) {
block *ref_block = NULL, *curr_block = NULL;
block address_block, input_block, zero_block;
uint64_t pseudo_rand, ref_index, ref_lane;
uint32_t prev_offset, curr_offset;
uint32_t starting_index;
uint32_t i;
int data_independent_addressing;
if (instance == NULL) {
return;
}
data_independent_addressing =
(instance->type == Argon2_i) ||
(instance->type == Argon2_id && (position.pass == 0) &&
(position.slice < ARGON2_SYNC_POINTS / 2));
if (data_independent_addressing) {
init_block_value(&zero_block, 0);
init_block_value(&input_block, 0);
input_block.v[0] = position.pass;
input_block.v[1] = position.lane;
input_block.v[2] = position.slice;
input_block.v[3] = instance->memory_blocks;
input_block.v[4] = instance->passes;
input_block.v[5] = instance->type;
}
starting_index = 0;
if ((0 == position.pass) && (0 == position.slice)) {
starting_index = 2; /* we have already generated the first two blocks */
/* Don't forget to generate the first block of addresses: */
if (data_independent_addressing) {
next_addresses(&address_block, &input_block, &zero_block);
}
}
/* Offset of the current block */
curr_offset = position.lane * instance->lane_length +
position.slice * instance->segment_length + starting_index;
if (0 == curr_offset % instance->lane_length) {
/* Last block in this lane */
prev_offset = curr_offset + instance->lane_length - 1;
} else {
/* Previous block */
prev_offset = curr_offset - 1;
}
for (i = starting_index; i < instance->segment_length;
++i, ++curr_offset, ++prev_offset) {
/*1.1 Rotating prev_offset if needed */
if (curr_offset % instance->lane_length == 1) {
prev_offset = curr_offset - 1;
}
/* 1.2 Computing the index of the reference block */
/* 1.2.1 Taking pseudo-random value from the previous block */
if (data_independent_addressing) {
if (i % ARGON2_ADDRESSES_IN_BLOCK == 0) {
next_addresses(&address_block, &input_block, &zero_block);
}
pseudo_rand = address_block.v[i % ARGON2_ADDRESSES_IN_BLOCK];
} else {
pseudo_rand = instance->memory[prev_offset].v[0];
}
/* 1.2.2 Computing the lane of the reference block */
ref_lane = ((pseudo_rand >> 32)) % instance->lanes;
if ((position.pass == 0) && (position.slice == 0)) {
/* Can not reference other lanes yet */
ref_lane = position.lane;
}
/* 1.2.3 Computing the number of possible reference block within the
* lane.
*/
position.index = i;
ref_index = index_alpha(instance, &position, pseudo_rand & 0xFFFFFFFF,
ref_lane == position.lane);
/* 2 Creating a new block */
ref_block =
instance->memory + instance->lane_length * ref_lane + ref_index;
curr_block = instance->memory + curr_offset;
if (ARGON2_VERSION_10 == instance->version) {
/* version 1.2.1 and earlier: overwrite, not XOR */
fill_block(instance->memory + prev_offset, ref_block, curr_block, 0);
} else {
if(0 == position.pass) {
fill_block(instance->memory + prev_offset, ref_block,
curr_block, 0);
} else {
fill_block(instance->memory + prev_offset, ref_block,
curr_block, 1);
}
}
}
}

View File

@@ -0,0 +1,57 @@
/*
* Argon2 reference source code package - reference C implementations
*
* Copyright 2015
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
*
* You may use this work under the terms of a Creative Commons CC0 1.0
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
* these licenses can be found at:
*
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
*
* You should have received a copy of both of these licenses along with this
* software. If not, they may be obtained at the above URLs.
*/
#if !defined(ARGON2_NO_THREADS)
#include "thread.h"
#if defined(_WIN32)
#include <windows.h>
#endif
int argon2_thread_create(argon2_thread_handle_t *handle,
argon2_thread_func_t func, void *args) {
if (NULL == handle || func == NULL) {
return -1;
}
#if defined(_WIN32)
*handle = _beginthreadex(NULL, 0, func, args, 0, NULL);
return *handle != 0 ? 0 : -1;
#else
return pthread_create(handle, NULL, func, args);
#endif
}
int argon2_thread_join(argon2_thread_handle_t handle) {
#if defined(_WIN32)
if (WaitForSingleObject((HANDLE)handle, INFINITE) == WAIT_OBJECT_0) {
return CloseHandle((HANDLE)handle) != 0 ? 0 : -1;
}
return -1;
#else
return pthread_join(handle, NULL);
#endif
}
void argon2_thread_exit(void) {
#if defined(_WIN32)
_endthreadex(0);
#else
pthread_exit(NULL);
#endif
}
#endif /* ARGON2_NO_THREADS */

View File

@@ -0,0 +1,67 @@
/*
* Argon2 reference source code package - reference C implementations
*
* Copyright 2015
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
*
* You may use this work under the terms of a Creative Commons CC0 1.0
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
* these licenses can be found at:
*
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
*
* You should have received a copy of both of these licenses along with this
* software. If not, they may be obtained at the above URLs.
*/
#ifndef ARGON2_THREAD_H
#define ARGON2_THREAD_H
#if !defined(ARGON2_NO_THREADS)
/*
Here we implement an abstraction layer for the simpĺe requirements
of the Argon2 code. We only require 3 primitives---thread creation,
joining, and termination---so full emulation of the pthreads API
is unwarranted. Currently we wrap pthreads and Win32 threads.
The API defines 2 types: the function pointer type,
argon2_thread_func_t,
and the type of the thread handle---argon2_thread_handle_t.
*/
#if defined(_WIN32)
#include <process.h>
typedef unsigned(__stdcall *argon2_thread_func_t)(void *);
typedef uintptr_t argon2_thread_handle_t;
#else
#include <pthread.h>
typedef void *(*argon2_thread_func_t)(void *);
typedef pthread_t argon2_thread_handle_t;
#endif
/* Creates a thread
* @param handle pointer to a thread handle, which is the output of this
* function. Must not be NULL.
* @param func A function pointer for the thread's entry point. Must not be
* NULL.
* @param args Pointer that is passed as an argument to @func. May be NULL.
* @return 0 if @handle and @func are valid pointers and a thread is successfuly
* created.
*/
int argon2_thread_create(argon2_thread_handle_t *handle,
argon2_thread_func_t func, void *args);
/* Waits for a thread to terminate
* @param handle Handle to a thread created with argon2_thread_create.
* @return 0 if @handle is a valid handle, and joining completed successfully.
*/
int argon2_thread_join(argon2_thread_handle_t handle);
/* Terminate the current thread. Must be run inside a thread created by
* argon2_thread_create.
*/
void argon2_thread_exit(void);
#endif /* ARGON2_NO_THREADS */
#endif

View File

@@ -0,0 +1,185 @@
/*
* Argon2 PBKDF2 library wrapper
*
* Copyright (C) 2016-2017, Red Hat, Inc. All rights reserved.
* Copyright (C) 2016-2017, Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this file; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <errno.h>
#include "crypto_backend.h"
#include "argon2/argon2.h"
#define CONST_CAST(x) (x)(uintptr_t)
int argon2(const char *type, const char *password, size_t password_length,
const char *salt, size_t salt_length,
char *key, size_t key_length,
uint32_t iterations, uint32_t memory, uint32_t parallel)
{
argon2_type atype;
argon2_context context = {
.flags = ARGON2_DEFAULT_FLAGS,
.version = ARGON2_VERSION_NUMBER,
.t_cost = (uint32_t)iterations,
.m_cost = (uint32_t)memory,
.lanes = (uint32_t)parallel,
.threads = (uint32_t)parallel,
.out = (uint8_t *)key,
.outlen = (uint32_t)key_length,
.pwd = CONST_CAST(uint8_t *)password,
.pwdlen = (uint32_t)password_length,
.salt = CONST_CAST(uint8_t *)salt,
.saltlen = (uint32_t)salt_length,
};
int r;
if (!strcmp(type, "argon2i"))
atype = Argon2_i;
else if(!strcmp(type, "argon2id"))
atype = Argon2_id;
else
return -EINVAL;
switch (argon2_ctx(&context, atype)) {
case ARGON2_OK:
r = 0;
break;
case ARGON2_MEMORY_ALLOCATION_ERROR:
case ARGON2_FREE_MEMORY_CBK_NULL:
case ARGON2_ALLOCATE_MEMORY_CBK_NULL:
r = -ENOMEM;
break;
default:
r = -EINVAL;
}
return r;
}
#if 0
#include <stdio.h>
struct test_vector {
argon2_type type;
unsigned int memory;
unsigned int iterations;
unsigned int parallelism;
const char *password;
unsigned int password_length;
const char *salt;
unsigned int salt_length;
const char *key;
unsigned int key_length;
const char *ad;
unsigned int ad_length;
const char *output;
unsigned int output_length;
};
struct test_vector test_vectors[] = {
/* Argon2 RFC */
{
Argon2_i, 32, 3, 4,
"\x01\x01\x01\x01\x01\x01\x01\x01"
"\x01\x01\x01\x01\x01\x01\x01\x01"
"\x01\x01\x01\x01\x01\x01\x01\x01"
"\x01\x01\x01\x01\x01\x01\x01\x01", 32,
"\x02\x02\x02\x02\x02\x02\x02\x02"
"\x02\x02\x02\x02\x02\x02\x02\x02", 16,
"\x03\x03\x03\x03\x03\x03\x03\x03", 8,
"\x04\x04\x04\x04\x04\x04\x04\x04"
"\x04\x04\x04\x04", 12,
"\xc8\x14\xd9\xd1\xdc\x7f\x37\xaa"
"\x13\xf0\xd7\x7f\x24\x94\xbd\xa1"
"\xc8\xde\x6b\x01\x6d\xd3\x88\xd2"
"\x99\x52\xa4\xc4\x67\x2b\x6c\xe8", 32
},
{
Argon2_id, 32, 3, 4,
"\x01\x01\x01\x01\x01\x01\x01\x01"
"\x01\x01\x01\x01\x01\x01\x01\x01"
"\x01\x01\x01\x01\x01\x01\x01\x01"
"\x01\x01\x01\x01\x01\x01\x01\x01", 32,
"\x02\x02\x02\x02\x02\x02\x02\x02"
"\x02\x02\x02\x02\x02\x02\x02\x02", 16,
"\x03\x03\x03\x03\x03\x03\x03\x03", 8,
"\x04\x04\x04\x04\x04\x04\x04\x04"
"\x04\x04\x04\x04", 12,
"\x0d\x64\x0d\xf5\x8d\x78\x76\x6c"
"\x08\xc0\x37\xa3\x4a\x8b\x53\xc9"
"\xd0\x1e\xf0\x45\x2d\x75\xb6\x5e"
"\xb5\x25\x20\xe9\x6b\x01\xe6\x59", 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 argon2_test_vectors(void)
{
char result[64];
int i, r;
struct test_vector *vec;
argon2_context context;
printf("Argon2 running test vectors\n");
for (i = 0; i < (sizeof(test_vectors) / sizeof(*test_vectors)); i++) {
vec = &test_vectors[i];
memset(result, 0, sizeof(result));
memset(&context, 0, sizeof(context));
context.flags = ARGON2_DEFAULT_FLAGS;
context.version = ARGON2_VERSION_NUMBER;
context.out = (uint8_t *)result;
context.outlen = (uint32_t)vec->output_length;
context.pwd = (uint8_t *)vec->password;
context.pwdlen = (uint32_t)vec->password_length;
context.salt = (uint8_t *)vec->salt;
context.saltlen = (uint32_t)vec->salt_length;
context.secret = (uint8_t *)vec->key;
context.secretlen = (uint32_t)vec->key_length;;
context.ad = (uint8_t *)vec->ad;
context.adlen = (uint32_t)vec->ad_length;
context.t_cost = vec->iterations;
context.m_cost = vec->memory;
context.lanes = vec->parallelism;
context.threads = vec->parallelism;
r = argon2_ctx(&context, vec->type);
if (r != ARGON2_OK) {
printf("Argon2 failed %i, vector %d\n", r, i);
return -EINVAL;
}
if (memcmp(result, vec->output, vec->output_length) != 0) {
printf("vector %u\n", i);
printhex(" got", result, vec->output_length);
printhex("want", vec->output, vec->output_length);
return -EINVAL;
}
}
return 0;
}
#endif

116
lib/crypto_backend/crc32.c Normal file
View File

@@ -0,0 +1,116 @@
/*
* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
* code or tables extracted from it, as desired without restriction.
*
* First, the polynomial itself and its table of feedback terms. The
* polynomial is
* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0
*
* Note that we take it "backwards" and put the highest-order term in
* the lowest-order bit. The X^32 term is "implied"; the LSB is the
* X^31 term, etc. The X^0 term (usually shown as "+1") results in
* the MSB being 1.
*
* Note that the usual hardware shift register implementation, which
* is what we're using (we're merely optimizing it by doing eight-bit
* chunks at a time) shifts bits into the lowest-order term. In our
* implementation, that means shifting towards the right. Why do we
* do it this way? Because the calculated CRC must be transmitted in
* order from highest-order term to lowest-order term. UARTs transmit
* characters in order from LSB to MSB. By storing the CRC this way,
* we hand it to the UART in the order low-byte to high-byte; the UART
* sends each low-bit to hight-bit; and the result is transmission bit
* by bit from highest- to lowest-order term without requiring any bit
* shuffling on our part. Reception works similarly.
*
* The feedback terms table consists of 256, 32-bit entries. Notes
*
* The table can be generated at runtime if desired; code to do so
* is shown later. It might not be obvious, but the feedback
* terms simply represent the results of eight shift/xor opera-
* tions for all combinations of data and CRC register values.
*
* The values must be right-shifted by eight bits by the "updcrc"
* logic; the shift must be unsigned (bring in zeroes). On some
* hardware you could probably optimize the shift in assembler by
* using byte-swap instructions.
* polynomial $edb88320
*
*/
#include <stdio.h>
#include "crypto_backend.h"
static const uint32_t crc32_tab[] = {
0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
0x2d02ef8dL
};
/*
* This a generic crc32() function, it takes seed as an argument,
* and does __not__ xor at the end. Then individual users can do
* whatever they need.
*/
uint32_t crypt_crc32(uint32_t seed, const unsigned char *buf, size_t len)
{
uint32_t crc = seed;
const unsigned char *p = buf;
while(len-- > 0)
crc = crc32_tab[(crc ^ *p++) & 0xff] ^ (crc >> 8);
return crc;
}

View File

@@ -1,32 +1,37 @@
/*
* crypto backend implementation
*
* Copyright (C) 2010-2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2017, Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2017, Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
* 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 program is distributed in the hope that it will be useful,
* 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 General Public License for more details.
* 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 General Public License
* along with this program; if not, write to the Free Software
* You should have received a copy of the GNU Lesser General Public
* License along with this file; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef _CRYPTO_BACKEND_H
#define _CRYPTO_BACKEND_H
#include <stdint.h>
#include "config.h"
#include <string.h>
struct crypt_device;
struct crypt_hash;
struct crypt_hmac;
struct crypt_cipher;
struct crypt_storage;
int crypt_backend_init(struct crypt_device *ctx);
void crypt_backend_destroy(void);
#define CRYPT_BACKEND_KERNEL (1 << 0) /* Crypto uses kernel part, for benchmark */
@@ -52,4 +57,68 @@ int crypt_hmac_destroy(struct crypt_hmac *ctx);
enum { CRYPT_RND_NORMAL = 0, CRYPT_RND_KEY = 1, CRYPT_RND_SALT = 2 };
int crypt_backend_rng(char *buffer, size_t length, int quality, int fips);
/* PBKDF*/
int crypt_pbkdf(const char *kdf, const char *hash,
const char *password, size_t password_length,
const char *salt, size_t salt_length,
char *key, size_t key_length,
uint32_t iterations, uint32_t memory, uint32_t parallel);
int crypt_pbkdf_perf(const char *kdf, const char *hash,
const char *password, size_t password_size,
const char *salt, size_t salt_size,
size_t volume_key_size, uint32_t time_ms,
uint32_t max_memory_kb, uint32_t parallel_threads,
uint32_t *iterations_out, uint32_t *memory_out,
int (*progress)(uint32_t time_ms, void *usrptr), void *usrptr);
#if USE_INTERNAL_PBKDF2
/* internal PBKDF2 implementation */
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 hash_block_size);
#endif
#if USE_INTERNAL_ARGON2
/* internal Argon2 implementation */
int argon2(const char *type, const char *password, size_t password_length,
const char *salt, size_t salt_length,
char *key, size_t key_length,
uint32_t iterations, uint32_t memory, uint32_t parallel);
#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);
int crypt_cipher_encrypt(struct crypt_cipher *ctx,
const char *in, char *out, size_t length,
const char *iv, size_t iv_length);
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

@@ -0,0 +1,269 @@
/*
* Linux kernel userspace API crypto backend implementation (skcipher)
*
* Copyright (C) 2012-2017, Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2017, 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 <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include "crypto_backend.h"
#ifdef ENABLE_AF_ALG
#include <linux/if_alg.h>
#ifndef AF_ALG
#define AF_ALG 38
#endif
#ifndef SOL_ALG
#define SOL_ALG 279
#endif
struct crypt_cipher {
int tfmfd;
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;
}
/*
* ciphers
*
* ENOENT - algorithm not available
* ENOTSUP - AF_ALG family not available
* (but cannot check specificaly for skcipher API)
*/
int crypt_cipher_init(struct crypt_cipher **ctx, const char *name,
const char *mode, const void *buffer, size_t length)
{
struct crypt_cipher *h;
struct sockaddr_alg sa = {
.salg_family = AF_ALG,
.salg_type = "skcipher",
};
h = malloc(sizeof(*h));
if (!h)
return -ENOMEM;
snprintf((char *)sa.salg_name, sizeof(sa.salg_name),
"%s(%s)", mode, name);
h->opfd = -1;
h->tfmfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
if (h->tfmfd < 0) {
crypt_cipher_destroy(h);
return -ENOTSUP;
}
if (bind(h->tfmfd, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
crypt_cipher_destroy(h);
return -ENOENT;
}
if (!strcmp(name, "cipher_null"))
length = 0;
if (setsockopt(h->tfmfd, SOL_ALG, ALG_SET_KEY, buffer, length) < 0) {
crypt_cipher_destroy(h);
return -EINVAL;
}
h->opfd = accept(h->tfmfd, NULL, 0);
if (h->opfd < 0) {
crypt_cipher_destroy(h);
return -EINVAL;
}
*ctx = h;
return 0;
}
/* The in/out should be aligned to page boundary */
static int crypt_cipher_crypt(struct crypt_cipher *ctx,
const char *in, char *out, size_t length,
const char *iv, size_t iv_length,
uint32_t direction)
{
int r = 0;
ssize_t len;
struct af_alg_iv *alg_iv;
struct cmsghdr *header;
uint32_t *type;
struct iovec iov = {
.iov_base = (void*)(uintptr_t)in,
.iov_len = length,
};
int iv_msg_size = iv ? CMSG_SPACE(sizeof(*alg_iv) + iv_length) : 0;
char buffer[CMSG_SPACE(sizeof(*type)) + iv_msg_size];
struct msghdr msg = {
.msg_control = buffer,
.msg_controllen = sizeof(buffer),
.msg_iov = &iov,
.msg_iovlen = 1,
};
if (!in || !out || !length)
return -EINVAL;
if ((!iv && iv_length) || (iv && !iv_length))
return -EINVAL;
memset(buffer, 0, sizeof(buffer));
/* 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));
type = (void*)CMSG_DATA(header);
*type = direction;
/* Set IV */
if (iv) {
header = CMSG_NXTHDR(&msg, header);
header->cmsg_level = SOL_ALG;
header->cmsg_type = ALG_SET_IV;
header->cmsg_len = iv_msg_size;
alg_iv = (void*)CMSG_DATA(header);
alg_iv->ivlen = iv_length;
memcpy(alg_iv->iv, iv, iv_length);
}
len = sendmsg(ctx->opfd, &msg, 0);
if (len != (ssize_t)length) {
r = -EIO;
goto bad;
}
len = read(ctx->opfd, out, length);
if (len != (ssize_t)length)
r = -EIO;
bad:
crypt_backend_memzero(buffer, sizeof(buffer));
return r;
}
int crypt_cipher_encrypt(struct crypt_cipher *ctx,
const char *in, char *out, size_t length,
const char *iv, size_t iv_length)
{
return crypt_cipher_crypt(ctx, in, out, length,
iv, iv_length, ALG_OP_ENCRYPT);
}
int crypt_cipher_decrypt(struct crypt_cipher *ctx,
const char *in, char *out, size_t length,
const char *iv, size_t iv_length)
{
return crypt_cipher_crypt(ctx, in, out, length,
iv, iv_length, ALG_OP_DECRYPT);
}
int crypt_cipher_destroy(struct crypt_cipher *ctx)
{
if (ctx->tfmfd >= 0)
close(ctx->tfmfd);
if (ctx->opfd >= 0)
close(ctx->opfd);
memset(ctx, 0, sizeof(*ctx));
free(ctx);
return 0;
}
#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)
{
return -ENOTSUP;
}
int crypt_cipher_destroy(struct crypt_cipher *ctx)
{
return 0;
}
int crypt_cipher_encrypt(struct crypt_cipher *ctx,
const char *in, char *out, size_t length,
const char *iv, size_t iv_length)
{
return -EINVAL;
}
int crypt_cipher_decrypt(struct crypt_cipher *ctx,
const char *in, char *out, size_t length,
const char *iv, size_t iv_length)
{
return -EINVAL;
}
#endif

View File

@@ -1,19 +1,21 @@
/*
* GCRYPT crypto backend implementation
*
* Copyright (C) 2010-2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2017, Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2017, Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
* 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 program is distributed in the hope that it will be useful,
* 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 General Public License for more details.
* 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 General Public License
* along with this program; if not, write to the Free Software
* 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.
*/
@@ -26,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 {
@@ -40,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)
@@ -68,13 +109,26 @@ 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;
}
void crypt_backend_destroy(void)
{
if (crypto_backend_initialised)
gcry_control(GCRYCTL_TERM_SECMEM);
crypto_backend_initialised = 0;
}
const char *crypt_backend_version(void)
{
return crypto_backend_initialised ? version : "";
@@ -85,6 +139,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)
{
@@ -92,7 +163,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;
@@ -102,6 +173,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);
@@ -109,13 +181,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;
}
@@ -171,6 +243,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);
@@ -178,13 +251,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;
}
@@ -251,3 +324,49 @@ int crypt_backend_rng(char *buffer, size_t length, int quality, int fips)
}
return 0;
}
static int pbkdf2(const char *hash,
const char *password, size_t password_length,
const char *salt, size_t salt_length,
char *key, size_t key_length,
uint32_t iterations)
{
const char *hash_name = crypt_hash_compat_name(hash, NULL);
#if USE_INTERNAL_PBKDF2
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_name);
if (!hash_id)
return -EINVAL;
if (gcry_kdf_derive(password, password_length, GCRY_KDF_PBKDF2, hash_id,
salt, salt_length, iterations, key_length, key))
return -EINVAL;
return 0;
#endif /* USE_INTERNAL_PBKDF2 */
}
/* PBKDF */
int crypt_pbkdf(const char *kdf, const char *hash,
const char *password, size_t password_length,
const char *salt, size_t salt_length,
char *key, size_t key_length,
uint32_t iterations, uint32_t memory, uint32_t parallel)
{
if (!kdf)
return -EINVAL;
if (!strcmp(kdf, "pbkdf2"))
return pbkdf2(hash, password, password_length, salt, salt_length,
key, key_length, iterations);
#if USE_INTERNAL_ARGON2
else if (!strncmp(kdf, "argon2", 6))
return argon2(kdf, password, password_length, salt, salt_length,
key, key_length, iterations, memory, parallel);
#endif
return -EINVAL;
}

View File

@@ -1,19 +1,21 @@
/*
* Linux kernel userspace API crypto backend implementation
*
* Copyright (C) 2010-2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2017, Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2017, Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
* 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 program is distributed in the hope that it will be useful,
* 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 General Public License for more details.
* 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 General Public License
* along with this program; if not, write to the Free Software
* 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.
*/
@@ -36,21 +38,22 @@
#endif
static int crypto_backend_initialised = 0;
static char version[64];
static char version[256];
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, 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 {
@@ -65,30 +68,33 @@ struct crypt_hmac {
int hash_len;
};
static int _socket_init(struct sockaddr_alg *sa, int *tfmfd, int *opfd)
static int crypt_kernel_socket_init(struct sockaddr_alg *sa, int *tfmfd, int *opfd,
const void *key, size_t key_length)
{
*tfmfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
if (*tfmfd == -1)
goto bad;
if (*tfmfd < 0)
return -ENOTSUP;
if (bind(*tfmfd, (struct sockaddr *)sa, sizeof(*sa)) == -1)
goto bad;
*opfd = accept(*tfmfd, NULL, 0);
if (*opfd == -1)
goto bad;
return 0;
bad:
if (*tfmfd != -1) {
if (bind(*tfmfd, (struct sockaddr *)sa, sizeof(*sa)) < 0) {
close(*tfmfd);
*tfmfd = -1;
return -ENOENT;
}
if (*opfd != -1) {
close(*opfd);
*opfd = -1;
if (key && setsockopt(*tfmfd, SOL_ALG, ALG_SET_KEY, key, key_length) < 0) {
close(*tfmfd);
*tfmfd = -1;
return -EINVAL;
}
return -EINVAL;
*opfd = accept(*tfmfd, NULL, 0);
if (*opfd < 0) {
close(*tfmfd);
*tfmfd = -1;
return -EINVAL;
}
return 0;
}
int crypt_backend_init(struct crypt_device *ctx)
@@ -97,7 +103,7 @@ int crypt_backend_init(struct crypt_device *ctx)
struct sockaddr_alg sa = {
.salg_family = AF_ALG,
.salg_type = "hash",
.salg_name = "sha1",
.salg_name = "sha256",
};
int tfmfd = -1, opfd = -1;
@@ -107,7 +113,7 @@ int crypt_backend_init(struct crypt_device *ctx)
if (uname(&uts) == -1 || strcmp(uts.sysname, "Linux"))
return -EINVAL;
if (_socket_init(&sa, &tfmfd, &opfd) < 0)
if (crypt_kernel_socket_init(&sa, &tfmfd, &opfd, NULL, 0) < 0)
return -EINVAL;
close(tfmfd);
@@ -120,6 +126,11 @@ int crypt_backend_init(struct crypt_device *ctx)
return 0;
}
void crypt_backend_destroy(void)
{
crypto_backend_initialised = 0;
}
uint32_t crypt_backend_flags(void)
{
return CRYPT_BACKEND_KERNEL;
@@ -172,7 +183,7 @@ int crypt_hash_init(struct crypt_hash **ctx, const char *name)
strncpy((char *)sa.salg_name, ha->kernel_name, sizeof(sa.salg_name));
if (_socket_init(&sa, &h->tfmfd, &h->opfd) < 0) {
if (crypt_kernel_socket_init(&sa, &h->tfmfd, &h->opfd, NULL, 0) < 0) {
free(h);
return -EINVAL;
}
@@ -208,9 +219,9 @@ int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length)
int crypt_hash_destroy(struct crypt_hash *ctx)
{
if (ctx->tfmfd != -1)
if (ctx->tfmfd >= 0)
close(ctx->tfmfd);
if (ctx->opfd != -1)
if (ctx->opfd >= 0)
close(ctx->opfd);
memset(ctx, 0, sizeof(*ctx));
free(ctx);
@@ -247,16 +258,11 @@ int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
snprintf((char *)sa.salg_name, sizeof(sa.salg_name),
"hmac(%s)", ha->kernel_name);
if (_socket_init(&sa, &h->tfmfd, &h->opfd) < 0) {
if (crypt_kernel_socket_init(&sa, &h->tfmfd, &h->opfd, buffer, length) < 0) {
free(h);
return -EINVAL;
}
if (setsockopt(h->tfmfd, SOL_ALG, ALG_SET_KEY, buffer, length) == -1) {
crypt_hmac_destroy(h);
return -EINVAL;
}
*ctx = h;
return 0;
}
@@ -288,9 +294,9 @@ int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length)
int crypt_hmac_destroy(struct crypt_hmac *ctx)
{
if (ctx->tfmfd != -1)
if (ctx->tfmfd >= 0)
close(ctx->tfmfd);
if (ctx->opfd != -1)
if (ctx->opfd >= 0)
close(ctx->opfd);
memset(ctx, 0, sizeof(*ctx));
free(ctx);
@@ -302,3 +308,32 @@ int crypt_backend_rng(char *buffer, size_t length, int quality, int fips)
{
return -EINVAL;
}
/* PBKDF */
int crypt_pbkdf(const char *kdf, const char *hash,
const char *password, size_t password_length,
const char *salt, size_t salt_length,
char *key, size_t key_length,
uint32_t iterations, uint32_t memory, uint32_t parallel)
{
struct hash_alg *ha;
if (!kdf)
return -EINVAL;
if (!strcmp(kdf, "pbkdf2")) {
ha = _get_alg(hash);
if (!ha)
return -EINVAL;
return pkcs5_pbkdf2(hash, password, password_length, salt, salt_length,
iterations, key_length, key, ha->block_length);
#if USE_INTERNAL_ARGON2
} else if (!strncmp(kdf, "argon2", 6)) {
return argon2(kdf, password, password_length, salt, salt_length,
key, key_length, iterations, memory, parallel);
#endif
}
return -EINVAL;
}

View File

@@ -1,19 +1,21 @@
/*
* Nettle crypto backend implementation
*
* Copyright (C) 2011-2012 Red Hat, Inc. All rights reserved.
* Copyright (C) 2011-2017 Red Hat, Inc. All rights reserved.
* Copyright (C) 2011-2017, Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
* 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 program is distributed in the hope that it will be useful,
* 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 General Public License for more details.
* 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 General Public License
* along with this program; if not, write to the Free Software
* 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.
*/
@@ -22,14 +24,15 @@
#include <errno.h>
#include <nettle/sha.h>
#include <nettle/hmac.h>
#include <nettle/pbkdf2.h>
#include "crypto_backend.h"
static char *version = "Nettle";
typedef void (*init_func) (void *);
typedef void (*update_func) (void *, unsigned, const uint8_t *);
typedef void (*digest_func) (void *, unsigned, uint8_t *);
typedef void (*set_key_func) (void *, unsigned, const uint8_t *);
typedef void (*update_func) (void *, size_t, const uint8_t *);
typedef void (*digest_func) (void *, size_t, uint8_t *);
typedef void (*set_key_func) (void *, size_t, const uint8_t *);
struct hash_alg {
const char *name;
@@ -140,6 +143,11 @@ int crypt_backend_init(struct crypt_device *ctx)
return 0;
}
void crypt_backend_destroy(void)
{
return;
}
const char *crypt_backend_version(void)
{
return version;
@@ -263,8 +271,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;
}
@@ -274,3 +282,37 @@ int crypt_backend_rng(char *buffer, size_t length, int quality, int fips)
{
return -EINVAL;
}
/* PBKDF */
int crypt_pbkdf(const char *kdf, const char *hash,
const char *password, size_t password_length,
const char *salt, size_t salt_length,
char *key, size_t key_length,
uint32_t iterations, uint32_t memory, uint32_t parallel)
{
struct crypt_hmac *h;
int r;
if (!kdf)
return -EINVAL;
if (!strcmp(kdf, "pbkdf2")) {
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;
#if USE_INTERNAL_ARGON2
} else if (!strncmp(kdf, "argon2", 6)) {
return argon2(kdf, password, password_length, salt, salt_length,
key, key_length, iterations, memory, parallel);
#endif
}
return -EINVAL;
}

View File

@@ -1,19 +1,21 @@
/*
* NSS crypto backend implementation
*
* Copyright (C) 2010-2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2017, Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2017, Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
* 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 program is distributed in the hope that it will be useful,
* 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 General Public License for more details.
* 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 General Public License
* along with this program; if not, write to the Free Software
* 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.
*/
@@ -33,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 }
};
@@ -85,6 +88,11 @@ int crypt_backend_init(struct crypt_device *ctx)
return 0;
}
void crypt_backend_destroy(void)
{
crypto_backend_initialised = 0;
}
uint32_t crypt_backend_flags(void)
{
return 0;
@@ -161,7 +169,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;
@@ -263,7 +271,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;
@@ -298,3 +306,32 @@ int crypt_backend_rng(char *buffer, size_t length, int quality, int fips)
return 0;
}
/* PBKDF */
int crypt_pbkdf(const char *kdf, const char *hash,
const char *password, size_t password_length,
const char *salt, size_t salt_length,
char *key, size_t key_length,
uint32_t iterations, uint32_t memory, uint32_t parallel)
{
struct hash_alg *ha;
if (!kdf)
return -EINVAL;
if (!strcmp(kdf, "pbkdf2")) {
ha = _get_alg(hash);
if (!ha)
return -EINVAL;
return pkcs5_pbkdf2(hash, password, password_length, salt, salt_length,
iterations, key_length, key, ha->block_length);
#if USE_INTERNAL_ARGON2
} else if (!strncmp(kdf, "argon2", 6)) {
return argon2(kdf, password, password_length, salt, salt_length,
key, key_length, iterations, memory, parallel);
#endif
}
return -EINVAL;
}

View File

@@ -1,19 +1,21 @@
/*
* OPENSSL crypto backend implementation
*
* Copyright (C) 2010-2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2017, Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2017, Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
* 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 program is distributed in the hope that it will be useful,
* 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 General Public License for more details.
* 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 General Public License
* along with this program; if not, write to the Free Software
* 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.
*
* In addition, as a special exception, the copyright holders give
@@ -22,7 +24,7 @@
* individual source file, and distribute linked combinations
* including the two.
*
* You must obey the GNU General Public License in all respects
* You must obey the GNU Lesser General Public License in all respects
* for all of the code used other than OpenSSL.
*/
@@ -36,28 +38,89 @@
static int crypto_backend_initialised = 0;
struct crypt_hash {
EVP_MD_CTX md;
EVP_MD_CTX *md;
const EVP_MD *hash_id;
int hash_len;
};
struct crypt_hmac {
HMAC_CTX md;
HMAC_CTX *md;
const EVP_MD *hash_id;
int hash_len;
};
/*
* Compatible wrappers for OpenSSL < 1.1.0
*/
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
static void openssl_backend_init(void)
{
OpenSSL_add_all_algorithms();
}
static const char *openssl_backend_version(void)
{
return SSLeay_version(SSLEAY_VERSION);
}
static EVP_MD_CTX *EVP_MD_CTX_new(void)
{
EVP_MD_CTX *md = malloc(sizeof(*md));
if (md)
EVP_MD_CTX_init(md);
return md;
}
static void EVP_MD_CTX_free(EVP_MD_CTX *md)
{
EVP_MD_CTX_cleanup(md);
free(md);
}
static HMAC_CTX *HMAC_CTX_new(void)
{
HMAC_CTX *md = malloc(sizeof(*md));
if (md)
HMAC_CTX_init(md);
return md;
}
static void HMAC_CTX_free(HMAC_CTX *md)
{
HMAC_CTX_cleanup(md);
free(md);
}
#else
static void openssl_backend_init(void)
{
}
static const char *openssl_backend_version(void)
{
return OpenSSL_version(OPENSSL_VERSION);
}
#endif
int crypt_backend_init(struct crypt_device *ctx)
{
if (crypto_backend_initialised)
return 0;
OpenSSL_add_all_digests();
openssl_backend_init();
crypto_backend_initialised = 1;
return 0;
}
void crypt_backend_destroy(void)
{
crypto_backend_initialised = 0;
}
uint32_t crypt_backend_flags(void)
{
return 0;
@@ -65,7 +128,7 @@ uint32_t crypt_backend_flags(void)
const char *crypt_backend_version(void)
{
return SSLeay_version(SSLEAY_VERSION);
return openssl_backend_version();
}
/* HASH */
@@ -87,13 +150,21 @@ int crypt_hash_init(struct crypt_hash **ctx, const char *name)
if (!h)
return -ENOMEM;
h->md = EVP_MD_CTX_new();
if (!h->md) {
free(h);
return -ENOMEM;
}
h->hash_id = EVP_get_digestbyname(name);
if (!h->hash_id) {
EVP_MD_CTX_free(h->md);
free(h);
return -EINVAL;
}
if (EVP_DigestInit(&h->md, h->hash_id) != 1) {
if (EVP_DigestInit_ex(h->md, h->hash_id, NULL) != 1) {
EVP_MD_CTX_free(h->md);
free(h);
return -EINVAL;
}
@@ -105,7 +176,7 @@ int crypt_hash_init(struct crypt_hash **ctx, const char *name)
static int crypt_hash_restart(struct crypt_hash *ctx)
{
if (EVP_DigestInit(&ctx->md, ctx->hash_id) != 1)
if (EVP_DigestInit_ex(ctx->md, ctx->hash_id, NULL) != 1)
return -EINVAL;
return 0;
@@ -113,7 +184,7 @@ static int crypt_hash_restart(struct crypt_hash *ctx)
int crypt_hash_write(struct crypt_hash *ctx, const char *buffer, size_t length)
{
if (EVP_DigestUpdate(&ctx->md, buffer, length) != 1)
if (EVP_DigestUpdate(ctx->md, buffer, length) != 1)
return -EINVAL;
return 0;
@@ -127,11 +198,11 @@ int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length)
if (length > (size_t)ctx->hash_len)
return -EINVAL;
if (EVP_DigestFinal_ex(&ctx->md, tmp, &tmp_len) != 1)
if (EVP_DigestFinal_ex(ctx->md, tmp, &tmp_len) != 1)
return -EINVAL;
memcpy(buffer, tmp, length);
memset(tmp, 0, sizeof(tmp));
crypt_backend_memzero(tmp, sizeof(tmp));
if (tmp_len < length)
return -EINVAL;
@@ -144,7 +215,7 @@ int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length)
int crypt_hash_destroy(struct crypt_hash *ctx)
{
EVP_MD_CTX_cleanup(&ctx->md);
EVP_MD_CTX_free(ctx->md);
memset(ctx, 0, sizeof(*ctx));
free(ctx);
return 0;
@@ -165,14 +236,20 @@ int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
if (!h)
return -ENOMEM;
h->md = HMAC_CTX_new();
if (!h->md) {
free(h);
return -ENOMEM;
}
h->hash_id = EVP_get_digestbyname(name);
if (!h->hash_id) {
HMAC_CTX_free(h->md);
free(h);
return -EINVAL;
}
HMAC_CTX_init(&h->md);
HMAC_Init_ex(&h->md, buffer, length, h->hash_id, NULL);
HMAC_Init_ex(h->md, buffer, length, h->hash_id, NULL);
h->hash_len = EVP_MD_size(h->hash_id);
*ctx = h;
@@ -181,12 +258,12 @@ int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
static void crypt_hmac_restart(struct crypt_hmac *ctx)
{
HMAC_Init_ex(&ctx->md, NULL, 0, ctx->hash_id, NULL);
HMAC_Init_ex(ctx->md, NULL, 0, ctx->hash_id, NULL);
}
int crypt_hmac_write(struct crypt_hmac *ctx, const char *buffer, size_t length)
{
HMAC_Update(&ctx->md, (const unsigned char *)buffer, length);
HMAC_Update(ctx->md, (const unsigned char *)buffer, length);
return 0;
}
@@ -198,10 +275,10 @@ int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length)
if (length > (size_t)ctx->hash_len)
return -EINVAL;
HMAC_Final(&ctx->md, tmp, &tmp_len);
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;
@@ -213,7 +290,7 @@ int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length)
int crypt_hmac_destroy(struct crypt_hmac *ctx)
{
HMAC_CTX_cleanup(&ctx->md);
HMAC_CTX_free(ctx->md);
memset(ctx, 0, sizeof(*ctx));
free(ctx);
return 0;
@@ -230,3 +307,36 @@ int crypt_backend_rng(char *buffer, size_t length, int quality, int fips)
return 0;
}
/* PBKDF */
int crypt_pbkdf(const char *kdf, const char *hash,
const char *password, size_t password_length,
const char *salt, size_t salt_length,
char *key, size_t key_length,
uint32_t iterations, uint32_t memory, uint32_t parallel)
{
const EVP_MD *hash_id;
if (!kdf)
return -EINVAL;
if (!strcmp(kdf, "pbkdf2")) {
hash_id = EVP_get_digestbyname(hash);
if (!hash_id)
return -EINVAL;
if (!PKCS5_PBKDF2_HMAC(password, (int)password_length,
(unsigned char *)salt, (int)salt_length,
(int)iterations, hash_id, (int)key_length, (unsigned char *)key))
return -EINVAL;
return 0;
#if USE_INTERNAL_ARGON2
} else if (!strncmp(kdf, "argon2", 6)) {
return argon2(kdf, password, password_length, salt, salt_length,
key, key_length, iterations, memory, parallel);
#endif
}
return -EINVAL;
}

View File

@@ -0,0 +1,299 @@
/*
* Generic wrapper for storage encryption modes and Initial Vectors
* (reimplementation of some functions from Linux dm-crypt kernel)
*
* Copyright (C) 2014-2017, 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, IV_PLAIN64BE } 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 < 8)
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, "plain64be")) {
ctx->type = IV_PLAIN64BE;
} 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_PLAIN64BE:
memset(ctx->iv, 0, ctx->iv_size);
*(uint64_t *)&ctx->iv[ctx->iv_size - sizeof(uint64_t)] = cpu_to_be64(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

@@ -0,0 +1,426 @@
/*
* Implementation of Password-Based Cryptography as per PKCS#5
* Copyright (C) 2002,2003 Simon Josefsson
* Copyright (C) 2004 Free Software Foundation
*
* cryptsetup related changes
* Copyright (C) 2012-2017, Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2017, Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this file; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#include <errno.h>
#include <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
*
* PBKDF2 applies a pseudorandom function (see Appendix B.1 for an
* example) to derive keys. The length of the derived key is essentially
* unbounded. (However, the maximum effective search space for the
* derived key may be limited by the structure of the underlying
* pseudorandom function. See Appendix B.1 for further discussion.)
* PBKDF2 is recommended for new applications.
*
* PBKDF2 (P, S, c, dkLen)
*
* Options: PRF underlying pseudorandom function (hLen
* denotes the length in octets of the
* pseudorandom function output)
*
* Input: P password, an octet string (ASCII or UTF-8)
* S salt, an octet string
* c iteration count, a positive integer
* dkLen intended length in octets of the derived
* key, a positive integer, at most
* (2^32 - 1) * hLen
*
* 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, 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;
char *tmp;
tmp = alloca(tmplen);
if (tmp == NULL)
return -ENOMEM;
hLen = crypt_hmac_size(hash);
if (hLen == 0 || hLen > MAX_PRF_BLOCK_LEN)
return -EINVAL;
if (c == 0)
return -EINVAL;
if (dkLen == 0)
return -EINVAL;
/*
*
* Steps:
*
* 1. If dkLen > (2^32 - 1) * hLen, output "derived key too long" and
* stop.
*/
if (dkLen > 4294967295U)
return -EINVAL;
/*
* 2. Let l be the number of hLen-octet blocks in the derived key,
* rounding up, and let r be the number of octets in the last
* block:
*
* l = CEIL (dkLen / hLen) ,
* r = dkLen - (l - 1) * hLen .
*
* Here, CEIL (x) is the "ceiling" function, i.e. the smallest
* integer greater than, or equal to, x.
*/
l = dkLen / hLen;
if (dkLen % hLen)
l++;
r = dkLen - (l - 1) * hLen;
/*
* 3. For each block of the derived key apply the function F defined
* below to the password P, the salt S, the iteration count c, and
* the block index to compute the block:
*
* T_1 = F (P, S, c, 1) ,
* T_2 = F (P, S, c, 2) ,
* ...
* T_l = F (P, S, c, l) ,
*
* where the function F is defined as the exclusive-or sum of the
* first c iterates of the underlying pseudorandom function PRF
* applied to the password P and the concatenation of the salt S
* and the block index i:
*
* F (P, S, c, i) = U_1 \xor U_2 \xor ... \xor U_c
*
* where
*
* U_1 = PRF (P, S || INT (i)) ,
* U_2 = PRF (P, U_1) ,
* ...
* U_c = PRF (P, U_{c-1}) .
*
* Here, INT (i) is a four-octet encoding of the integer i, most
* significant octet first.
*
* 4. Concatenate the blocks and extract the first dkLen octets to
* produce a derived key DK:
*
* DK = T_1 || T_2 || ... || T_l<0..r-1>
*
* 5. Output the derived key DK.
*
* Note. The construction of the function F follows a "belt-and-
* suspenders" approach. The iterates U_i are computed recursively to
* remove a degree of parallelism from an opponent; they are exclusive-
* ored together to reduce concerns about the recursion degenerating
* into a small set of values.
*
*/
/* 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);
for (u = 1; u <= c ; u++) {
if (u == 1) {
memcpy(tmp, S, Slen);
tmp[Slen + 0] = (i & 0xff000000) >> 24;
tmp[Slen + 1] = (i & 0x00ff0000) >> 16;
tmp[Slen + 2] = (i & 0x0000ff00) >> 8;
tmp[Slen + 3] = (i & 0x000000ff) >> 0;
if (crypt_hmac_write(hmac, tmp, tmplen))
goto out;
} else {
if (crypt_hmac_write(hmac, U, hLen))
goto out;
}
if (crypt_hmac_final(hmac, U, hLen))
goto out;
for (k = 0; (unsigned int) k < hLen; k++)
T[k] ^= U[k];
}
memcpy(DK + (i - 1) * hLen, T, (unsigned int) i == l ? r : hLen);
}
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

@@ -0,0 +1,395 @@
/*
* PBKDF performance check
* Copyright (C) 2012-2017, Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2017, Milan Broz
* Copyright (C) 2016-2017, Ondrej Mosnacek
*
* 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 <limits.h>
#include <time.h>
#include <sys/time.h>
#include <sys/resource.h>
#include "crypto_backend.h"
#define BENCH_MIN_MS 250
#define BENCH_MIN_MS_FAST 10
#define BENCH_PERCENT_ATLEAST 95
#define BENCH_PERCENT_ATMOST 110
#define BENCH_SAMPLES_FAST 3
#define BENCH_SAMPLES_SLOW 1
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 (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;
}
return ms;
}
static long timespec_ms(struct timespec *start, struct timespec *end)
{
return (end->tv_sec - start->tv_sec) * 1000 +
(end->tv_nsec - start->tv_nsec) / (1000 * 1000);
}
static int measure_argon2(const char *kdf, const char *password, size_t password_length,
const char *salt, size_t salt_length,
char *key, size_t key_length,
uint32_t t_cost, uint32_t m_cost, uint32_t parallel,
size_t samples, long ms_atleast, long *out_ms)
{
long ms, ms_min = LONG_MAX;
int r;
size_t i;
for (i = 0; i < samples; i++) {
struct timespec tstart, tend;
/*
* NOTE: We must use clock_gettime here, because Argon2 can run over
* multiple threads, and thus we care about real time, not CPU time!
*/
if (clock_gettime(CLOCK_MONOTONIC_RAW, &tstart) < 0)
return -EINVAL;
r = crypt_pbkdf(kdf, NULL, password, password_length, salt,
salt_length, key, key_length, t_cost, m_cost, parallel);
if (r < 0)
return r;
if (clock_gettime(CLOCK_MONOTONIC_RAW, &tend) < 0)
return -EINVAL;
ms = timespec_ms(&tstart, &tend);
if (ms < 0)
return -EINVAL;
if (ms < ms_atleast) {
/* early exit */
ms_min = ms;
break;
}
if (ms < ms_min) {
ms_min = ms;
}
}
*out_ms = ms_min;
return 0;
}
#define CONTINUE 0
#define FINAL 1
static int next_argon2_params(uint32_t *t_cost, uint32_t *m_cost,
uint32_t min_t_cost, uint32_t min_m_cost,
uint32_t max_m_cost, long ms, uint32_t target_ms)
{
uint32_t old_t_cost, old_m_cost, new_t_cost, new_m_cost;
uint64_t num, denom;
old_t_cost = *t_cost;
old_m_cost = *m_cost;
if (ms > target_ms) {
/* decreasing, first try to lower t_cost, then m_cost */
num = (uint64_t)*t_cost * (uint64_t)target_ms;
denom = (uint64_t)ms;
new_t_cost = (uint32_t)(num / denom);
if (new_t_cost < min_t_cost) {
num = (uint64_t)*t_cost * (uint64_t)*m_cost *
(uint64_t)target_ms;
denom = (uint64_t)min_t_cost * (uint64_t)ms;
*t_cost = min_t_cost;
*m_cost = (uint32_t)(num / denom);
if (*m_cost < min_m_cost) {
*m_cost = min_m_cost;
return FINAL;
}
} else {
*t_cost = new_t_cost;
}
} else {
/* increasing, first try to increase m_cost, then t_cost */
num = (uint64_t)*m_cost * (uint64_t)target_ms;
denom = (uint64_t)ms;
new_m_cost = (uint32_t)(num / denom);
if (new_m_cost > max_m_cost) {
num = (uint64_t)*t_cost * (uint64_t)*m_cost *
(uint64_t)target_ms;
denom = (uint64_t)max_m_cost * (uint64_t)ms;
*t_cost = (uint32_t)(num / denom);
*m_cost = max_m_cost;
if (*t_cost <= min_t_cost) {
*t_cost = min_t_cost;
return FINAL;
}
} else if (new_m_cost < min_m_cost) {
*m_cost = min_m_cost;
return FINAL;
} else {
*m_cost = new_m_cost;
}
}
/* do not continue if it is the same as in the previous run */
if (old_t_cost == *t_cost && old_m_cost == *m_cost)
return FINAL;
return CONTINUE;
}
static int crypt_argon2_check(const char *kdf, const char *password,
size_t password_length, const char *salt,
size_t salt_length, size_t key_length,
uint32_t min_t_cost, uint32_t max_m_cost,
uint32_t parallel, uint32_t target_ms,
uint32_t *out_t_cost, uint32_t *out_m_cost,
int (*progress)(uint32_t time_ms, void *usrptr),
void *usrptr)
{
int r = 0;
char *key = NULL;
uint32_t t_cost, m_cost, min_m_cost = 8 * parallel;
long ms;
long ms_atleast = (long)target_ms * BENCH_PERCENT_ATLEAST / 100;
long ms_atmost = (long)target_ms * BENCH_PERCENT_ATMOST / 100;
if (key_length <= 0 || target_ms <= 0)
return -EINVAL;
if (max_m_cost < min_m_cost)
return -EINVAL;
key = malloc(key_length);
if (!key)
return -ENOMEM;
t_cost = min_t_cost;
m_cost = min_m_cost;
/* 1. Find some small parameters, s. t. ms >= BENCH_MIN_MS: */
while (1) {
r = measure_argon2(kdf, password, password_length, salt, salt_length,
key, key_length, t_cost, m_cost, parallel,
BENCH_SAMPLES_FAST, BENCH_MIN_MS, &ms);
if (!r) {
/* Update parameters to actual measurement */
*out_t_cost = t_cost;
*out_m_cost = m_cost;
if (progress && progress((uint32_t)ms, usrptr))
r = -EINTR;
}
if (r < 0)
goto out;
if (ms >= BENCH_MIN_MS)
break;
if (m_cost == max_m_cost) {
if (ms < BENCH_MIN_MS_FAST)
t_cost *= 16;
else {
uint32_t new = (t_cost * BENCH_MIN_MS) / (uint32_t)ms;
if (new == t_cost)
break;
t_cost = new;
}
} else {
if (ms < BENCH_MIN_MS_FAST)
m_cost *= 16;
else {
uint32_t new = (m_cost * BENCH_MIN_MS) / (uint32_t)ms;
if (new == m_cost)
break;
m_cost = new;
}
if (m_cost > max_m_cost) {
m_cost = max_m_cost;
}
}
}
/*
* 2. Use the params obtained in (1.) to estimate the target params.
* 3. Then repeatedly measure the candidate params and if they fall out of
* the acceptance range (+-5 %), try to improve the estimate:
*/
do {
if (next_argon2_params(&t_cost, &m_cost, min_t_cost, min_m_cost,
max_m_cost, ms, target_ms)) {
/* Update parameters to final computation */
*out_t_cost = t_cost;
*out_m_cost = m_cost;
break;
}
r = measure_argon2(kdf, password, password_length, salt, salt_length,
key, key_length, t_cost, m_cost, parallel,
BENCH_SAMPLES_SLOW, ms_atleast, &ms);
if (!r) {
/* Update parameters to actual measurement */
*out_t_cost = t_cost;
*out_m_cost = m_cost;
if (progress && progress((uint32_t)ms, usrptr))
r = -EINTR;
}
if (r < 0)
break;
} while (ms < ms_atleast || ms > ms_atmost);
out:
if (key) {
crypt_backend_memzero(key, key_length);
free(key);
}
return r;
}
/* This code benchmarks PBKDF and returns iterations/second using specified hash */
static int crypt_pbkdf_check(const char *kdf, const char *hash,
const char *password, size_t password_length,
const char *salt, size_t salt_length,
size_t key_length, uint32_t *iter_secs, uint32_t target_ms,
int (*progress)(uint32_t time_ms, void *usrptr), void *usrptr)
{
struct rusage rstart, rend;
int r = 0, step = 0;
long ms = 0;
char *key = NULL;
uint32_t iterations;
double PBKDF2_temp;
if (!kdf || !hash || key_length <= 0)
return -EINVAL;
key = malloc(key_length);
if (!key)
return -ENOMEM;
*iter_secs = 0;
iterations = 1 << 15;
while (1) {
if (getrusage(RUSAGE_SELF, &rstart) < 0) {
r = -EINVAL;
goto out;
}
r = crypt_pbkdf(kdf, hash, password, password_length, salt,
salt_length, key, key_length, iterations, 0, 0);
if (r < 0)
goto out;
if (getrusage(RUSAGE_SELF, &rend) < 0) {
r = -EINVAL;
goto out;
}
ms = time_ms(&rstart, &rend);
if (ms) {
PBKDF2_temp = (double)iterations * target_ms / ms;
if (PBKDF2_temp > UINT32_MAX)
return -EINVAL;
*iter_secs = (uint32_t)PBKDF2_temp;
}
if (progress && progress((uint32_t)ms, usrptr)) {
r = -EINTR;
goto out;
}
if (ms > 500)
break;
if (ms <= 62)
iterations <<= 4;
else if (ms <= 125)
iterations <<= 3;
else if (ms <= 250)
iterations <<= 2;
else
iterations <<= 1;
if (++step > 10 || !iterations) {
r = -EINVAL;
goto out;
}
}
out:
if (key) {
crypt_backend_memzero(key, key_length);
free(key);
}
return r;
}
#define ARGON2_MIN_T_COST 4
int crypt_pbkdf_perf(const char *kdf, const char *hash,
const char *password, size_t password_size,
const char *salt, size_t salt_size,
size_t volume_key_size, uint32_t time_ms,
uint32_t max_memory_kb, uint32_t parallel_threads,
uint32_t *iterations_out, uint32_t *memory_out,
int (*progress)(uint32_t time_ms, void *usrptr), void *usrptr)
{
int r = -EINVAL;
if (!kdf || !iterations_out || !memory_out)
return -EINVAL;
*memory_out = 0;
*iterations_out = 0;
if (!strcmp(kdf, "pbkdf2"))
r = crypt_pbkdf_check(kdf, hash, password, password_size,
salt, salt_size, volume_key_size,
iterations_out, time_ms, progress, usrptr);
else if (!strncmp(kdf, "argon2", 6))
r = crypt_argon2_check(kdf, password, password_size,
salt, salt_size, volume_key_size,
ARGON2_MIN_T_COST, max_memory_kb,
parallel_threads, time_ms, iterations_out,
memory_out, progress, usrptr);
return r;
}

13
lib/integrity/Makefile.am Normal file
View File

@@ -0,0 +1,13 @@
moduledir = $(libdir)/cryptsetup
noinst_LTLIBRARIES = libintegrity.la
libintegrity_la_CFLAGS = -Wall $(AM_CFLAGS) @CRYPTO_CFLAGS@
libintegrity_la_SOURCES = \
integrity.c \
integrity.h
AM_CPPFLAGS = -include config.h \
-I$(top_srcdir)/lib \
-I$(top_srcdir)/lib/crypto_backend

282
lib/integrity/integrity.c Normal file
View File

@@ -0,0 +1,282 @@
/*
* Integrity volume handling
*
* Copyright (C) 2016-2017, Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this file; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <uuid/uuid.h>
#include "integrity.h"
#include "internal.h"
static int INTEGRITY_read_superblock(struct crypt_device *cd,
struct device *device,
uint64_t offset, struct superblock *sb)
{
int devfd, r;
devfd = device_open(device, O_RDONLY);
if(devfd < 0) {
return -EINVAL;
}
if (read_lseek_blockwise(devfd, device_block_size(device),
device_alignment(device), sb, sizeof(*sb), offset) != sizeof(*sb) ||
memcmp(sb->magic, SB_MAGIC, sizeof(sb->magic)) ||
sb->version != SB_VERSION) {
log_std(cd, "No integrity superblock detected on %s.\n",
device_path(device));
r = -EINVAL;
} else {
sb->integrity_tag_size = le16toh(sb->integrity_tag_size);
sb->journal_sections = le32toh(sb->journal_sections);
sb->provided_data_sectors = le64toh(sb->provided_data_sectors);
r = 0;
}
close(devfd);
return r;
}
int INTEGRITY_read_sb(struct crypt_device *cd, struct crypt_params_integrity *params)
{
struct superblock sb;
int r;
r = INTEGRITY_read_superblock(cd, crypt_data_device(cd), 0, &sb);
if (r)
return r;
params->sector_size = SECTOR_SIZE << sb.log2_sectors_per_block;
params->tag_size = sb.integrity_tag_size;
return 0;
}
int INTEGRITY_dump(struct crypt_device *cd, struct device *device, uint64_t offset)
{
struct superblock sb;
int r;
r = INTEGRITY_read_superblock(cd, device, offset, &sb);
if (r)
return r;
log_std(cd, "Info for integrity device %s.\n", device_path(device));
log_std(cd, "log2_interleave_sectors %d\n", sb.log2_interleave_sectors);
log_std(cd, "integrity_tag_size %u\n", sb.integrity_tag_size);
log_std(cd, "journal_sections %u\n", sb.journal_sections);
log_std(cd, "provided_data_sectors %" PRIu64 "\n", sb.provided_data_sectors);
log_std(cd, "sector_size %u\n", SECTOR_SIZE << sb.log2_sectors_per_block);
return 0;
}
int INTEGRITY_data_sectors(struct crypt_device *cd,
struct device *device, uint64_t offset,
uint64_t *data_sectors)
{
struct superblock sb;
int r;
r = INTEGRITY_read_superblock(cd, device, offset, &sb);
if (r)
return r;
*data_sectors = sb.provided_data_sectors;
return 0;
}
int INTEGRITY_key_size(struct crypt_device *cd)
{
const char *integrity = crypt_get_integrity(cd);
if (!integrity)
return 0;
//FIXME: use crypto backend hash size
if (!strcmp(integrity, "aead"))
return 0;
else if (!strcmp(integrity, "hmac(sha256)"))
return 32;
else if (!strcmp(integrity, "hmac(sha512)"))
return 64;
else if (!strcmp(integrity, "poly1305"))
return 0;
else if (!strcmp(integrity, "none"))
return 0;
return -EINVAL;
}
int INTEGRITY_tag_size(struct crypt_device *cd,
const char *integrity,
const char *cipher_mode)
{
int iv_tag_size = 0, auth_tag_size = 0;
if (!cipher_mode)
iv_tag_size = 0;
else if (!strcmp(cipher_mode, "xts-random"))
iv_tag_size = 16;
else if (!strcmp(cipher_mode, "gcm-random"))
iv_tag_size = 12;
else if (!strcmp(cipher_mode, "ccm-random"))
iv_tag_size = 8;
else if (!strcmp(cipher_mode, "ctr-random"))
iv_tag_size = 16;
else if (!strcmp(cipher_mode, "random"))
iv_tag_size = 16;
//FIXME: use crypto backend hash size
if (!integrity || !strcmp(integrity, "none"))
auth_tag_size = 0;
else if (!strcmp(integrity, "aead"))
auth_tag_size = 16; //FIXME gcm- mode only
else if (!strcmp(integrity, "cmac(aes)"))
auth_tag_size = 16;
else if (!strcmp(integrity, "hmac(sha256)"))
auth_tag_size = 32;
else if (!strcmp(integrity, "hmac(sha512)"))
auth_tag_size = 64;
else if (!strcmp(integrity, "poly1305")) {
if (iv_tag_size)
iv_tag_size = 12;
auth_tag_size = 16;
}
return iv_tag_size + auth_tag_size;
}
int INTEGRITY_activate(struct crypt_device *cd,
const char *name,
const struct crypt_params_integrity *params,
struct volume_key *vk,
struct volume_key *journal_crypt_key,
struct volume_key *journal_mac_key,
uint32_t flags)
{
uint32_t dmi_flags;
struct crypt_dm_active_device dmdi = {
.target = DM_INTEGRITY,
.data_device = crypt_data_device(cd),
.flags = flags,
.u.integrity = {
.offset = crypt_get_data_offset(cd),
.tag_size = crypt_get_integrity_tag_size(cd),
.sector_size = crypt_get_sector_size(cd),
.vk = vk,
.journal_crypt_key = journal_crypt_key,
.journal_integrity_key = journal_mac_key,
}
};
int r;
r = INTEGRITY_data_sectors(cd, dmdi.data_device,
dmdi.u.integrity.offset * SECTOR_SIZE, &dmdi.size);
if (r < 0)
return r;
if (params) {
dmdi.u.integrity.journal_size = params->journal_size;
dmdi.u.integrity.journal_watermark = params->journal_watermark;
dmdi.u.integrity.journal_commit_time = params->journal_commit_time;
dmdi.u.integrity.interleave_sectors = params->interleave_sectors;
dmdi.u.integrity.buffer_sectors = params->buffer_sectors;
dmdi.u.integrity.integrity = params->integrity;
dmdi.u.integrity.journal_integrity = params->journal_integrity;
dmdi.u.integrity.journal_crypt = params->journal_crypt;
}
log_dbg("Trying to activate INTEGRITY device on top of %s, using name %s, tag size %d, provided sectors %" PRIu64".",
device_path(dmdi.data_device), name, dmdi.u.integrity.tag_size, dmdi.size);
r = device_block_adjust(cd, dmdi.data_device, DEV_EXCL,
dmdi.u.integrity.offset, NULL, &dmdi.flags);
if (r)
return r;
r = dm_create_device(cd, name, "INTEGRITY", &dmdi, 0);
if (r < 0 && (dm_flags(DM_INTEGRITY, &dmi_flags) || !(dmi_flags & DM_INTEGRITY_SUPPORTED))) {
log_err(cd, _("Kernel doesn't support dm-integrity mapping.\n"));
return -ENOTSUP;
}
return r;
}
int INTEGRITY_format(struct crypt_device *cd,
const struct crypt_params_integrity *params,
struct volume_key *journal_crypt_key,
struct volume_key *journal_mac_key)
{
uint32_t dmi_flags;
char tmp_name[64], tmp_uuid[40];
struct crypt_dm_active_device dmdi = {
.target = DM_INTEGRITY,
.data_device = crypt_data_device(cd),
.size = 8,
.flags = CRYPT_ACTIVATE_PRIVATE, /* We always create journal but it can be unused later */
.u.integrity = {
.offset = crypt_get_data_offset(cd),
.tag_size = crypt_get_integrity_tag_size(cd),
.sector_size = crypt_get_sector_size(cd),
.journal_crypt_key = journal_crypt_key,
.journal_integrity_key = journal_mac_key,
}
};
int r;
uuid_t tmp_uuid_bin;
if (params) {
dmdi.u.integrity.journal_size = params->journal_size;
dmdi.u.integrity.journal_watermark = params->journal_watermark;
dmdi.u.integrity.journal_commit_time = params->journal_commit_time;
dmdi.u.integrity.interleave_sectors = params->interleave_sectors;
dmdi.u.integrity.buffer_sectors = params->buffer_sectors;
dmdi.u.integrity.journal_integrity = params->journal_integrity;
dmdi.u.integrity.journal_crypt = params->journal_crypt;
dmdi.u.integrity.integrity = params->integrity;
}
uuid_generate(tmp_uuid_bin);
uuid_unparse(tmp_uuid_bin, tmp_uuid);
snprintf(tmp_name, sizeof(tmp_name), "temporary-cryptsetup-%s", tmp_uuid);
log_dbg("Trying to format INTEGRITY device on top of %s, tmp name %s, tag size %d.",
device_path(dmdi.data_device), tmp_name, dmdi.u.integrity.tag_size);
r = device_block_adjust(cd, dmdi.data_device, DEV_EXCL, dmdi.u.integrity.offset, NULL, NULL);
if (r < 0 && (dm_flags(DM_INTEGRITY, &dmi_flags) || !(dmi_flags & DM_INTEGRITY_SUPPORTED))) {
log_err(cd, _("Kernel doesn't support dm-integrity mapping.\n"));
return -ENOTSUP;
}
if (r)
return r;
r = dm_create_device(cd, tmp_name, "INTEGRITY", &dmdi, 0);
if (r)
return r;
return dm_remove_device(cd, tmp_name, CRYPT_DEACTIVATE_FORCE);
}

70
lib/integrity/integrity.h Normal file
View File

@@ -0,0 +1,70 @@
/*
* Integrity header defitinion
*
* Copyright (C) 2016-2017, 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.
*/
#ifndef _CRYPTSETUP_INTEGRITY_H
#define _CRYPTSETUP_INTEGRITY_H
#include <stdint.h>
struct crypt_device;
struct device;
struct crypt_params_integrity;
struct volume_key;
/* dm-integrity helper */
#define SB_MAGIC "integrt"
#define SB_VERSION 1
struct superblock {
uint8_t magic[8];
uint8_t version;
int8_t log2_interleave_sectors;
uint16_t integrity_tag_size;
uint32_t journal_sections;
uint64_t provided_data_sectors;
uint32_t flags;
uint8_t log2_sectors_per_block;
} __attribute__ ((packed));
int INTEGRITY_read_sb(struct crypt_device *cd, struct crypt_params_integrity *params);
int INTEGRITY_dump(struct crypt_device *cd, struct device *device, uint64_t offset);
int INTEGRITY_data_sectors(struct crypt_device *cd,
struct device *device, uint64_t offset,
uint64_t *data_sectors);
int INTEGRITY_key_size(struct crypt_device *cd);
int INTEGRITY_tag_size(struct crypt_device *cd,
const char *integrity,
const char *cipher_mode);
int INTEGRITY_format(struct crypt_device *cd,
const struct crypt_params_integrity *params,
struct volume_key *journal_crypt_key,
struct volume_key *journal_mac_key);
int INTEGRITY_activate(struct crypt_device *cd,
const char *name,
const struct crypt_params_integrity *params,
struct volume_key *vk,
struct volume_key *journal_crypt_key,
struct volume_key *journal_mac_key,
uint32_t flags);
#endif

View File

@@ -1,13 +1,15 @@
/*
* 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-2017, Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2017, Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -22,82 +24,146 @@
#ifndef INTERNAL_H
#define INTERNAL_H
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdint.h>
#include <stdarg.h>
#include <stdbool.h>
#include <unistd.h>
#include <inttypes.h>
#include "nls.h"
#include "bitops.h"
#include "utils_crypt.h"
#include "utils_loop.h"
#include "utils_dm.h"
#include "utils_fips.h"
#include "utils_keyring.h"
#include "crypto_backend.h"
#include "libcryptsetup.h"
/* to silent gcc -Wcast-qual for const cast */
#define CONST_CAST(x) (x)(uintptr_t)
#define SECTOR_SHIFT 9
#define SECTOR_SIZE (1 << SECTOR_SHIFT)
#define MAX_SECTOR_SIZE 4096 /* min page size among all platforms */
#define DEFAULT_DISK_ALIGNMENT 1048576 /* 1MiB */
#define DEFAULT_MEM_ALIGNMENT 4096
#define MAX_ERROR_LENGTH 512
#define MAX_PBKDF_THREADS 4
#define MAX_PBKDF_MEMORY 1024*1024 /* 1GiB */
#define MIN_PBKDF2_ITERATIONS 1000 /* recommendation in NIST SP 800-132 */
#define at_least(a, b) ({ __typeof__(a) __at_least = (a); (__at_least >= (b))?__at_least:(b); })
#define CRYPT_DEFAULT_SEGMENT 0
struct crypt_device;
struct volume_key {
size_t keylength;
const char *key_description;
char key[];
};
struct volume_key *crypt_alloc_volume_key(unsigned keylength, const char *key);
struct volume_key *crypt_generate_volume_key(struct crypt_device *cd, unsigned keylength);
struct volume_key *crypt_alloc_volume_key(size_t keylength, const char *key);
struct volume_key *crypt_generate_volume_key(struct crypt_device *cd, size_t keylength);
void crypt_free_volume_key(struct volume_key *vk);
void crypt_volume_key_set_description(struct volume_key *key, const char *key_description);
const char *crypt_volume_key_get_description(const struct volume_key *key);
struct crypt_pbkdf_type *crypt_get_pbkdf(struct crypt_device *cd);
int init_pbkdf_type(struct crypt_device *cd,
const struct crypt_pbkdf_type *pbkdf,
const char *dev_type);
int verify_pbkdf_params(struct crypt_device *cd,
const struct crypt_pbkdf_type *pbkdf);
int crypt_benchmark_pbkdf_internal(struct crypt_device *cd,
struct crypt_pbkdf_type *pbkdf,
size_t volume_key_size);
/* Device backend */
struct device;
int device_alloc(struct device **device, const char *path);
int device_alloc_no_check(struct device **device, const char *path);
void device_free(struct device *device);
const char *device_path(const struct device *device);
const char *device_dm_name(const struct device *device);
const char *device_block_path(const struct device *device);
void device_topology_alignment(struct device *device,
unsigned long *required_alignment, /* bytes */
unsigned long *alignment_offset, /* bytes */
unsigned long default_alignment);
size_t device_block_size(struct device *device);
int device_read_ahead(struct device *device, uint32_t *read_ahead);
int device_size(struct device *device, uint64_t *size);
int device_open(struct device *device, int flags);
void device_disable_direct_io(struct device *device);
int device_is_identical(struct device *device1, struct device *device2);
int device_is_rotational(struct device *device);
size_t device_alignment(struct device *device);
int device_direct_io(struct device *device);
int device_open_locked(struct device *device, int flags);
int device_read_lock(struct crypt_device *cd, struct device *device);
int device_write_lock(struct crypt_device *cd, struct device *device);
void device_read_unlock(struct device *device);
void device_write_unlock(struct device *device);
enum devcheck { DEV_OK = 0, DEV_EXCL = 1, DEV_SHARED = 2 };
int device_check_access(struct crypt_device *cd,
struct device *device,
enum devcheck device_check);
int device_block_adjust(struct crypt_device *cd,
struct device *device,
enum devcheck device_check,
uint64_t device_offset,
uint64_t *size,
uint32_t *flags);
size_t size_round_up(size_t size, size_t block);
/* Receive backend devices from context helpers */
struct device *crypt_metadata_device(struct crypt_device *cd);
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_check_crypt_segment(const char *device, uint64_t offset, uint64_t size);
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);
int lookup_by_disk_id(const char *dm_uuid);
int lookup_by_sysfs_uuid_field(const char *dm_uuid, size_t max_len);
int sector_size_for_device(const char *device);
int device_read_ahead(const char *dev, uint32_t *read_ahead);
ssize_t write_blockwise(int fd, void *buf, size_t count);
ssize_t read_blockwise(int fd, void *_buf, size_t count);
ssize_t write_lseek_blockwise(int fd, char *buf, size_t count, off_t offset);
int device_ready(struct crypt_device *cd, const char *device, int mode);
int device_size(const char *device, uint64_t *size);
ssize_t write_buffer(int fd, const void *buf, size_t count);
ssize_t read_buffer(int fd, void *buf, size_t count);
ssize_t write_blockwise(int fd, size_t bsize, size_t alignment, void *orig_buf, size_t count);
ssize_t read_blockwise(int fd, size_t bsize, size_t alignment, void *buf, size_t count);
ssize_t write_lseek_blockwise(int fd, size_t bsize, size_t alignment, void *buf, size_t count, off_t offset);
ssize_t read_lseek_blockwise(int fd, size_t bsize, size_t alignment, void *buf, size_t count, off_t offset);
enum devcheck { DEV_OK = 0, DEV_EXCL = 1, DEV_SHARED = 2 };
int device_check_and_adjust(struct crypt_device *cd,
const char *device,
enum devcheck device_check,
uint64_t *size,
uint64_t *offset,
uint32_t *flags);
size_t crypt_getpagesize(void);
unsigned crypt_cpusonline(void);
void logger(struct crypt_device *cd, int class, const char *file, int line, const char *format, ...);
int init_crypto(struct crypt_device *ctx);
const char *uint64_to_str(char *buffer, size_t size, const uint64_t *val);
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)
#define log_err(c, x...) logger(c, CRYPT_LOG_ERROR, __FILE__, __LINE__, x)
int crypt_get_debug_level(void);
void debug_processes_using_device(const char *name);
int crypt_memlock_inc(struct crypt_device *ctx);
int crypt_memlock_dec(struct crypt_device *ctx);
void get_topology_alignment(const char *device,
unsigned long *required_alignment, /* bytes */
unsigned long *alignment_offset, /* bytes */
unsigned long default_alignment);
int crypt_metadata_locking_enabled(void);
int crypt_random_init(struct crypt_device *ctx);
int crypt_random_get(struct crypt_device *ctx, char *buf, size_t len, int quality);
@@ -114,23 +180,23 @@ int PLAIN_activate(struct crypt_device *cd,
uint64_t size,
uint32_t flags);
/**
* Different methods used to erase sensitive data concerning
* either encrypted payload area or master key inside keyslot
* area
*/
typedef enum {
CRYPT_WIPE_ZERO, /**< overwrite area using zero blocks */
CRYPT_WIPE_DISK, /**< erase disk (using Gutmann method if it is rotational disk)*/
CRYPT_WIPE_SSD, /**< erase solid state disk (random write) */
CRYPT_WIPE_RANDOM /**< overwrite area using some up to now unspecified
* random algorithm */
} crypt_wipe_type;
void *crypt_get_hdr(struct crypt_device *cd, const char *type);
int crypt_wipe(const char *device,
uint64_t offset,
uint64_t sectors,
crypt_wipe_type type,
int flags);
int crypt_wipe_device(struct crypt_device *cd,
struct device *device,
crypt_wipe_pattern pattern,
uint64_t offset,
uint64_t length,
size_t wipe_block_size,
int (*progress)(uint64_t size, uint64_t offset, void *usrptr),
void *usrptr);
/* Internal integrity helpers */
const char *crypt_get_integrity(struct crypt_device *cd);
int crypt_get_integrity_key_size(struct crypt_device *cd);
int crypt_get_integrity_tag_size(struct crypt_device *cd);
int crypt_key_in_keyring(struct crypt_device *cd);
void crypt_set_key_in_keyring(struct crypt_device *cd, unsigned key_in_keyring);
#endif /* INTERNAL_H */

File diff suppressed because it is too large Load Diff

View File

@@ -1,21 +1,20 @@
CRYPTSETUP_1.0 {
CRYPTSETUP_2.0 {
global:
crypt_init;
crypt_init_by_name;
crypt_init_by_name_and_header;
crypt_set_log_callback;
crypt_set_confirm_callback;
crypt_set_password_callback;
crypt_set_timeout;
crypt_set_password_retry;
crypt_set_iterarion_time;
crypt_set_iteration_time;
crypt_set_password_verify;
crypt_set_uuid;
crypt_set_label;
crypt_set_data_device;
crypt_memory_lock;
crypt_metadata_locking;
crypt_format;
crypt_convert;
crypt_load;
crypt_repair;
crypt_resize;
@@ -26,43 +25,75 @@ CRYPTSETUP_1.0 {
crypt_free;
crypt_keyslot_add_by_passphrase;
crypt_keyslot_change_by_passphrase;
crypt_keyslot_add_by_keyfile;
crypt_keyslot_add_by_keyfile_offset;
crypt_keyslot_add_by_volume_key;
crypt_keyslot_add_by_key;
crypt_keyslot_set_priority;
crypt_keyslot_get_priority;
crypt_token_json_get;
crypt_token_json_set;
crypt_token_status;
crypt_token_luks2_keyring_get;
crypt_token_luks2_keyring_set;
crypt_token_assign_keyslot;
crypt_token_unassign_keyslot;
crypt_token_register;
crypt_activate_by_token;
crypt_keyslot_destroy;
crypt_activate_by_passphrase;
crypt_activate_by_keyfile;
crypt_activate_by_keyfile_offset;
crypt_activate_by_volume_key;
crypt_activate_by_keyring;
crypt_deactivate;
crypt_deactivate_by_name;
crypt_volume_key_get;
crypt_volume_key_verify;
crypt_volume_key_keyring;
crypt_status;
crypt_dump;
crypt_benchmark;
crypt_benchmark_pbkdf;
crypt_get_cipher;
crypt_get_cipher_mode;
crypt_get_integrity_info;
crypt_get_uuid;
crypt_get_data_offset;
crypt_get_iv_offset;
crypt_get_volume_key_size;
crypt_get_device_name;
crypt_get_verity_info;
crypt_get_sector_size;
crypt_get_type;
crypt_get_active_device;
crypt_persistent_flags_set;
crypt_persistent_flags_get;
crypt_set_rng_type;
crypt_get_rng_type;
crypt_set_pbkdf_type;
crypt_get_pbkdf_type;
crypt_keyslot_max;
crypt_keyslot_area;
crypt_keyslot_status;
crypt_last_error;
crypt_get_error;
crypt_get_dir;
crypt_set_debug_level;
crypt_log;
crypt_header_backup;
crypt_header_restore;
crypt_keyfile_read;
crypt_wipe;
local:
*;
};

File diff suppressed because it is too large Load Diff

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
INCLUDES = -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,19 +1,21 @@
/*
* loop-AES compatible volume handling
*
* Copyright (C) 2011-2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2011-2017, Red Hat, Inc. All rights reserved.
* Copyright (C) 2011-2017, Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
* 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 program is distributed in the hope that it will be useful,
* 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 General Public License for more details.
* 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 General Public License
* along with this program; if not, write to the Free Software
* 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.
*/
@@ -73,16 +75,16 @@ static int hash_keys(struct crypt_device *cd,
const char *hash_override,
const char **input_keys,
unsigned int keys_count,
unsigned int key_len_output)
unsigned int key_len_output,
unsigned int key_len_input)
{
const char *hash_name;
char tweak, *key_ptr;
unsigned i, key_len_input;
unsigned int i;
int r;
hash_name = hash_override ?: get_hash(key_len_output);
tweak = get_tweak(keys_count);
key_len_input = strlen(input_keys[0]);
if (!keys_count || !key_len_output || !hash_name || !key_len_input) {
log_err(cd, _("Key processing error (using hash %s).\n"),
@@ -132,9 +134,10 @@ int LOOPAES_parse_keyfile(struct crypt_device *cd,
size_t buffer_len)
{
const char *keys[LOOPAES_KEYS_MAX];
unsigned i, key_index, key_len, offset;
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;
@@ -152,33 +155,45 @@ int LOOPAES_parse_keyfile(struct crypt_device *cd,
offset = 0;
key_index = 0;
key_lengths[0] = 0;
while (offset < buffer_len && key_index < LOOPAES_KEYS_MAX) {
keys[key_index++] = &buffer[offset];
while (offset < buffer_len && buffer[offset])
keys[key_index] = &buffer[offset];
key_lengths[key_index] = 0;;
while (offset < buffer_len && buffer[offset]) {
offset++;
key_lengths[key_index]++;
}
if (offset == buffer_len) {
log_dbg("Unterminated key #%d in keyfile.", key_index);
log_err(cd, _("Incompatible loop-AES keyfile detected.\n"));
return -EINVAL;
}
while (offset < buffer_len && !buffer[offset])
offset++;
key_index++;
}
/* All keys must be the same length */
key_len = key_index ? strlen(keys[0]) : 0;
key_len = key_lengths[0];
for (i = 0; i < key_index; i++)
if (key_len != strlen(keys[i])) {
if (!key_lengths[i] || (key_lengths[i] != key_len)) {
log_dbg("Unexpected length %d of key #%d (should be %d).",
strlen(keys[i]), i, key_len);
key_lengths[i], i, key_len);
key_len = 0;
break;
}
log_dbg("Keyfile: %d keys of length %d.", key_index, key_len);
if (offset != buffer_len || key_len == 0 ||
(key_index != 1 && key_index !=64 && key_index != 65)) {
log_err(cd, _("Incompatible loop-AES keyfile detected.\n"));
return -EINVAL;
}
log_dbg("Keyfile: %d keys of length %d.", key_index, key_len);
*keys_count = key_index;
return hash_keys(cd, vk, hash, keys, key_index, crypt_get_volume_key_size(cd));
return hash_keys(cd, vk, hash, keys, key_index,
crypt_get_volume_key_size(cd), key_len);
}
int LOOPAES_activate(struct crypt_device *cd,
@@ -189,21 +204,24 @@ int LOOPAES_activate(struct crypt_device *cd,
uint32_t flags)
{
char *cipher = NULL;
uint32_t req_flags;
uint32_t req_flags, dmc_flags;
int r;
struct crypt_dm_active_device dmd = {
.device = crypt_get_device_name(cd),
.cipher = NULL,
.uuid = crypt_get_uuid(cd),
.vk = vk,
.offset = crypt_get_data_offset(cd),
.iv_offset = crypt_get_iv_offset(cd),
.target = DM_CRYPT,
.size = 0,
.flags = flags
.flags = flags,
.data_device = crypt_data_device(cd),
.u.crypt = {
.cipher = NULL,
.vk = vk,
.offset = crypt_get_data_offset(cd),
.iv_offset = crypt_get_iv_offset(cd),
.sector_size = crypt_get_sector_size(cd),
}
};
r = device_check_and_adjust(cd, dmd.device, DEV_EXCL, &dmd.size, &dmd.offset, &flags);
r = device_block_adjust(cd, dmd.data_device, DEV_EXCL,
dmd.u.crypt.offset, &dmd.size, &dmd.flags);
if (r)
return r;
@@ -217,12 +235,14 @@ int LOOPAES_activate(struct crypt_device *cd,
if (r < 0)
return -ENOMEM;
dmd.cipher = cipher;
log_dbg("Trying to activate loop-AES device %s using cipher %s.", name, dmd.cipher);
dmd.u.crypt.cipher = cipher;
log_dbg("Trying to activate loop-AES device %s using cipher %s.",
name, dmd.u.crypt.cipher);
r = dm_create_device(name, CRYPT_LOOPAES, &dmd, 0);
r = dm_create_device(cd, name, CRYPT_LOOPAES, &dmd, 0);
if (!r && !(dm_flags() & req_flags)) {
if (r < 0 && !dm_flags(DM_CRYPT, &dmc_flags) &&
(dmc_flags & req_flags) != req_flags) {
log_err(cd, _("Kernel doesn't support loop-AES compatible mapping.\n"));
r = -ENOTSUP;
}

View File

@@ -1,19 +1,21 @@
/*
* loop-AES compatible volume handling
*
* Copyright (C) 2011-2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2011-2017, Red Hat, Inc. All rights reserved.
* Copyright (C) 2011-2017, Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
* 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 program is distributed in the hope that it will be useful,
* 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 General Public License for more details.
* 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 General Public License
* along with this program; if not, write to the Free Software
* 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.
*/
@@ -21,7 +23,6 @@
#define _LOOPAES_H
#include <unistd.h>
#include "config.h"
struct crypt_device;
struct volume_key;

View File

@@ -2,20 +2,16 @@ 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 \
pbkdf.c \
keymanage.c \
keyencryption.c \
pbkdf.h \
af.h \
luks.h
INCLUDES = -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

@@ -2,14 +2,15 @@
* AFsplitter - Anti forensic information splitter
*
* Copyright (C) 2004, Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2017, Red Hat, Inc. All rights reserved.
*
* AFsplitter diffuses information over a large stripe of data,
* therefor supporting secure data destruction.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -66,9 +67,14 @@ out:
static int diffuse(char *src, char *dst, size_t size, const char *hash_name)
{
unsigned int digest_size = crypt_hash_size(hash_name);
int hash_size = crypt_hash_size(hash_name);
unsigned int digest_size;
unsigned int i, blocks, padding;
if (hash_size <= 0)
return 1;
digest_size = hash_size;
blocks = size / digest_size;
padding = size % digest_size;
@@ -93,7 +99,7 @@ static int diffuse(char *src, char *dst, size_t size, const char *hash_name)
* must be supplied to AF_merge to recover information.
*/
int AF_split(char *src, char *dst, size_t blocksize,
int AF_split(const char *src, char *dst, size_t blocksize,
unsigned int blocknumbers, const char *hash)
{
unsigned int i;
@@ -119,7 +125,7 @@ out:
return r;
}
int AF_merge(char *src, char *dst, size_t blocksize,
int AF_merge(const char *src, char *dst, size_t blocksize,
unsigned int blocknumbers, const char *hash)
{
unsigned int i;
@@ -141,3 +147,17 @@ out:
free(bufblock);
return r;
}
/* Size of final split data including sector alignment */
size_t AF_split_sectors(size_t blocksize, unsigned int blocknumbers)
{
size_t af_size;
/* data material * stripes */
af_size = blocksize * blocknumbers;
/* round up to sector */
af_size = (af_size + (SECTOR_SIZE - 1)) / SECTOR_SIZE;
return af_size;
}

View File

@@ -2,14 +2,15 @@
* AFsplitter - Anti forensic information splitter
*
* Copyright (C) 2004, Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2017, Red Hat, Inc. All rights reserved.
*
* AFsplitter diffuses information over a large stripe of data,
* therefor supporting secure data destruction.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -36,7 +37,24 @@
* On error, both functions return -1, 0 otherwise.
*/
int AF_split(char *src, char *dst, size_t blocksize, unsigned int blocknumbers, const char *hash);
int AF_merge(char *src, char *dst, size_t blocksize, unsigned int blocknumbers, const char *hash);
int AF_split(const char *src, char *dst, size_t blocksize, unsigned int blocknumbers, const char *hash);
int AF_merge(const char *src, char *dst, size_t blocksize, unsigned int blocknumbers, const char *hash);
size_t AF_split_sectors(size_t blocksize, unsigned int blocknumbers);
int LUKS_encrypt_to_storage(
char *src, size_t srcLength,
const char *cipher,
const char *cipher_mode,
struct volume_key *vk,
unsigned int sector,
struct crypt_device *ctx);
int LUKS_decrypt_from_storage(
char *dst, size_t dstLength,
const char *cipher,
const char *cipher_mode,
struct volume_key *vk,
unsigned int sector,
struct crypt_device *ctx);
#endif

View File

@@ -2,11 +2,13 @@
* LUKS - Linux Unified Key Setup
*
* Copyright (C) 2004-2006, Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2017, Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2017, Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,186 +20,239 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <inttypes.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/utsname.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include "luks.h"
#include "af.h"
#include "internal.h"
#define div_round_up(a,b) ({ \
typeof(a) __a = (a); \
typeof(b) __b = (b); \
(__a - 1) / __b + 1; \
})
static inline int round_up_modulo(int x, int m) {
return div_round_up(x, m) * m;
}
static const char *cleaner_name=NULL;
static uint64_t cleaner_size = 0;
static int devfd=-1;
static int setup_mapping(const char *cipher, const char *name,
const char *device,
struct volume_key *vk,
unsigned int sector, size_t srcLength,
int mode, struct crypt_device *ctx)
static void _error_hint(struct crypt_device *ctx, const char *device,
const char *cipher, const char *mode, size_t keyLength)
{
int device_sector_size = sector_size_for_device(device);
struct crypt_dm_active_device dmd = {
.device = device,
.cipher = cipher,
.uuid = NULL,
.vk = vk,
.offset = sector,
.iv_offset = 0,
.size = 0,
.flags = 0
};
char cipher_spec[MAX_CIPHER_LEN * 3];
dmd.flags = CRYPT_ACTIVATE_PRIVATE;
if (mode == O_RDONLY)
dmd.flags |= CRYPT_ACTIVATE_READONLY;
/*
* we need to round this to nearest multiple of the underlying
* device's sector size, otherwise the mapping will be refused.
*/
if(device_sector_size < 0) {
log_err(ctx, _("Unable to obtain sector size for %s"), device);
return -EINVAL;
}
if (snprintf(cipher_spec, sizeof(cipher_spec), "%s-%s", cipher, mode) < 0)
return;
dmd.size = round_up_modulo(srcLength,device_sector_size)/SECTOR_SIZE;
cleaner_size = dmd.size;
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);
return dm_create_device(name, "TEMP", &dmd, 0);
if (!strncmp(mode, "xts", 3) && (keyLength != 256 && keyLength != 512))
log_err(ctx, _("Key size in XTS mode must be 256 or 512 bits.\n"));
}
static void sigint_handler(int sig __attribute__((unused)))
{
if(devfd >= 0)
close(devfd);
devfd = -1;
if(cleaner_name)
dm_remove_device(cleaner_name, 1, cleaner_size);
signal(SIGINT, SIG_DFL);
kill(getpid(), SIGINT);
}
static const char *_error_hint(char *cipherMode, size_t keyLength)
{
const char *hint= "";
if (!strncmp(cipherMode, "xts", 3) && (keyLength != 256 && keyLength != 512))
hint = _("Key size in XTS mode must be 256 or 512 bits.\n");
return hint;
}
/* This function is not reentrant safe, as it installs a signal
handler and global vars for cleaning */
static int LUKS_endec_template(char *src, size_t srcLength,
struct luks_phdr *hdr,
const char *cipher, const char *cipher_mode,
struct volume_key *vk,
const char *device,
unsigned int sector,
ssize_t (*func)(int, void *, size_t),
ssize_t (*func)(int, size_t, size_t, void *, size_t),
int mode,
struct crypt_device *ctx)
{
char *name = NULL;
char *fullpath = NULL;
char *dmCipherSpec = NULL;
const char *dmDir = dm_get_dir();
int r = -1;
char name[PATH_MAX], path[PATH_MAX];
char cipher_spec[MAX_CIPHER_LEN * 3];
struct crypt_dm_active_device dmd = {
.target = DM_CRYPT,
.uuid = NULL,
.flags = CRYPT_ACTIVATE_PRIVATE,
.data_device = crypt_metadata_device(ctx),
.u.crypt = {
.cipher = cipher_spec,
.vk = vk,
.offset = sector,
.iv_offset = 0,
.sector_size = SECTOR_SIZE,
}
};
int r, devfd = -1;
size_t bsize, alignment;
if(dmDir == NULL) {
log_err(ctx, _("Failed to obtain device mapper directory."));
return -1;
}
if(asprintf(&name,"temporary-cryptsetup-%d",getpid()) == -1 ||
asprintf(&fullpath,"%s/%s",dmDir,name) == -1 ||
asprintf(&dmCipherSpec,"%s-%s",hdr->cipherName, hdr->cipherMode) == -1) {
r = -ENOMEM;
goto out1;
}
log_dbg("Using dmcrypt to access keyslot area.");
signal(SIGINT, sigint_handler);
cleaner_name = name;
bsize = device_block_size(dmd.data_device);
alignment = device_alignment(dmd.data_device);
if (!bsize || !alignment)
return -EINVAL;
r = setup_mapping(dmCipherSpec, name, device,
vk, sector, srcLength, mode, ctx);
if(r < 0) {
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%s"),
device, dmCipherSpec,
_error_hint(hdr->cipherMode, vk->keylength * 8));
r = -EIO;
goto out1;
dmd.size = size_round_up(srcLength, bsize) / SECTOR_SIZE;
if (mode == O_RDONLY)
dmd.flags |= CRYPT_ACTIVATE_READONLY;
if (snprintf(name, sizeof(name), "temporary-cryptsetup-%d", getpid()) < 0)
return -ENOMEM;
if (snprintf(path, sizeof(path), "%s/%s", dm_get_dir(), name) < 0)
return -ENOMEM;
if (snprintf(cipher_spec, sizeof(cipher_spec), "%s-%s", cipher, cipher_mode) < 0)
return -ENOMEM;
r = device_block_adjust(ctx, dmd.data_device, DEV_OK,
dmd.u.crypt.offset, &dmd.size, &dmd.flags);
if (r < 0) {
log_err(ctx, _("Device %s doesn't exist or access denied.\n"),
device_path(dmd.data_device));
return -EIO;
}
devfd = open(fullpath, mode | O_DIRECT | O_SYNC); /* devfd is a global var */
if(devfd == -1) {
if (mode != O_RDONLY && dmd.flags & CRYPT_ACTIVATE_READONLY) {
log_err(ctx, _("Cannot write to device %s, permission denied.\n"),
device_path(dmd.data_device));
return -EACCES;
}
r = dm_create_device(ctx, name, "TEMP", &dmd, 0);
if (r < 0) {
if (r != -EACCES && r != -ENOTSUP)
_error_hint(ctx, device_path(dmd.data_device),
cipher, cipher_mode, vk->keylength * 8);
return -EIO;
}
devfd = open(path, mode | O_DIRECT | O_SYNC);
if (devfd == -1) {
log_err(ctx, _("Failed to open temporary keystore device.\n"));
r = -EIO;
goto out2;
goto out;
}
r = func(devfd,src,srcLength);
if(r < 0) {
r = func(devfd, bsize, alignment, src, srcLength);
if (r < 0) {
log_err(ctx, _("Failed to access temporary keystore device.\n"));
r = -EIO;
goto out3;
}
r = 0;
out3:
close(devfd);
devfd = -1;
out2:
dm_remove_device(cleaner_name, 1, cleaner_size);
out1:
signal(SIGINT, SIG_DFL);
cleaner_name = NULL;
cleaner_size = 0;
free(dmCipherSpec);
free(fullpath);
free(name);
} else
r = 0;
out:
if (devfd != -1)
close(devfd);
dm_remove_device(ctx, name, CRYPT_DEACTIVATE_FORCE);
return r;
}
int LUKS_encrypt_to_storage(char *src, size_t srcLength,
struct luks_phdr *hdr,
const char *cipher,
const char *cipher_mode,
struct volume_key *vk,
const char *device,
unsigned int sector,
struct crypt_device *ctx)
{
return LUKS_endec_template(src,srcLength,hdr,vk, device,
sector, write_blockwise, O_RDWR, ctx);
struct device *device = crypt_metadata_device(ctx);
struct crypt_storage *s;
int devfd = -1, 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 */
devfd = device_open(device, O_RDWR);
if (devfd < 0)
goto out;
if (lseek(devfd, sector * SECTOR_SIZE, SEEK_SET) == -1 ||
write_blockwise(devfd, device_block_size(device),
device_alignment(device), src, srcLength) == -1)
goto out;
r = 0;
out:
if (devfd >= 0)
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,
struct luks_phdr *hdr,
const char *cipher,
const char *cipher_mode,
struct volume_key *vk,
const char *device,
unsigned int sector,
struct crypt_device *ctx)
{
return LUKS_endec_template(dst,dstLength,hdr,vk, device,
sector, read_blockwise, O_RDONLY, ctx);
struct device *device = crypt_metadata_device(ctx);
struct crypt_storage *s;
int devfd = -1, 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 */
devfd = device_open(device, O_RDONLY);
if (devfd < 0)
goto bad;
if (lseek(devfd, sector * SECTOR_SIZE, SEEK_SET) == -1 ||
read_blockwise(devfd, device_block_size(device),
device_alignment(device), 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 >= 0)
close(devfd);
log_err(ctx, _("IO error while decrypting keyslot.\n"));
crypt_storage_destroy(s);
return r;
}

File diff suppressed because it is too large Load Diff

View File

@@ -2,11 +2,12 @@
* LUKS - Linux Unified Key Setup
*
* Copyright (C) 2004-2006, Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2017, 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
* version 2 as published by the Free Software Foundation.
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -39,6 +40,9 @@
#define LUKS_MKD_ITERATIONS_MIN 1000
#define LUKS_SLOT_ITERATIONS_MIN 1000
// Iteration time for digest in ms
#define LUKS_MKD_ITERATIONS_MS 125
#define LUKS_KEY_DISABLED_OLD 0
#define LUKS_KEY_ENABLED_OLD 0xCAFE
@@ -51,8 +55,6 @@
#define LUKS_MAGIC {'L','U','K','S', 0xba, 0xbe};
#define LUKS_MAGIC_L 6
#define LUKS_PHDR_SIZE (sizeof(struct luks_phdr)/SECTOR_SIZE+1)
/* Actually we need only 37, but we don't want struct autoaligning to kick in */
#define UUID_STRING_L 40
@@ -63,6 +65,7 @@
converted */
struct volume_key;
struct device_backend;
struct luks_phdr {
char magic[LUKS_MAGIC_L];
@@ -106,13 +109,10 @@ int LUKS_generate_phdr(
unsigned int stripes,
unsigned int alignPayload,
unsigned int alignOffset,
uint32_t iteration_time_ms,
uint64_t *PBKDF2_per_sec,
const char *metadata_device,
int detached_metadata_device,
struct crypt_device *ctx);
int LUKS_read_phdr(
const char *device,
struct luks_phdr *hdr,
int require_luks_device,
int repair,
@@ -120,47 +120,37 @@ int LUKS_read_phdr(
int LUKS_read_phdr_backup(
const char *backup_file,
const char *device,
struct luks_phdr *hdr,
int require_luks_device,
struct crypt_device *ctx);
int LUKS_hdr_uuid_set(
const char *device,
struct luks_phdr *hdr,
const char *uuid,
struct crypt_device *ctx);
int LUKS_hdr_backup(
const char *backup_file,
const char *device,
struct luks_phdr *hdr,
struct crypt_device *ctx);
int LUKS_hdr_restore(
const char *backup_file,
const char *device,
struct luks_phdr *hdr,
struct crypt_device *ctx);
int LUKS_write_phdr(
const char *device,
struct luks_phdr *hdr,
struct crypt_device *ctx);
int LUKS_set_key(
const char *device,
unsigned int keyIndex,
const char *password,
size_t passwordLen,
struct luks_phdr *hdr,
struct volume_key *vk,
uint32_t iteration_time_ms,
uint64_t *PBKDF2_per_sec,
struct crypt_device *ctx);
int LUKS_open_key_with_hdr(
const char *device,
int keyIndex,
const char *password,
size_t passwordLen,
@@ -169,7 +159,6 @@ int LUKS_open_key_with_hdr(
struct crypt_device *ctx);
int LUKS_del_key(
const char *device,
unsigned int keyIndex,
struct luks_phdr *hdr,
struct crypt_device *ctx);
@@ -178,22 +167,12 @@ crypt_keyslot_info LUKS_keyslot_info(struct luks_phdr *hdr, int keyslot);
int LUKS_keyslot_find_empty(struct luks_phdr *hdr);
int LUKS_keyslot_active_count(struct luks_phdr *hdr);
int LUKS_keyslot_set(struct luks_phdr *hdr, int keyslot, int enable);
int LUKS_encrypt_to_storage(
char *src, size_t srcLength,
struct luks_phdr *hdr,
struct volume_key *vk,
const char *device,
unsigned int sector,
struct crypt_device *ctx);
int LUKS_decrypt_from_storage(
char *dst, size_t dstLength,
struct luks_phdr *hdr,
struct volume_key *vk,
const char *device,
unsigned int sector,
struct crypt_device *ctx);
int LUKS_keyslot_area(const struct luks_phdr *hdr,
int keyslot,
uint64_t *offset,
uint64_t *length);
size_t LUKS_device_sectors(const struct luks_phdr *hdr);
size_t LUKS_keyslots_offset(const struct luks_phdr *hdr);
int LUKS1_activate(struct crypt_device *cd,
const char *name,

View File

@@ -1,267 +0,0 @@
/*
* Implementation of Password-Based Cryptography as per PKCS#5
* Copyright (C) 2002,2003 Simon Josefsson
* Copyright (C) 2004 Free Software Foundation
*
* LUKS code
* Copyright (C) 2004, Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2009-2012, 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
* 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 <netinet/in.h>
#include <errno.h>
#include <signal.h>
#include <alloca.h>
#include <string.h>
#include <sys/time.h>
#include "crypto_backend.h"
#include "pbkdf.h"
static volatile uint64_t __PBKDF2_global_j = 0;
static volatile uint64_t __PBKDF2_performance = 0;
/*
* 5.2 PBKDF2
*
* PBKDF2 applies a pseudorandom function (see Appendix B.1 for an
* example) to derive keys. The length of the derived key is essentially
* unbounded. (However, the maximum effective search space for the
* derived key may be limited by the structure of the underlying
* pseudorandom function. See Appendix B.1 for further discussion.)
* PBKDF2 is recommended for new applications.
*
* PBKDF2 (P, S, c, dkLen)
*
* Options: PRF underlying pseudorandom function (hLen
* denotes the length in octets of the
* pseudorandom function output)
*
* Input: P password, an octet string (ASCII or UTF-8)
* S salt, an octet string
* c iteration count, a positive integer
* dkLen intended length in octets of the derived
* key, a positive integer, at most
* (2^32 - 1) * hLen
*
* Output: DK derived key, a dkLen-octet string
*/
#define MAX_PRF_BLOCK_LEN 80
static 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, int perfcheck)
{
struct crypt_hmac *hmac;
char U[MAX_PRF_BLOCK_LEN];
char T[MAX_PRF_BLOCK_LEN];
int i, k, rc = -EINVAL;
unsigned int u, hLen, l, r;
size_t tmplen = Slen + 4;
char *tmp;
tmp = alloca(tmplen);
if (tmp == NULL)
return -ENOMEM;
hLen = crypt_hmac_size(hash);
if (hLen == 0 || hLen > MAX_PRF_BLOCK_LEN)
return -EINVAL;
if (c == 0)
return -EINVAL;
if (dkLen == 0)
return -EINVAL;
/*
*
* Steps:
*
* 1. If dkLen > (2^32 - 1) * hLen, output "derived key too long" and
* stop.
*/
if (dkLen > 4294967295U)
return -EINVAL;
/*
* 2. Let l be the number of hLen-octet blocks in the derived key,
* rounding up, and let r be the number of octets in the last
* block:
*
* l = CEIL (dkLen / hLen) ,
* r = dkLen - (l - 1) * hLen .
*
* Here, CEIL (x) is the "ceiling" function, i.e. the smallest
* integer greater than, or equal to, x.
*/
l = dkLen / hLen;
if (dkLen % hLen)
l++;
r = dkLen - (l - 1) * hLen;
/*
* 3. For each block of the derived key apply the function F defined
* below to the password P, the salt S, the iteration count c, and
* the block index to compute the block:
*
* T_1 = F (P, S, c, 1) ,
* T_2 = F (P, S, c, 2) ,
* ...
* T_l = F (P, S, c, l) ,
*
* where the function F is defined as the exclusive-or sum of the
* first c iterates of the underlying pseudorandom function PRF
* applied to the password P and the concatenation of the salt S
* and the block index i:
*
* F (P, S, c, i) = U_1 \xor U_2 \xor ... \xor U_c
*
* where
*
* U_1 = PRF (P, S || INT (i)) ,
* U_2 = PRF (P, U_1) ,
* ...
* U_c = PRF (P, U_{c-1}) .
*
* Here, INT (i) is a four-octet encoding of the integer i, most
* significant octet first.
*
* 4. Concatenate the blocks and extract the first dkLen octets to
* produce a derived key DK:
*
* DK = T_1 || T_2 || ... || T_l<0..r-1>
*
* 5. Output the derived key DK.
*
* Note. The construction of the function F follows a "belt-and-
* suspenders" approach. The iterates U_i are computed recursively to
* remove a degree of parallelism from an opponent; they are exclusive-
* ored together to reduce concerns about the recursion degenerating
* into a small set of values.
*
*/
if (crypt_hmac_init(&hmac, hash, P, Plen))
return -EINVAL;
for (i = 1; (uint) i <= l; i++) {
memset(T, 0, hLen);
for (u = 1; u <= c ; u++) {
if (u == 1) {
memcpy(tmp, S, Slen);
tmp[Slen + 0] = (i & 0xff000000) >> 24;
tmp[Slen + 1] = (i & 0x00ff0000) >> 16;
tmp[Slen + 2] = (i & 0x0000ff00) >> 8;
tmp[Slen + 3] = (i & 0x000000ff) >> 0;
if (crypt_hmac_write(hmac, tmp, tmplen))
goto out;
} else {
if (crypt_hmac_write(hmac, U, hLen))
goto out;
}
if (crypt_hmac_final(hmac, U, hLen))
goto out;
for (k = 0; (uint) k < hLen; k++)
T[k] ^= U[k];
if (perfcheck && __PBKDF2_performance) {
rc = 0;
goto out;
}
if (perfcheck)
__PBKDF2_global_j++;
}
memcpy(DK + (i - 1) * hLen, T, (uint) i == l ? r : hLen);
}
rc = 0;
out:
crypt_hmac_destroy(hmac);
return rc;
}
int PBKDF2_HMAC(const char *hash,
const char *password, size_t passwordLen,
const char *salt, size_t saltLen, unsigned int iterations,
char *dKey, size_t dKeyLen)
{
return pkcs5_pbkdf2(hash, password, passwordLen, salt, saltLen,
iterations, (unsigned int)dKeyLen, dKey, 0);
}
int PBKDF2_HMAC_ready(const char *hash)
{
if (crypt_hmac_size(hash) < 20)
return -EINVAL;
return 1;
}
static void sigvtalarm(int foo __attribute__((unused)))
{
__PBKDF2_performance = __PBKDF2_global_j;
}
/* This code benchmarks PBKDF2 and returns iterations/second using wth specified hash */
int PBKDF2_performance_check(const char *hash, uint64_t *iter)
{
int timer_type, r;
char buf;
struct itimerval it;
if (__PBKDF2_global_j)
return -EBUSY;
if (PBKDF2_HMAC_ready(hash) < 0)
return -EINVAL;
/* If crypto backend is not implemented in userspace,
* but uses some kernel part, we must measure also time
* spent in kernel. */
if (crypt_backend_flags() & CRYPT_BACKEND_KERNEL) {
timer_type = ITIMER_PROF;
signal(SIGPROF,sigvtalarm);
} else {
timer_type = ITIMER_VIRTUAL;
signal(SIGVTALRM,sigvtalarm);
}
it.it_interval.tv_usec = 0;
it.it_interval.tv_sec = 0;
it.it_value.tv_usec = 0;
it.it_value.tv_sec = 1;
if (setitimer(timer_type, &it, NULL) < 0)
return -EINVAL;
r = pkcs5_pbkdf2(hash, "foo", 3, "bar", 3, ~(0U), 1, &buf, 1);
*iter = __PBKDF2_performance;
__PBKDF2_global_j = 0;
__PBKDF2_performance = 0;
return r;
}

23
lib/luks2/Makefile.am Normal file
View File

@@ -0,0 +1,23 @@
moduledir = $(libdir)/cryptsetup
noinst_LTLIBRARIES = libluks2.la
libluks2_la_CFLAGS = -Wall $(AM_CFLAGS) @CRYPTO_CFLAGS@
libluks2_la_SOURCES = \
luks2_disk_metadata.c \
luks2_json_format.c \
luks2_json_metadata.c \
luks2_luks1_convert.c \
luks2_digest.c \
luks2_digest_pbkdf2.c \
luks2_keyslot.c \
luks2_keyslot_luks2.c \
luks2_token_keyring.c \
luks2_token.c \
luks2_internal.h \
luks2.h
AM_CPPFLAGS = -include config.h \
-I$(top_srcdir)/lib \
-I$(top_srcdir)/lib/crypto_backend

353
lib/luks2/luks2.h Normal file
View File

@@ -0,0 +1,353 @@
/*
* LUKS - Linux Unified Key Setup v2
*
* Copyright (C) 2015-2017, Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2017, 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
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef _CRYPTSETUP_LUKS2_ONDISK_H
#define _CRYPTSETUP_LUKS2_ONDISK_H
#include <stdint.h>
#define LUKS2_MAGIC_1ST "LUKS\xba\xbe"
#define LUKS2_MAGIC_2ND "SKUL\xba\xbe"
#define LUKS2_MAGIC_L 6
#define LUKS2_UUID_L 40
#define LUKS2_LABEL_L 48
#define LUKS2_SALT_L 64
#define LUKS2_CHECKSUM_ALG_L 32
#define LUKS2_CHECKSUM_L 64
#define LUKS2_KEYSLOTS_MAX 32
#define LUKS2_TOKENS_MAX 32
#define LUKS2_BUILTIN_TOKEN_PREFIX "luks2-"
#define LUKS2_BUILTIN_TOKEN_PREFIX_LEN 6
#define LUKS2_TOKEN_KEYRING LUKS2_BUILTIN_TOKEN_PREFIX "keyring"
#define LUKS2_DIGEST_MAX 8
typedef int digests_t[LUKS2_DIGEST_MAX];
#define CRYPT_ANY_SEGMENT -1
#define CRYPT_DEFAULT_SEGMENT 0
#define CRYPT_DEFAULT_SEGMENT_STR "0"
/*
* LUKS2 header on-disk.
*
* Binary header is followed by JSON area.
* JSON area is followed by keyslot area and data area,
* these are described in JSON metadata.
*
* Note: uuid, csum_alg are intentionally on the same offset as LUKS1
* (checksum alg replaces hash in LUKS1)
*
* String (char) should be zero terminated.
* Padding should be wiped.
* Checksum is calculated with csum zeroed (+ full JSON area).
*/
struct luks2_hdr_disk {
char magic[LUKS2_MAGIC_L];
uint16_t version; /* Version 2 */
uint64_t hdr_size; /* in bytes, including JSON area */
uint64_t seqid; /* increased on every update */
char label[LUKS2_LABEL_L];
char checksum_alg[LUKS2_CHECKSUM_ALG_L];
uint8_t salt[LUKS2_SALT_L]; /* unique for every header/offset */
char uuid[LUKS2_UUID_L];
char subsystem[LUKS2_LABEL_L]; /* owner subsystem label */
uint64_t hdr_offset; /* offset from device start in bytes */
char _padding[184];
uint8_t csum[LUKS2_CHECKSUM_L];
char _padding4096[7*512];
/* JSON area starts here */
} __attribute__ ((packed));
/*
* LUKS2 header in-memory.
*/
typedef struct json_object json_object;
struct luks2_hdr {
size_t hdr_size;
uint64_t seqid;
unsigned int version;
char label[LUKS2_LABEL_L];
char subsystem[LUKS2_LABEL_L];
char checksum_alg[LUKS2_CHECKSUM_ALG_L];
uint8_t salt1[LUKS2_SALT_L];
uint8_t salt2[LUKS2_SALT_L];
char uuid[LUKS2_UUID_L];
json_object *jobj;
};
/*
* Supportable header sizes (hdr_disk + JSON area)
* Also used as offset for the 2nd header.
*/
#define LUKS2_HDR_16K_LEN 0x4000
#define LUKS2_HDR_BIN_LEN sizeof(struct luks2_hdr_disk)
#define LUKS2_HDR_DEFAULT_LEN 0x400000 /* 4 MiB */
#define LUKS2_MAX_KEYSLOTS_SIZE 0x8000000 /* 128 MiB */
int LUKS2_hdr_version_unlocked(struct crypt_device *cd);
int LUKS2_hdr_read(struct crypt_device *cd, struct luks2_hdr *hdr);
int LUKS2_hdr_write(struct crypt_device *cd, struct luks2_hdr *hdr);
int LUKS2_hdr_dump(struct crypt_device *cd, struct luks2_hdr *hdr);
int LUKS2_hdr_uuid(struct crypt_device *cd,
struct luks2_hdr *hdr,
const char *uuid);
int LUKS2_hdr_labels(struct crypt_device *cd,
struct luks2_hdr *hdr,
const char *label,
const char *subsystem,
int commit);
void LUKS2_hdr_free(struct luks2_hdr *hdr);
int LUKS2_hdr_backup(struct crypt_device *cd,
struct luks2_hdr *hdr,
const char *backup_file);
int LUKS2_hdr_restore(struct crypt_device *cd,
struct luks2_hdr *hdr,
const char *backup_file);
uint64_t LUKS2_hdr_and_areas_size(json_object *jobj);
uint64_t LUKS2_keyslots_size(json_object *jobj);
/*
* Generic LUKS2 keyslot
*/
int LUKS2_keyslot_open(struct crypt_device *cd,
int keyslot,
int segment,
const char *password,
size_t password_len,
struct volume_key **vk);
int LUKS2_keyslot_store(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot,
const char *password,
size_t password_len,
const struct volume_key *vk);
int LUKS2_keyslot_wipe(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot,
int wipe_area_only);
int LUKS2_keyslot_dump(struct crypt_device *cd,
int keyslot);
crypt_keyslot_priority LUKS2_keyslot_priority_get(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot);
int LUKS2_keyslot_priority_set(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot,
crypt_keyslot_priority priority,
int commit);
/*
* Generic LUKS2 token
*/
int LUKS2_token_json_get(struct crypt_device *cd,
struct luks2_hdr *hdr,
int token,
const char **json);
int LUKS2_token_assign(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot,
int token,
int assign,
int commit);
int LUKS2_token_create(struct crypt_device *cd,
struct luks2_hdr *hdr,
int token,
const char *json,
int commit);
crypt_token_info LUKS2_token_status(struct crypt_device *cd,
struct luks2_hdr *hdr,
int token,
const char **type);
int LUKS2_builtin_token_get(struct crypt_device *cd,
struct luks2_hdr *hdr,
int token,
const char *type,
void *params);
int LUKS2_builtin_token_create(struct crypt_device *cd,
struct luks2_hdr *hdr,
int token,
const char *type,
const void *params,
int commit);
int LUKS2_token_open_and_activate(struct crypt_device *cd,
struct luks2_hdr *hdr,
int token,
const char *name,
uint32_t flags,
void *usrptr);
int LUKS2_token_open_and_activate_any(struct crypt_device *cd,
struct luks2_hdr *hdr,
const char *name,
uint32_t flags);
/*
* Generic LUKS2 digest
*/
int LUKS2_digests_verify_by_segment(struct crypt_device *cd,
struct luks2_hdr *hdr,
int segment,
const struct volume_key *vk,
digests_t digests);
void LUKS2_digests_erase_unused(struct crypt_device *cd,
struct luks2_hdr *hdr);
int LUKS2_digest_verify(struct crypt_device *cd,
struct luks2_hdr *hdr,
struct volume_key *vk,
int keyslot);
int LUKS2_digest_dump(struct crypt_device *cd,
int digest);
int LUKS2_digest_json_get(struct crypt_device *cd,
struct luks2_hdr *hdr,
int digest,
const char **json);
int LUKS2_digest_json_set(struct crypt_device *cd,
struct luks2_hdr *hdr,
int digest,
const char *json);
int LUKS2_digests_assign(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot,
digests_t digests,
int assign,
int commit);
int LUKS2_digest_assign(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot,
int digest,
int assign,
int commit);
int LUKS2_digest_segment_assign(struct crypt_device *cd,
struct luks2_hdr *hdr,
int segment,
int digest,
int assign,
int commit);
int LUKS2_digests_by_keyslot(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot,
digests_t digests);
int LUKS2_digest_create(struct crypt_device *cd,
const char *type,
struct luks2_hdr *hdr,
const struct volume_key *vk);
/*
* LUKS2 generic
*/
int LUKS2_activate(struct crypt_device *cd,
const char *name,
struct volume_key *vk,
uint32_t flags);
int LUKS2_keyslot_luks2_format(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot,
const char *cipher,
size_t keylength);
int LUKS2_generate_hdr(
struct crypt_device *cd,
struct luks2_hdr *hdr,
const struct volume_key *vk,
const char *cipherName,
const char *cipherMode,
const char *integrity,
const char *uuid,
unsigned int sector_size,
unsigned int alignPayload,
unsigned int alignOffset,
int detached_metadata_device);
uint64_t LUKS2_get_data_offset(struct luks2_hdr *hdr);
int LUKS2_get_sector_size(struct luks2_hdr *hdr);
const char *LUKS2_get_cipher(struct luks2_hdr *hdr, int segment);
const char *LUKS2_get_integrity(struct luks2_hdr *hdr, int segment);
int LUKS2_get_volume_key_size(struct luks2_hdr *hdr, int segment);
int LUKS2_get_keyslot_key_size(struct luks2_hdr *hdr, int keyslot);
int LUKS2_keyslot_find_empty(struct luks2_hdr *hdr, const char *type);
int LUKS2_keyslot_active_count(struct luks2_hdr *hdr, int segment);
int LUKS2_keyslot_for_segment(struct luks2_hdr *hdr, int keyslot, int segment);
crypt_keyslot_info LUKS2_keyslot_info(struct luks2_hdr *hdr, int keyslot);
int LUKS2_keyslot_area(struct luks2_hdr *hdr,
int keyslot,
uint64_t *offset,
uint64_t *length);
/*
* Permanent activation flags stored in header
*/
int LUKS2_config_get_flags(struct crypt_device *cd, struct luks2_hdr *hdr, uint32_t *flags);
int LUKS2_config_set_flags(struct crypt_device *cd, struct luks2_hdr *hdr, uint32_t flags);
/*
* Requirements for device activation or header modification
*/
int LUKS2_config_get_requirements(struct crypt_device *cd, struct luks2_hdr *hdr, uint32_t *reqs);
int LUKS2_config_set_requirements(struct crypt_device *cd, struct luks2_hdr *hdr, uint32_t reqs);
int LUKS2_unmet_requirements(struct crypt_device *cd, struct luks2_hdr *hdr, uint32_t reqs_mask, int quiet);
int crypt_use_keyring_for_vk(const struct crypt_device *cd);
int crypt_volume_key_load_in_keyring(struct crypt_device *cd, struct volume_key *vk);
struct luks_phdr;
int LUKS2_luks1_to_luks2(struct crypt_device *cd,
struct luks_phdr *hdr1,
struct luks2_hdr *hdr2);
int LUKS2_luks2_to_luks1(struct crypt_device *cd,
struct luks2_hdr *hdr2,
struct luks_phdr *hdr1);
#endif

391
lib/luks2/luks2_digest.c Normal file
View File

@@ -0,0 +1,391 @@
/*
* LUKS - Linux Unified Key Setup v2, digest handling
*
* Copyright (C) 2015-2017, Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2017, 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
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "luks2_internal.h"
extern const digest_handler PBKDF2_digest;
static const digest_handler *digest_handlers[LUKS2_DIGEST_MAX] = {
&PBKDF2_digest,
NULL
};
int crypt_digest_register(const digest_handler *handler)
{
int i;
for (i = 0; i < LUKS2_DIGEST_MAX && digest_handlers[i]; i++) {
if (!strcmp(digest_handlers[i]->name, handler->name))
return -EINVAL;
}
if (i == LUKS2_DIGEST_MAX)
return -EINVAL;
digest_handlers[i] = handler;
return 0;
}
const digest_handler *LUKS2_digest_handler_type(struct crypt_device *cd, const char *type)
{
int i;
for (i = 0; i < LUKS2_DIGEST_MAX && digest_handlers[i]; i++) {
if (!strcmp(digest_handlers[i]->name, type))
return digest_handlers[i];
}
return NULL;
}
static const digest_handler *LUKS2_digest_handler(struct crypt_device *cd, int digest)
{
struct luks2_hdr *hdr;
json_object *jobj1, *jobj2;
if (digest < 0)
return NULL;
if (!(hdr = crypt_get_hdr(cd, CRYPT_LUKS2)))
return NULL;
if (!(jobj1 = LUKS2_get_digest_jobj(hdr, digest)))
return NULL;
if (!json_object_object_get_ex(jobj1, "type", &jobj2))
return NULL;
return LUKS2_digest_handler_type(cd, json_object_get_string(jobj2));
}
static int LUKS2_digest_find_free(struct crypt_device *cd, struct luks2_hdr *hdr)
{
int digest = 0;
while (LUKS2_get_digest_jobj(hdr, digest) && digest < LUKS2_DIGEST_MAX)
digest++;
return digest < LUKS2_DIGEST_MAX ? digest : -1;
}
int LUKS2_digest_create(struct crypt_device *cd,
const char *type,
struct luks2_hdr *hdr,
const struct volume_key *vk)
{
int digest;
const digest_handler *dh;
dh = LUKS2_digest_handler_type(cd, type);
if (!dh)
return -EINVAL;
digest = LUKS2_digest_find_free(cd, hdr);
if (digest < 0)
return -EINVAL;
log_dbg("Creating new digest %d (%s).", digest, type);
return dh->store(cd, digest, vk->key, vk->keylength) ?: digest;
}
int LUKS2_digests_by_keyslot(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot,
digests_t digests)
{
char keyslot_name[16];
int i = 0;
json_object *jobj_digests, *jobj_digest_keyslots;
if (snprintf(keyslot_name, sizeof(keyslot_name), "%u", keyslot) < 1)
return -ENOMEM;
json_object_object_get_ex(hdr->jobj, "digests", &jobj_digests);
json_object_object_foreach(jobj_digests, key, val) {
json_object_object_get_ex(val, "keyslots", &jobj_digest_keyslots);
if (LUKS2_array_jobj(jobj_digest_keyslots, keyslot_name))
digests[i++] = atoi(key);
}
if (i < LUKS2_DIGEST_MAX)
digests[i] = -1;
return i ? 0 : -ENOENT;
}
int LUKS2_digest_verify(struct crypt_device *cd,
struct luks2_hdr *hdr,
struct volume_key *vk,
int keyslot)
{
const digest_handler *h;
digests_t digests;
int i, r;
r = LUKS2_digests_by_keyslot(cd, hdr, keyslot, digests);
if (r == -ENOENT)
return 0;
if (r < 0)
return r;
for (i = 0; i < LUKS2_DIGEST_MAX && digests[i] != -1 ; i++) {
log_dbg("Verifying key from keyslot %d, digest %d.",
keyslot, digests[i]);
h = LUKS2_digest_handler(cd, digests[i]);
if (!h)
return -EINVAL;
r = h->verify(cd, digests[i], vk->key, vk->keylength);
if (r < 0) {
log_dbg("Digest %d (%s) verify failed with %d.",
digests[i], h->name, r);
return r;
}
}
return 0;
}
int LUKS2_digest_dump(struct crypt_device *cd, int digest)
{
const digest_handler *h;
if (!(h = LUKS2_digest_handler(cd, digest)))
return -EINVAL;
return h->dump(cd, digest);
}
int LUKS2_digests_verify_by_segment(struct crypt_device *cd,
struct luks2_hdr *hdr,
int segment,
const struct volume_key *vk,
digests_t digests)
{
char segment_name[16];
const digest_handler *h;
json_object *jobj_digests, *jobj_digest_segments;
int digest, r, i = 0;
json_object_object_get_ex(hdr->jobj, "digests", &jobj_digests);
if (snprintf(segment_name, sizeof(segment_name), "%u", segment) < 1)
return -EINVAL;
json_object_object_foreach(jobj_digests, key, val) {
json_object_object_get_ex(val, "segments", &jobj_digest_segments);
if (!LUKS2_array_jobj(jobj_digest_segments, segment_name))
continue;
digest = atoi(key);
log_dbg("Verifying key digest %d.", digest);
h = LUKS2_digest_handler(cd, digest);
if (!h)
return -EINVAL;
r = h->verify(cd, digest, vk->key, vk->keylength);
if (r < 0) {
log_dbg("Digest %d (%s) verify failed with %d.", digest, h->name, r);
return r;
}
if (digests)
digests[i] = digest;
i++;
}
if (digests && i < LUKS2_DIGEST_MAX)
digests[i] = -1;
return i ? 0 : -ENOENT;
}
int LUKS2_digest_json_get(struct crypt_device *cd, struct luks2_hdr *hdr,
int digest, const char **json)
{
json_object *jobj_digest;
jobj_digest = LUKS2_get_digest_jobj(hdr, digest);
if (!jobj_digest)
return -EINVAL;
*json = json_object_to_json_string_ext(jobj_digest, JSON_C_TO_STRING_PLAIN);
return 0;
}
static int assign_one_digest(struct crypt_device *cd, struct luks2_hdr *hdr,
int keyslot, int digest, int assign)
{
json_object *jobj1, *jobj_digest, *jobj_digest_keyslots;
char num[16];
log_dbg("Keyslot %i %s digest %i.", keyslot, assign ? "assigned to" : "unassigned from", digest);
jobj_digest = LUKS2_get_digest_jobj(hdr, digest);
if (!jobj_digest)
return -EINVAL;
json_object_object_get_ex(jobj_digest, "keyslots", &jobj_digest_keyslots);
if (!jobj_digest_keyslots)
return -EINVAL;
snprintf(num, sizeof(num), "%d", keyslot);
if (assign) {
jobj1 = LUKS2_array_jobj(jobj_digest_keyslots, num);
if (!jobj1)
json_object_array_add(jobj_digest_keyslots, json_object_new_string(num));
} else {
jobj1 = LUKS2_array_remove(jobj_digest_keyslots, num);
if (jobj1)
json_object_object_add(jobj_digest, "keyslots", jobj1);
}
return 0;
}
int LUKS2_digests_assign(struct crypt_device *cd, struct luks2_hdr *hdr,
int keyslot, digests_t digests, int assign, int commit)
{
int i, r;
for (i = 0; i < LUKS2_DIGEST_MAX && digests[i] != -1; i++) {
r = LUKS2_digest_assign(cd, hdr, keyslot, digests[i], assign, 0);
if (r < 0)
return r;
}
return commit ? LUKS2_hdr_write(cd, hdr) : 0;
}
int LUKS2_digest_assign(struct crypt_device *cd, struct luks2_hdr *hdr,
int keyslot, int digest, int assign, int commit)
{
json_object *jobj_digests;
int r = 0;
if (digest == CRYPT_ANY_DIGEST) {
json_object_object_get_ex(hdr->jobj, "digests", &jobj_digests);
json_object_object_foreach(jobj_digests, key, val) {
UNUSED(val);
r = assign_one_digest(cd, hdr, keyslot, atoi(key), assign);
if (r < 0)
break;
}
} else
r = assign_one_digest(cd, hdr, keyslot, digest, assign);
if (r < 0)
return r;
// FIXME: do not write header in nothing changed
return commit ? LUKS2_hdr_write(cd, hdr) : 0;
}
static int assign_one_segment(struct crypt_device *cd, struct luks2_hdr *hdr,
int segment, int digest, int assign)
{
json_object *jobj1, *jobj_digest, *jobj_digest_segments;
char num[16];
log_dbg("Segment %i %s digest %i.", segment, assign ? "assigned to" : "unassigned from", digest);
jobj_digest = LUKS2_get_digest_jobj(hdr, digest);
if (!jobj_digest)
return -EINVAL;
json_object_object_get_ex(jobj_digest, "segments", &jobj_digest_segments);
if (!jobj_digest_segments)
return -EINVAL;
snprintf(num, sizeof(num), "%d", segment);
if (assign) {
jobj1 = LUKS2_array_jobj(jobj_digest_segments, num);
if (!jobj1)
json_object_array_add(jobj_digest_segments, json_object_new_string(num));
} else {
jobj1 = LUKS2_array_remove(jobj_digest_segments, num);
if (jobj1)
json_object_object_add(jobj_digest, "segments", jobj1);
}
return 0;
}
int LUKS2_digest_segment_assign(struct crypt_device *cd, struct luks2_hdr *hdr,
int segment, int digest, int assign, int commit)
{
json_object *jobj_digests;
int r = 0;
if (digest == CRYPT_ANY_DIGEST) {
json_object_object_get_ex(hdr->jobj, "digests", &jobj_digests);
json_object_object_foreach(jobj_digests, key, val) {
UNUSED(val);
r = assign_one_segment(cd, hdr, segment, atoi(key), assign);
if (r < 0)
break;
}
} else
r = assign_one_segment(cd, hdr, segment, digest, assign);
if (r < 0)
return r;
// FIXME: do not write header in nothing changed
return commit ? LUKS2_hdr_write(cd, hdr) : 0;
}
static int digest_unused(json_object *jobj_digest)
{
json_object *jobj;
json_object_object_get_ex(jobj_digest, "segments", &jobj);
if (!jobj || !json_object_is_type(jobj, json_type_array) || json_object_array_length(jobj))
return 0;
json_object_object_get_ex(jobj_digest, "keyslots", &jobj);
if (!jobj || !json_object_is_type(jobj, json_type_array))
return 0;
return json_object_array_length(jobj) ? 0 : 1;
}
void LUKS2_digests_erase_unused(struct crypt_device *cd,
struct luks2_hdr *hdr)
{
json_object *jobj_digests;
json_object_object_get_ex(hdr->jobj, "digests", &jobj_digests);
if (!jobj_digests || !json_object_is_type(jobj_digests, json_type_object))
return;
json_object_object_foreach(jobj_digests, key, val) {
if (digest_unused(val)) {
log_dbg("Erasing unused digest %d.", atoi(key));
json_object_object_del(jobj_digests, key);
}
}
}

View File

@@ -0,0 +1,197 @@
/*
* LUKS - Linux Unified Key Setup v2, PBKDF2 digest handler (LUKS1 compatible)
*
* Copyright (C) 2015-2017, Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2017, 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
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "luks2_internal.h"
#define LUKS_DIGESTSIZE 20 // since SHA1
#define LUKS_SALTSIZE 32
#define LUKS_MKD_ITERATIONS_MS 125
static int PBKDF2_digest_verify(struct crypt_device *cd,
int digest,
const char *volume_key,
size_t volume_key_len)
{
char checkHashBuf[64];
json_object *jobj_digest, *jobj1;
const char *hashSpec;
char *mkDigest = NULL, mkDigestSalt[LUKS_SALTSIZE];
unsigned int mkDigestIterations;
size_t len;
int r;
/* This can be done only for internally linked digests */
jobj_digest = LUKS2_get_digest_jobj(crypt_get_hdr(cd, CRYPT_LUKS2), digest);
if (!jobj_digest)
return -EINVAL;
if (!json_object_object_get_ex(jobj_digest, "hash", &jobj1))
return -EINVAL;
hashSpec = json_object_get_string(jobj1);
if (!json_object_object_get_ex(jobj_digest, "iterations", &jobj1))
return -EINVAL;
mkDigestIterations = json_object_get_int64(jobj1);
if (!json_object_object_get_ex(jobj_digest, "salt", &jobj1))
return -EINVAL;
len = sizeof(mkDigestSalt);
if (!base64_decode(json_object_get_string(jobj1),
json_object_get_string_len(jobj1), mkDigestSalt, &len))
return -EINVAL;
if (len != LUKS_SALTSIZE)
return -EINVAL;
if (!json_object_object_get_ex(jobj_digest, "digest", &jobj1))
return -EINVAL;
len = 0;
if (!base64_decode_alloc(json_object_get_string(jobj1),
json_object_get_string_len(jobj1), &mkDigest, &len))
return -EINVAL;
if (len < LUKS_DIGESTSIZE ||
len > sizeof(checkHashBuf) ||
(len != LUKS_DIGESTSIZE && len != (size_t)crypt_hash_size(hashSpec))) {
free(mkDigest);
return -EINVAL;
}
r = -EPERM;
if (crypt_pbkdf(CRYPT_KDF_PBKDF2, hashSpec, volume_key, volume_key_len,
mkDigestSalt, LUKS_SALTSIZE,
checkHashBuf, len,
mkDigestIterations, 0, 0) < 0) {
r = -EINVAL;
} else {
if (memcmp(checkHashBuf, mkDigest, len) == 0)
r = 0;
}
free(mkDigest);
return r;
}
static int PBKDF2_digest_store(struct crypt_device *cd,
int digest,
const char *volume_key,
size_t volume_key_len)
{
json_object *jobj_digest, *jobj_digests;
char salt[LUKS_SALTSIZE], digest_raw[128], num[16];
int r;
char *base64_str;
struct luks2_hdr *hdr;
struct crypt_pbkdf_type pbkdf = {
.type = CRYPT_KDF_PBKDF2,
.hash = "sha256",
.time_ms = LUKS_MKD_ITERATIONS_MS,
};
log_dbg("Setting PBKDF2 type key digest %d.", digest);
r = crypt_random_get(cd, salt, LUKS_SALTSIZE, CRYPT_RND_SALT);
if (r < 0)
return r;
if (crypt_get_pbkdf(cd)->flags & CRYPT_PBKDF_NO_BENCHMARK)
pbkdf.iterations = MIN_PBKDF2_ITERATIONS;
else {
r = crypt_benchmark_pbkdf_internal(cd, &pbkdf, volume_key_len);
if (r < 0)
return r;
}
r = crypt_pbkdf(CRYPT_KDF_PBKDF2, pbkdf.hash, volume_key, volume_key_len,
salt, LUKS_SALTSIZE, digest_raw, crypt_hmac_size(pbkdf.hash),
pbkdf.iterations, 0, 0);
if (r < 0)
return r;
jobj_digest = LUKS2_get_digest_jobj(crypt_get_hdr(cd, CRYPT_LUKS2), digest);
jobj_digests = NULL;
if (!jobj_digest) {
hdr = crypt_get_hdr(cd, CRYPT_LUKS2);
jobj_digest = json_object_new_object();
json_object_object_get_ex(hdr->jobj, "digests", &jobj_digests);
}
json_object_object_add(jobj_digest, "type", json_object_new_string("pbkdf2"));
json_object_object_add(jobj_digest, "keyslots", json_object_new_array());
json_object_object_add(jobj_digest, "segments", json_object_new_array());
json_object_object_add(jobj_digest, "hash", json_object_new_string(pbkdf.hash));
json_object_object_add(jobj_digest, "iterations", json_object_new_int(pbkdf.iterations));
base64_encode_alloc(salt, LUKS_SALTSIZE, &base64_str);
if (!base64_str) {
json_object_put(jobj_digest);
return -ENOMEM;
}
json_object_object_add(jobj_digest, "salt", json_object_new_string(base64_str));
free(base64_str);
base64_encode_alloc(digest_raw, crypt_hmac_size(pbkdf.hash), &base64_str);
if (!base64_str) {
json_object_put(jobj_digest);
return -ENOMEM;
}
json_object_object_add(jobj_digest, "digest", json_object_new_string(base64_str));
free(base64_str);
if (jobj_digests) {
snprintf(num, sizeof(num), "%d", digest);
json_object_object_add(jobj_digests, num, jobj_digest);
}
JSON_DBG(jobj_digest, "Digest JSON");
return 0;
}
static int PBKDF2_digest_dump(struct crypt_device *cd, int digest)
{
json_object *jobj_digest, *jobj1;
/* This can be done only for internally linked digests */
jobj_digest = LUKS2_get_digest_jobj(crypt_get_hdr(cd, CRYPT_LUKS2), digest);
if (!jobj_digest)
return -EINVAL;
json_object_object_get_ex(jobj_digest, "hash", &jobj1);
log_std(cd, "\tHash: %s\n", json_object_get_string(jobj1));
json_object_object_get_ex(jobj_digest, "iterations", &jobj1);
log_std(cd, "\tIterations: %" PRIu64 "\n", json_object_get_int64(jobj1));
json_object_object_get_ex(jobj_digest, "salt", &jobj1);
log_std(cd, "\tSalt: ");
hexprint_base64(cd, jobj1, " ", " ");
json_object_object_get_ex(jobj_digest, "digest", &jobj1);
log_std(cd, "\tDigest: ");
hexprint_base64(cd, jobj1, " ", " ");
return 0;
}
const digest_handler PBKDF2_digest = {
.name = "pbkdf2",
.verify = PBKDF2_digest_verify,
.store = PBKDF2_digest_store,
.dump = PBKDF2_digest_dump,
};

View File

@@ -0,0 +1,699 @@
/*
* LUKS - Linux Unified Key Setup v2
*
* Copyright (C) 2015-2017, Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2017, 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
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <assert.h>
#include "luks2_internal.h"
/*
* Helper functions
*/
json_object *parse_json_len(const char *json_area, int length, int *end_offset)
{
json_object *jobj;
struct json_tokener *jtok;
if (!json_area || length <= 0)
return NULL;
jtok = json_tokener_new();
if (!jtok) {
log_dbg("ERROR: Failed to init json tokener");
return NULL;
}
jobj = json_tokener_parse_ex(jtok, json_area, length);
if (!jobj)
log_dbg("ERROR: Failed to parse json data (%d): %s",
json_tokener_get_error(jtok),
json_tokener_error_desc(json_tokener_get_error(jtok)));
else
*end_offset = jtok->char_offset;
json_tokener_free(jtok);
return jobj;
}
static void log_dbg_checksum(const uint8_t *csum, const char *csum_alg, const char *info)
{
char csum_txt[2*LUKS2_CHECKSUM_L+1];
int i;
for (i = 0; i < crypt_hash_size(csum_alg); i++)
snprintf(&csum_txt[i*2], 3, "%02hhx", (const char)csum[i]);
csum_txt[i*2+1] = '\0'; /* Just to be safe, sprintf should write \0 there. */
log_dbg("Checksum:%s (%s)", &csum_txt[0], info);
}
/*
* Calculate hash (checksum) of |LUKS2_bin|LUKS2_JSON_area| from in-memory structs.
* LUKS2 on-disk header contains uniques salt both for primary and secondary header.
* Checksum is always calculated with zeroed checksum field in binary header.
*/
static int hdr_checksum_calculate(const char *alg, struct luks2_hdr_disk *hdr_disk,
const char *json_area, size_t json_len)
{
struct crypt_hash *hd = NULL;
int r;
if (crypt_hash_size(alg) <= 0 || crypt_hash_init(&hd, alg))
return -EINVAL;
/* Binary header, csum zeroed. */
r = crypt_hash_write(hd, (char*)hdr_disk, LUKS2_HDR_BIN_LEN);
/* JSON area (including unused space) */
if (!r)
r = crypt_hash_write(hd, json_area, json_len);
if (!r)
r = crypt_hash_final(hd, (char*)hdr_disk->csum, crypt_hash_size(alg));
crypt_hash_destroy(hd);
return r;
}
/*
* Compare hash (checksum) of on-disk and in-memory header.
*/
static int hdr_checksum_check(const char *alg, struct luks2_hdr_disk *hdr_disk,
const char *json_area, size_t json_len)
{
struct luks2_hdr_disk hdr_tmp;
int r;
if (crypt_hash_size(alg) <= 0)
return -EINVAL;
/* Copy header and zero checksum. */
memcpy(&hdr_tmp, hdr_disk, LUKS2_HDR_BIN_LEN);
memset(&hdr_tmp.csum, 0, sizeof(hdr_tmp.csum));
r = hdr_checksum_calculate(alg, &hdr_tmp, json_area, json_len);
if (r < 0)
return r;
log_dbg_checksum(hdr_disk->csum, alg, "on-disk");
log_dbg_checksum(hdr_tmp.csum, alg, "in-memory");
if (memcmp(hdr_tmp.csum, hdr_disk->csum, crypt_hash_size(alg)))
return -EINVAL;
return 0;
}
/*
* Convert header from on-disk format to in-memory struct
*/
static void hdr_from_disk(struct luks2_hdr_disk *hdr_disk1,
struct luks2_hdr_disk *hdr_disk2,
struct luks2_hdr *hdr,
int secondary)
{
hdr->version = be16_to_cpu(hdr_disk1->version);
hdr->hdr_size = be64_to_cpu(hdr_disk1->hdr_size);
hdr->seqid = be64_to_cpu(hdr_disk1->seqid);
memcpy(hdr->label, hdr_disk1->label, LUKS2_LABEL_L);
hdr->label[LUKS2_LABEL_L - 1] = '\0';
memcpy(hdr->subsystem, hdr_disk1->subsystem, LUKS2_LABEL_L);
hdr->subsystem[LUKS2_LABEL_L - 1] = '\0';
memcpy(hdr->checksum_alg, hdr_disk1->checksum_alg, LUKS2_CHECKSUM_ALG_L);
hdr->checksum_alg[LUKS2_CHECKSUM_ALG_L - 1] = '\0';
memcpy(hdr->uuid, hdr_disk1->uuid, LUKS2_UUID_L);
hdr->uuid[LUKS2_UUID_L - 1] = '\0';
if (secondary) {
memcpy(hdr->salt1, hdr_disk2->salt, LUKS2_SALT_L);
memcpy(hdr->salt2, hdr_disk1->salt, LUKS2_SALT_L);
} else {
memcpy(hdr->salt1, hdr_disk1->salt, LUKS2_SALT_L);
memcpy(hdr->salt2, hdr_disk2->salt, LUKS2_SALT_L);
}
}
/*
* Convert header from in-memory struct to on-disk format
*/
static void hdr_to_disk(struct luks2_hdr *hdr,
struct luks2_hdr_disk *hdr_disk,
int secondary, uint64_t offset)
{
assert(((char*)&(hdr_disk->_padding4096) - (char*)&(hdr_disk->magic)) == 512);
memset(hdr_disk, 0, LUKS2_HDR_BIN_LEN);
memcpy(&hdr_disk->magic, secondary ? LUKS2_MAGIC_2ND : LUKS2_MAGIC_1ST, LUKS2_MAGIC_L);
hdr_disk->version = cpu_to_be16(hdr->version);
hdr_disk->hdr_size = cpu_to_be64(hdr->hdr_size);
hdr_disk->hdr_offset = cpu_to_be64(offset);
hdr_disk->seqid = cpu_to_be64(hdr->seqid);
strncpy(hdr_disk->label, hdr->label, LUKS2_LABEL_L);
hdr_disk->label[LUKS2_LABEL_L - 1] = '\0';
strncpy(hdr_disk->subsystem, hdr->subsystem, LUKS2_LABEL_L);
hdr_disk->subsystem[LUKS2_LABEL_L - 1] = '\0';
strncpy(hdr_disk->checksum_alg, hdr->checksum_alg, LUKS2_CHECKSUM_ALG_L);
hdr_disk->checksum_alg[LUKS2_CHECKSUM_ALG_L - 1] = '\0';
strncpy(hdr_disk->uuid, hdr->uuid, LUKS2_UUID_L);
hdr_disk->uuid[LUKS2_UUID_L - 1] = '\0';
memcpy(hdr_disk->salt, secondary ? hdr->salt2 : hdr->salt1, LUKS2_SALT_L);
}
/*
* Sanity checks before checkum is validated
*/
static int hdr_disk_sanity_check_pre(struct luks2_hdr_disk *hdr,
size_t *hdr_json_size, int secondary,
uint64_t offset)
{
if (memcmp(hdr->magic, secondary ? LUKS2_MAGIC_2ND : LUKS2_MAGIC_1ST, LUKS2_MAGIC_L))
return -EINVAL;
if (be16_to_cpu(hdr->version) != 2) {
log_dbg("Unsupported LUKS2 header version %u.", be16_to_cpu(hdr->version));
return -EINVAL;
}
if (offset != be64_to_cpu(hdr->hdr_offset)) {
log_dbg("LUKS2 offset 0x%04x on device differs to expected offset 0x%04x.",
(unsigned)be64_to_cpu(hdr->hdr_offset), (unsigned)offset);
return -EINVAL;
}
/* FIXME: sanity check checksum alg. */
log_dbg("LUKS2 header version %u of size %u bytes, checksum %s.",
(unsigned)be16_to_cpu(hdr->version), (unsigned)be64_to_cpu(hdr->hdr_size),
hdr->checksum_alg);
*hdr_json_size = be64_to_cpu(hdr->hdr_size) - LUKS2_HDR_BIN_LEN;
return 0;
}
/*
* Read LUKS2 header from disk at specific offset.
*/
static int hdr_read_disk(struct device *device, struct luks2_hdr_disk *hdr_disk,
char **json_area, uint64_t offset, int secondary)
{
size_t hdr_json_size = 0;
int devfd = -1, r;
log_dbg("Trying to read %s LUKS2 header at offset %" PRIu64 ".",
secondary ? "secondary" : "primary", offset);
devfd = device_open_locked(device, O_RDONLY);
if (devfd < 0)
return devfd == -1 ? -EIO : devfd;
/*
* Read binary header and run sanity check before reading
* JSON area and validating checksum.
*/
if (read_lseek_blockwise(devfd, device_block_size(device),
device_alignment(device), hdr_disk,
LUKS2_HDR_BIN_LEN, offset) != LUKS2_HDR_BIN_LEN) {
close(devfd);
return -EIO;
}
r = hdr_disk_sanity_check_pre(hdr_disk, &hdr_json_size, secondary, offset);
if (r < 0) {
close(devfd);
return r;
}
/*
* Allocate and read JSON area. Always the whole area must be read.
*/
*json_area = malloc(hdr_json_size);
if (!*json_area) {
close(devfd);
return -ENOMEM;
}
if (read_lseek_blockwise(devfd, device_block_size(device),
device_alignment(device), *json_area, hdr_json_size,
offset + LUKS2_HDR_BIN_LEN) != (ssize_t)hdr_json_size) {
close(devfd);
free(*json_area);
*json_area = NULL;
return -EIO;
}
close(devfd);
/*
* Calculate and validate checksum and zero it afterwards.
*/
if (hdr_checksum_check(hdr_disk->checksum_alg, hdr_disk,
*json_area, hdr_json_size)) {
log_dbg("LUKS2 header checksum error (offset %" PRIu64 ").", offset);
r = -EINVAL;
}
memset(hdr_disk->csum, 0, LUKS2_CHECKSUM_L);
return r;
}
/*
* Write LUKS2 header to disk at specific offset.
*/
static int hdr_write_disk(struct device *device, struct luks2_hdr *hdr,
const char *json_area, int secondary)
{
struct luks2_hdr_disk hdr_disk;
uint64_t offset = secondary ? hdr->hdr_size : 0;
size_t hdr_json_len;
int devfd = -1, r;
log_dbg("Trying to write LUKS2 header (%zu bytes) at offset %" PRIu64 ".",
hdr->hdr_size, offset);
/* FIXME: read-only device silent fail? */
devfd = device_open_locked(device, O_RDWR);
if (devfd < 0)
return devfd == -1 ? -EINVAL : devfd;
hdr_json_len = hdr->hdr_size - LUKS2_HDR_BIN_LEN;
hdr_to_disk(hdr, &hdr_disk, secondary, offset);
/*
* Write header without checksum but with proper seqid.
*/
if (write_lseek_blockwise(devfd, device_block_size(device),
device_alignment(device), (char *)&hdr_disk,
LUKS2_HDR_BIN_LEN, offset) < (ssize_t)LUKS2_HDR_BIN_LEN) {
close(devfd);
return -EIO;
}
/*
* Write json area.
*/
if (write_lseek_blockwise(devfd, device_block_size(device),
device_alignment(device),
CONST_CAST(char*)json_area, hdr_json_len,
LUKS2_HDR_BIN_LEN + offset) < (ssize_t)hdr_json_len) {
close(devfd);
return -EIO;
}
/*
* Calculate checksum and write header with checkum.
*/
r = hdr_checksum_calculate(hdr_disk.checksum_alg, &hdr_disk,
json_area, hdr_json_len);
if (r < 0) {
close(devfd);
return r;
}
log_dbg_checksum(hdr_disk.csum, hdr_disk.checksum_alg, "in-memory");
if (write_lseek_blockwise(devfd, device_block_size(device),
device_alignment(device), (char *)&hdr_disk,
LUKS2_HDR_BIN_LEN, offset) < (ssize_t)LUKS2_HDR_BIN_LEN)
r = -EIO;
close(devfd);
return r;
}
static int LUKS2_check_device_size(struct crypt_device *cd, struct device *device, uint64_t hdr_size)
{
uint64_t dev_size;
if (device_size(device, &dev_size)) {
log_dbg("Cannot get device size for device %s.", device_path(device));
return -EIO;
}
log_dbg("Device size %" PRIu64 ", header size %"
PRIu64 ".", dev_size, hdr_size);
if (hdr_size > dev_size) {
log_err(cd, _("Device %s is too small. (LUKS2 requires at least %" PRIu64 " bytes.)\n"),
device_path(device), hdr_size);
return -EINVAL;
}
return 0;
}
/*
* Convert in-memory LUKS2 header and write it to disk.
* This will increase sequence id, write both header copies and calculate checksum.
*/
int LUKS2_disk_hdr_write(struct crypt_device *cd, struct luks2_hdr *hdr, struct device *device)
{
char *json_area;
const char *json_text;
size_t json_area_len;
int r;
if (hdr->version != 2) {
log_dbg("Unsupported LUKS2 header version (%u).", hdr->version);
return -EINVAL;
}
if (hdr->hdr_size != LUKS2_HDR_16K_LEN) {
log_dbg("Unsupported LUKS2 header size (%zu).", hdr->hdr_size);
return -EINVAL;
}
r = LUKS2_check_device_size(cd, crypt_metadata_device(cd), LUKS2_hdr_and_areas_size(hdr->jobj));
if (r)
return r;
/*
* Allocate and zero JSON area (of proper header size).
*/
json_area_len = hdr->hdr_size - LUKS2_HDR_BIN_LEN;
json_area = malloc(json_area_len);
if (!json_area)
return -ENOMEM;
memset(json_area, 0, json_area_len);
/*
* Generate text space-efficient JSON representation to json area.
*/
json_text = json_object_to_json_string_ext(hdr->jobj, JSON_C_TO_STRING_PLAIN);
if (!json_text || !*json_text) {
log_dbg("Cannot parse JSON object to text representation.");
free(json_area);
return -ENOMEM;
}
if (strlen(json_text) > (json_area_len - 1)) {
log_dbg("JSON is too large (%zu > %zu).", strlen(json_text), json_area_len);
free(json_area);
return -EINVAL;
}
strncpy(json_area, json_text, json_area_len);
/* Increase sequence id before writing it to disk. */
hdr->seqid++;
r = device_write_lock(cd, device);
if (r) {
log_err(cd, _("Failed to acquire write device lock.\n"));
free(json_area);
return r;
}
/* Write primary and secondary header */
r = hdr_write_disk(device, hdr, json_area, 0);
if (!r)
r = hdr_write_disk(device, hdr, json_area, 1);
if (r)
log_dbg("LUKS2 header write failed (%d).", r);
device_write_unlock(device);
/* FIXME: try recovery here? */
free(json_area);
return r;
}
static int validate_json_area(const char *json_area, int start, int length)
{
char c;
/* Enforce there are no needless opening bytes */
if (*json_area != '{') {
log_dbg("ERROR: Opening character must be left curly bracket: '{'.");
return -EINVAL;
}
if (start >= length) {
log_dbg("ERROR: Missing trailing null byte beyond parsed json data string.");
return -EINVAL;
}
/*
* TODO:
* validate there are legal json format characters between
* 'json_area' and 'json_area + start'
*/
do {
c = *(json_area + start);
if (c != '\0') {
log_dbg("ERROR: Forbidden ascii code 0x%02hhx found beyond json data string at offset %d.",
c, start);
return -EINVAL;
}
} while (++start < length);
return 0;
}
static int validate_luks2_json_object(json_object *jobj_hdr)
{
int r;
/* we require top level object to be of json_type_object */
r = !json_object_is_type(jobj_hdr, json_type_object);
if (r) {
log_dbg("ERROR: Resulting object is not a json object type");
return r;
}
r = LUKS2_hdr_validate(jobj_hdr);
if (r)
log_dbg("ERROR: LUKS2 validation failed");
return r;
}
static json_object *parse_and_validate_json(const char *json_area, int length)
{
int offset, r;
json_object *jobj = parse_json_len(json_area, length, &offset);
if (!jobj)
return NULL;
/* successfull parse_json_len must not return offset <= 0 */
assert(offset > 0);
r = validate_json_area(json_area, offset, length);
if (!r)
r = validate_luks2_json_object(jobj);
if (r) {
json_object_put(jobj);
jobj = NULL;
}
return jobj;
}
/*
* Read and convert on-disk LUKS2 header to in-memory representation..
* Try to do recovery if on-disk state is not consistent.
*/
int LUKS2_disk_hdr_read(struct crypt_device *cd, struct luks2_hdr *hdr,
struct device *device, int do_recovery)
{
enum { HDR_OK, HDR_OBSOLETE, HDR_FAIL, HDR_FAIL_IO } state_hdr1, state_hdr2;
struct luks2_hdr_disk hdr_disk1, hdr_disk2;
char *json_area1 = NULL, *json_area2 = NULL;
json_object *jobj_hdr1 = NULL, *jobj_hdr2 = NULL;
int i, r;
uint64_t hdr_size;
if (do_recovery && !crypt_metadata_locking_enabled()) {
do_recovery = 0;
log_dbg("Disabling header auto-recovery due to locking being disabled.");
}
/*
* Read primary LUKS2 header (offset 0).
*/
state_hdr1 = HDR_FAIL;
r = hdr_read_disk(device, &hdr_disk1, &json_area1, 0, 0);
if (r == 0) {
jobj_hdr1 = parse_and_validate_json(json_area1, be64_to_cpu(hdr_disk1.hdr_size) - LUKS2_HDR_BIN_LEN);
state_hdr1 = jobj_hdr1 ? HDR_OK : HDR_OBSOLETE;
} else if (r == -EIO)
state_hdr1 = HDR_FAIL_IO;
/*
* Read secondary LUKS2 header (follows primary).
*/
state_hdr2 = HDR_FAIL;
if (state_hdr1 != HDR_FAIL && state_hdr1 != HDR_FAIL_IO) {
r = hdr_read_disk(device, &hdr_disk2, &json_area2, be64_to_cpu(hdr_disk1.hdr_size), 1);
if (r == 0) {
jobj_hdr2 = parse_and_validate_json(json_area2, be64_to_cpu(hdr_disk2.hdr_size) - LUKS2_HDR_BIN_LEN);
state_hdr2 = jobj_hdr2 ? HDR_OK : HDR_OBSOLETE;
} else if (r == -EIO)
state_hdr2 = HDR_FAIL_IO;
} else {
/*
* No header size, check all known offsets.
*/
for (r = -EINVAL,i = 2; r < 0 && i <= 1024; i <<= 1)
r = hdr_read_disk(device, &hdr_disk2, &json_area2, i * 4096, 1);
if (r == 0) {
jobj_hdr2 = parse_and_validate_json(json_area2, be64_to_cpu(hdr_disk2.hdr_size) - LUKS2_HDR_BIN_LEN);
state_hdr2 = jobj_hdr2 ? HDR_OK : HDR_OBSOLETE;
} else if (r == -EIO)
state_hdr2 = HDR_FAIL_IO;
}
/*
* Check sequence id if both headers are read correctly.
*/
if (state_hdr1 == HDR_OK && state_hdr2 == HDR_OK) {
if (be64_to_cpu(hdr_disk1.seqid) > be64_to_cpu(hdr_disk2.seqid))
state_hdr2 = HDR_OBSOLETE;
else if (be64_to_cpu(hdr_disk1.seqid) < be64_to_cpu(hdr_disk2.seqid))
state_hdr1 = HDR_OBSOLETE;
}
/* check header with keyslots to fit the device */
if (state_hdr1 == HDR_OK)
hdr_size = LUKS2_hdr_and_areas_size(jobj_hdr1);
else if (state_hdr2 == HDR_OK)
hdr_size = LUKS2_hdr_and_areas_size(jobj_hdr2);
else {
r = (state_hdr1 == HDR_FAIL_IO && state_hdr2 == HDR_FAIL_IO) ? -EIO : -EINVAL;
goto err;
}
r = LUKS2_check_device_size(cd, device, hdr_size);
if (r)
goto err;
/*
* Try to rewrite (recover) bad header. Always regenerate salt for bad header.
*/
if (state_hdr1 == HDR_OK && state_hdr2 != HDR_OK) {
log_dbg("Secondary LUKS2 header requires recovery.");
if (do_recovery) {
memcpy(&hdr_disk2, &hdr_disk1, LUKS2_HDR_BIN_LEN);
r = crypt_random_get(NULL, (char*)hdr_disk2.salt, sizeof(hdr_disk2.salt), CRYPT_RND_SALT);
if (r)
log_dbg("Cannot generate master salt.");
else {
hdr_from_disk(&hdr_disk1, &hdr_disk2, hdr, 0);
r = hdr_write_disk(device, hdr, json_area1, 1);
}
if (r)
log_dbg("Secondary LUKS2 header recovery failed.");
}
} else if (state_hdr1 != HDR_OK && state_hdr2 == HDR_OK) {
log_dbg("Primary LUKS2 header requires recovery.");
if (do_recovery) {
memcpy(&hdr_disk1, &hdr_disk2, LUKS2_HDR_BIN_LEN);
r = crypt_random_get(NULL, (char*)hdr_disk1.salt, sizeof(hdr_disk1.salt), CRYPT_RND_SALT);
if (r)
log_dbg("Cannot generate master salt.");
else {
hdr_from_disk(&hdr_disk2, &hdr_disk1, hdr, 1);
r = hdr_write_disk(device, hdr, json_area2, 0);
}
if (r)
log_dbg("Primary LUKS2 header recovery failed.");
}
}
free(json_area1);
json_area1 = NULL;
free(json_area2);
json_area2 = NULL;
/* wrong lock for write mode during recovery attempt */
if (r == -EAGAIN)
goto err;
/*
* Even if status is failed, the second header includes salt.
*/
if (state_hdr1 == HDR_OK) {
hdr_from_disk(&hdr_disk1, &hdr_disk2, hdr, 0);
hdr->jobj = jobj_hdr1;
json_object_put(jobj_hdr2);
} else if (state_hdr2 == HDR_OK) {
hdr_from_disk(&hdr_disk2, &hdr_disk1, hdr, 1);
hdr->jobj = jobj_hdr2;
json_object_put(jobj_hdr1);
}
/*
* FIXME: should this fail? At least one header was read correctly.
* r = (state_hdr1 == HDR_FAIL_IO || state_hdr2 == HDR_FAIL_IO) ? -EIO : -EINVAL;
*/
return 0;
err:
log_dbg("LUKS2 header read failed (%d).", r);
free(json_area1);
free(json_area2);
json_object_put(jobj_hdr1);
json_object_put(jobj_hdr2);
hdr->jobj = NULL;
return r;
}
int LUKS2_hdr_version_unlocked(struct crypt_device *cd)
{
struct {
char magic[LUKS2_MAGIC_L];
uint16_t version;
} __attribute__ ((packed)) hdr;
struct device *device = crypt_metadata_device(cd);
int r, devfd, flags;
if (!device)
return 0;
flags = O_RDONLY;
if (device_direct_io(device))
flags |= O_DIRECT;
devfd = open(device_path(device), flags);
if (devfd < 0)
return 0;
if ((read_lseek_blockwise(devfd, device_block_size(device),
device_alignment(device), &hdr, sizeof(hdr), 0)
!= sizeof(hdr)) ||
memcmp(hdr.magic, LUKS2_MAGIC_1ST, LUKS2_MAGIC_L))
r = 0;
else
r = (int)be16_to_cpu(hdr.version);
close(devfd);
return r;
}

154
lib/luks2/luks2_internal.h Normal file
View File

@@ -0,0 +1,154 @@
/*
* LUKS - Linux Unified Key Setup v2
*
* Copyright (C) 2015-2017, Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2017, 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
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef _CRYPTSETUP_LUKS2_INTERNAL_H
#define _CRYPTSETUP_LUKS2_INTERNAL_H
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <json-c/json.h>
#include "internal.h"
#include "base64.h"
#include "luks2.h"
#define UNUSED(x) (void)(x)
/*
* On-disk access function prototypes
*/
int LUKS2_disk_hdr_read(struct crypt_device *cd, struct luks2_hdr *hdr,
struct device *device, int do_recovery);
int LUKS2_disk_hdr_write(struct crypt_device *cd, struct luks2_hdr *hdr,
struct device *device);
/*
* JSON struct access helpers
*/
json_object *LUKS2_get_keyslot_jobj(struct luks2_hdr *hdr, int keyslot);
json_object *LUKS2_get_token_jobj(struct luks2_hdr *hdr, int token);
json_object *LUKS2_get_digest_jobj(struct luks2_hdr *hdr, int keyslot);
json_object *LUKS2_get_segment_jobj(struct luks2_hdr *hdr, int segment);
void hexprint_base64(struct crypt_device *cd, json_object *jobj,
const char *sep, const char *line_sep);
json_object *parse_json_len(const char *json_area, int length, int *end_offset);
uint64_t json_object_get_uint64(json_object *jobj);
uint32_t json_object_get_uint32(json_object *jobj);
void JSON_DBG(json_object *jobj, const char *desc);
/*
* LUKS2 JSON validation
*/
int LUKS2_hdr_validate(json_object *hdr_jobj);
int LUKS2_keyslot_validate(json_object *hdr_jobj, json_object *hdr_keyslot, const char *key);
int LUKS2_check_json_size(const struct luks2_hdr *hdr);
int LUKS2_token_validate(json_object *hdr_jobj, json_object *jobj_token, const char *key);
void LUKS2_token_dump(struct crypt_device *cd, int token);
/*
* JSON array helpers
*/
struct json_object *LUKS2_array_jobj(struct json_object *array, const char *num);
struct json_object *LUKS2_array_remove(struct json_object *array, const char *num);
/*
* Plugins API
*/
/**
* LUKS2 keyslots handlers (EXPERIMENTAL)
*/
typedef int (*keyslot_alloc_func)(struct crypt_device *cd, int keyslot,
size_t volume_key_len);
typedef int (*keyslot_open_func) (struct crypt_device *cd, int keyslot,
const char *password, size_t password_len,
char *volume_key, size_t volume_key_len);
typedef int (*keyslot_store_func)(struct crypt_device *cd, int keyslot,
const char *password, size_t password_len,
const char *volume_key, size_t volume_key_len);
typedef int (*keyslot_wipe_func) (struct crypt_device *cd, int keyslot);
typedef int (*keyslot_dump_func) (struct crypt_device *cd, int keyslot);
typedef int (*keyslot_validate_func) (struct crypt_device *cd, int keyslot);
int luks2_keyslot_alloc(struct crypt_device *cd,
int keyslot,
size_t volume_key_len);
typedef struct {
const char *name;
keyslot_alloc_func alloc;
keyslot_open_func open;
keyslot_store_func store;
keyslot_wipe_func wipe;
keyslot_dump_func dump;
keyslot_validate_func validate;
} keyslot_handler;
/**
* LUKS2 digest handlers (EXPERIMENTAL)
*/
typedef int (*digest_verify_func)(struct crypt_device *cd, int digest,
const char *volume_key, size_t volume_key_len);
typedef int (*digest_store_func) (struct crypt_device *cd, int digest,
const char *volume_key, size_t volume_key_len);
typedef int (*digest_dump_func) (struct crypt_device *cd, int digest);
typedef struct {
const char *name;
digest_verify_func verify;
digest_store_func store;
digest_dump_func dump;
} digest_handler;
int crypt_digest_register(const digest_handler *handler);
const digest_handler *LUKS2_digest_handler_type(struct crypt_device *cd, const char *type);
#define CRYPT_ANY_DIGEST -1
int crypt_keyslot_assign_digest(struct crypt_device *cd, int keyslot, int digest);
int crypt_keyslot_unassign_digest(struct crypt_device *cd, int keyslot, int digest);
/**
* LUKS2 token handlers (internal use only)
*/
typedef int (*builtin_token_get_func) (json_object *jobj_token, void *params);
typedef int (*builtin_token_set_func) (json_object **jobj_token, const void *params);
typedef struct {
/* internal only section used by builtin tokens */
builtin_token_get_func get;
builtin_token_set_func set;
/* public token handler */
const crypt_token_handler *h;
} token_handler;
int token_keyring_set(json_object **, const void *);
int token_keyring_get(json_object *, void *);
#define CRYPT_ANY_TOKEN -1
int LUKS2_find_area_gap(struct crypt_device *cd, struct luks2_hdr *hdr,
size_t keylength, uint64_t *area_offset, uint64_t *area_length);
#endif

View File

@@ -0,0 +1,233 @@
/*
* LUKS - Linux Unified Key Setup v2, LUKS2 header format code
*
* Copyright (C) 2015-2017, Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2017, 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
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "luks2_internal.h"
#include <uuid/uuid.h>
struct area {
uint64_t offset;
uint64_t length;
};
static size_t get_area_size(size_t keylength)
{
//FIXME: calculate this properly, for now it is AF_split_sectors
return size_round_up(keylength * 4000, 4096);
}
static size_t get_min_offset(struct luks2_hdr *hdr)
{
return 2 * hdr->hdr_size;
}
static size_t get_max_offset(struct crypt_device *cd)
{
return crypt_get_data_offset(cd) * SECTOR_SIZE;
}
int LUKS2_find_area_gap(struct crypt_device *cd, struct luks2_hdr *hdr,
size_t keylength, uint64_t *area_offset, uint64_t *area_length)
{
struct area areas[LUKS2_KEYSLOTS_MAX], sorted_areas[LUKS2_KEYSLOTS_MAX] = {};
int i, j, k, area_i;
size_t offset, length;
/* fill area offset + length table */
for (i = 0; i < LUKS2_KEYSLOTS_MAX; i++) {
if (!LUKS2_keyslot_area(hdr, i, &areas[i].offset, &areas[i].length))
continue;
areas[i].length = 0;
areas[i].offset = 0;
}
/* sort table */
k = 0; /* index in sorted table */
for (i = 0; i < LUKS2_KEYSLOTS_MAX; i++) {
offset = get_max_offset(cd) ?: UINT64_MAX;
area_i = -1;
/* search for the smallest offset in table */
for (j = 0; j < LUKS2_KEYSLOTS_MAX; j++)
if (areas[j].offset && areas[j].offset <= offset) {
area_i = j;
offset = areas[j].offset;
}
if (area_i >= 0) {
sorted_areas[k].length = areas[area_i].length;
sorted_areas[k].offset = areas[area_i].offset;
areas[area_i].length = 0;
areas[area_i].offset = 0;
k++;
}
}
/* search for the gap we can use */
offset = get_min_offset(hdr);
length = get_area_size(keylength);
for (i = 0; i < LUKS2_KEYSLOTS_MAX; i++) {
/* skip empty */
if (sorted_areas[i].offset == 0 || sorted_areas[i].length == 0)
continue;
/* enough space before the used area */
if ((offset < sorted_areas[i].offset) && ((offset + length) <= sorted_areas[i].offset))
break;
/* both offset and length are already aligned to 4096 bytes */
offset = sorted_areas[i].offset + sorted_areas[i].length;
}
if (get_max_offset(cd) && (offset + length) > get_max_offset(cd)) {
log_err(cd, _("No space for new keyslot.\n"));
return -EINVAL;
}
log_dbg("Found area %zu -> %zu", offset, length + offset);
/*
log_dbg("Area offset min: %zu, max %zu, slots max %u",
get_min_offset(hdr), get_max_offset(cd), LUKS2_KEYSLOTS_MAX);
for (i = 0; i < LUKS2_KEYSLOTS_MAX; i++)
log_dbg("SLOT[%02i]: %-8" PRIu64 " -> %-8" PRIu64, i,
sorted_areas[i].offset,
sorted_areas[i].length + sorted_areas[i].offset);
*/
*area_offset = offset;
*area_length = length;
return 0;
}
int LUKS2_generate_hdr(
struct crypt_device *cd,
struct luks2_hdr *hdr,
const struct volume_key *vk,
const char *cipherName,
const char *cipherMode,
const char *integrity,
const char *uuid,
unsigned int sector_size,
unsigned int alignPayload,
unsigned int alignOffset,
int detached_metadata_device)
{
struct json_object *jobj_segment, *jobj_integrity, *jobj_keyslots, *jobj_segments, *jobj_config;
char num[24], cipher[128];
uint64_t offset, json_size, keyslots_size;
uuid_t partitionUuid;
int digest;
hdr->hdr_size = LUKS2_HDR_16K_LEN;
hdr->seqid = 1;
hdr->version = 2;
memset(hdr->label, 0, LUKS2_LABEL_L);
strcpy(hdr->checksum_alg, "sha256");
crypt_random_get(NULL, (char*)hdr->salt1, LUKS2_SALT_L, CRYPT_RND_SALT);
crypt_random_get(NULL, (char*)hdr->salt2, LUKS2_SALT_L, CRYPT_RND_SALT);
if (uuid && uuid_parse(uuid, partitionUuid) == -1) {
log_err(cd, _("Wrong LUKS UUID format provided.\n"));
return -EINVAL;
}
if (!uuid)
uuid_generate(partitionUuid);
uuid_unparse(partitionUuid, hdr->uuid);
if (*cipherMode != '\0')
snprintf(cipher, sizeof(cipher), "%s-%s", cipherName, cipherMode);
else
snprintf(cipher, sizeof(cipher), "%s", cipherName);
hdr->jobj = json_object_new_object();
jobj_keyslots = json_object_new_object();
json_object_object_add(hdr->jobj, "keyslots", jobj_keyslots);
json_object_object_add(hdr->jobj, "tokens", json_object_new_object());
jobj_segments = json_object_new_object();
json_object_object_add(hdr->jobj, "segments", jobj_segments);
json_object_object_add(hdr->jobj, "digests", json_object_new_object());
jobj_config = json_object_new_object();
json_object_object_add(hdr->jobj, "config", jobj_config);
digest = LUKS2_digest_create(cd, "pbkdf2", hdr, vk);
if (digest < 0) {
json_object_put(hdr->jobj);
hdr->jobj = NULL;
return -EINVAL;
}
if (LUKS2_digest_segment_assign(cd, hdr, CRYPT_DEFAULT_SEGMENT, digest, 1, 0) < 0) {
json_object_put(hdr->jobj);
hdr->jobj = NULL;
return -EINVAL;
}
jobj_segment = json_object_new_object();
json_object_object_add(jobj_segment, "type", json_object_new_string("crypt"));
if (detached_metadata_device)
offset = (uint64_t)alignPayload * sector_size;
else {
//FIXME
//offset = size_round_up(areas[7].offset + areas[7].length, alignPayload * SECTOR_SIZE);
offset = size_round_up(LUKS2_HDR_DEFAULT_LEN, alignPayload * sector_size);
offset += alignOffset;
}
json_object_object_add(jobj_segment, "offset", json_object_new_string(uint64_to_str(num, sizeof(num), &offset)));
json_object_object_add(jobj_segment, "iv_tweak", json_object_new_string("0"));
json_object_object_add(jobj_segment, "size", json_object_new_string("dynamic"));
json_object_object_add(jobj_segment, "encryption", json_object_new_string(cipher));
json_object_object_add(jobj_segment, "sector_size", json_object_new_int(sector_size));
if (integrity) {
jobj_integrity = json_object_new_object();
json_object_object_add(jobj_integrity, "type", json_object_new_string(integrity));
json_object_object_add(jobj_integrity, "journal_encryption", json_object_new_string("none"));
json_object_object_add(jobj_integrity, "journal_integrity", json_object_new_string("none"));
json_object_object_add(jobj_segment, "integrity", jobj_integrity);
}
snprintf(num, sizeof(num), "%u", CRYPT_DEFAULT_SEGMENT);
json_object_object_add(jobj_segments, num, jobj_segment);
json_size = hdr->hdr_size - LUKS2_HDR_BIN_LEN;
json_object_object_add(jobj_config, "json_size",
json_object_new_string(uint64_to_str(num, sizeof(num), &json_size)));
/* for detached metadata device compute reasonable keyslot areas size */
// FIXME: this is coupled with FIXME above
if (detached_metadata_device)
keyslots_size = LUKS2_HDR_DEFAULT_LEN - get_min_offset(hdr);
else
keyslots_size = offset - get_min_offset(hdr);
/* keep keyslots_size reasonable for custom data alignments */
if (keyslots_size > LUKS2_MAX_KEYSLOTS_SIZE)
keyslots_size = LUKS2_MAX_KEYSLOTS_SIZE;
/* keyslots size has to be 4 KiB aligned */
keyslots_size -= (keyslots_size % 4096);
json_object_object_add(jobj_config, "keyslots_size",
json_object_new_string(uint64_to_str(num, sizeof(num), &keyslots_size)));
JSON_DBG(hdr->jobj, "Header JSON");
return 0;
}

File diff suppressed because it is too large Load Diff

477
lib/luks2/luks2_keyslot.c Normal file
View File

@@ -0,0 +1,477 @@
/*
* LUKS - Linux Unified Key Setup v2, keyslot handling
*
* Copyright (C) 2015-2017, Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2017, 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
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "luks2_internal.h"
/* Internal implementations */
extern const keyslot_handler luks2_keyslot;
static const keyslot_handler *keyslot_handlers[LUKS2_KEYSLOTS_MAX] = {
&luks2_keyslot,
NULL
};
static const keyslot_handler
*LUKS2_keyslot_handler_type(struct crypt_device *cd, const char *type)
{
int i;
for (i = 0; i < LUKS2_KEYSLOTS_MAX && keyslot_handlers[i]; i++) {
if (!strcmp(keyslot_handlers[i]->name, type))
return keyslot_handlers[i];
}
return NULL;
}
static const keyslot_handler
*LUKS2_keyslot_handler(struct crypt_device *cd, int keyslot)
{
struct luks2_hdr *hdr;
json_object *jobj1, *jobj2;
if (keyslot < 0)
return NULL;
if (!(hdr = crypt_get_hdr(cd, CRYPT_LUKS2)))
return NULL;
if (!(jobj1 = LUKS2_get_keyslot_jobj(hdr, keyslot)))
return NULL;
if (!json_object_object_get_ex(jobj1, "type", &jobj2))
return NULL;
return LUKS2_keyslot_handler_type(cd, json_object_get_string(jobj2));
}
static crypt_keyslot_info LUKS2_keyslot_active(struct luks2_hdr *hdr, int keyslot)
{
if (keyslot >= LUKS2_KEYSLOTS_MAX)
return CRYPT_SLOT_INVALID;
return LUKS2_get_keyslot_jobj(hdr, keyslot) ? CRYPT_SLOT_ACTIVE : CRYPT_SLOT_INACTIVE;
}
int LUKS2_keyslot_find_empty(struct luks2_hdr *hdr, const char *type)
{
int i;
for (i = 0; i < LUKS2_KEYSLOTS_MAX; i++)
if (!LUKS2_get_keyslot_jobj(hdr, i))
return i;
return -EINVAL;
}
static int digests_by_segment(json_object *jobj_digests, const char *segment,
digests_t digests)
{
json_object *jobj_segs;
int i = 0;
json_object_object_foreach(jobj_digests, dig, val) {
json_object_object_get_ex(val, "segments", &jobj_segs);
if (LUKS2_array_jobj(jobj_segs, segment))
digests[i++] = atoi(dig);
}
if (i < LUKS2_DIGEST_MAX)
digests[i] = -1;
return i ? 0 : -ENOENT;
}
static int is_in(const int super[], int super_size, int elem)
{
int i;
for (i = 0; i < super_size && super[i] != -1; i++)
if (super[i] == elem)
return 1;
return 0;
}
static int is_subset(const int super[], const int sub[], int super_size)
{
int i;
for (i = 0; i < super_size && sub[i] != -1; i++)
if (!is_in(super, super_size, sub[i]))
return 0;
return 1;
}
int LUKS2_keyslot_for_segment(struct luks2_hdr *hdr, int keyslot, int segment)
{
char keyslot_name[16], segment_name[16];
digests_t keyslot_digests, segment_digests;
json_object *jobj_digests;
int r = -ENOENT;
/* no need to check anything */
if (segment == CRYPT_ANY_SEGMENT)
return 0;
if (snprintf(segment_name, sizeof(segment_name), "%u", segment) < 1 ||
snprintf(keyslot_name, sizeof(keyslot_name), "%u", keyslot) < 1)
return -EINVAL;
/* empty set is subset of any set and it'd be wrong */
json_object_object_get_ex(hdr->jobj, "digests", &jobj_digests);
r = LUKS2_digests_by_keyslot(NULL, hdr, keyslot, keyslot_digests);
if (r)
return r;
/* empty set can't be superset of non-empty one */
if (digests_by_segment(jobj_digests, segment_name, segment_digests))
return r;
/*
* keyslot may activate segment if set of digests for keyslot
* is actually subset of set of digests for segment
*/
return is_subset(segment_digests, keyslot_digests, LUKS2_DIGEST_MAX) ? 0 : -ENOENT;
}
int LUKS2_keyslot_active_count(struct luks2_hdr *hdr, int segment)
{
int num = 0;
json_object *jobj_keyslots;
json_object_object_get_ex(hdr->jobj, "keyslots", &jobj_keyslots);
/* keyslot digests must be subset of segment digests */
json_object_object_foreach(jobj_keyslots, slot, val) {
UNUSED(val);
if (!LUKS2_keyslot_for_segment(hdr, atoi(slot), segment))
num++;
}
return num;
}
crypt_keyslot_info LUKS2_keyslot_info(struct luks2_hdr *hdr, int keyslot)
{
crypt_keyslot_info ki;
if(keyslot >= LUKS2_KEYSLOTS_MAX || keyslot < 0)
return CRYPT_SLOT_INVALID;
ki = LUKS2_keyslot_active(hdr, keyslot);
if (ki != CRYPT_SLOT_ACTIVE)
return ki;
if (LUKS2_keyslot_active_count(hdr, CRYPT_DEFAULT_SEGMENT) == 1 && !LUKS2_keyslot_for_segment(hdr, keyslot, CRYPT_DEFAULT_SEGMENT))
return CRYPT_SLOT_ACTIVE_LAST;
return CRYPT_SLOT_ACTIVE;
}
int LUKS2_keyslot_area(struct luks2_hdr *hdr,
int keyslot,
uint64_t *offset,
uint64_t *length)
{
json_object *jobj_keyslot, *jobj_area, *jobj;
if(LUKS2_keyslot_info(hdr, keyslot) == CRYPT_SLOT_INVALID)
return -EINVAL;
jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot);
if (!jobj_keyslot)
return -ENOENT;
if (!json_object_object_get_ex(jobj_keyslot, "area", &jobj_area))
return -EINVAL;
if (!json_object_object_get_ex(jobj_area, "offset", &jobj))
return -EINVAL;
*offset = json_object_get_int64(jobj);
if (!json_object_object_get_ex(jobj_area, "size", &jobj))
return -EINVAL;
*length = json_object_get_int64(jobj);
return 0;
}
static int LUKS2_open_and_verify(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot,
int segment,
const char *password,
size_t password_len,
struct volume_key **vk)
{
const keyslot_handler *h;
int key_size, r;
if (!(h = LUKS2_keyslot_handler(cd, keyslot)))
return -ENOENT;
r = LUKS2_keyslot_for_segment(hdr, keyslot, segment);
if (r) {
if (r == -ENOENT)
log_dbg("Keyslot %d unusable for segment %d.", keyslot, segment);
return r;
}
key_size = LUKS2_get_volume_key_size(hdr, segment);
if (key_size < 0)
key_size = LUKS2_get_keyslot_key_size(hdr, keyslot);
if (key_size < 0)
return -EINVAL;
*vk = crypt_alloc_volume_key(key_size, NULL);
if (!*vk)
return -ENOMEM;
r = h->open(cd, keyslot, password, password_len, (*vk)->key, (*vk)->keylength);
if (r < 0)
log_dbg("Keyslot %d (%s) open failed with %d.", keyslot, h->name, r);
else
r = LUKS2_digest_verify(cd, hdr, *vk, keyslot);
if (r < 0) {
crypt_free_volume_key(*vk);
*vk = NULL;
}
return r < 0 ? r : keyslot;
}
static int LUKS2_keyslot_open_priority(struct crypt_device *cd,
struct luks2_hdr *hdr,
crypt_keyslot_priority priority,
const char *password,
size_t password_len,
int segment,
struct volume_key **vk)
{
json_object *jobj_keyslots, *jobj;
crypt_keyslot_priority slot_priority;
int keyslot, r = -ENOENT;
json_object_object_get_ex(hdr->jobj, "keyslots", &jobj_keyslots);
json_object_object_foreach(jobj_keyslots, slot, val) {
if (!json_object_object_get_ex(val, "priority", &jobj))
slot_priority = CRYPT_SLOT_PRIORITY_NORMAL;
else
slot_priority = json_object_get_int(jobj);
keyslot = atoi(slot);
if (slot_priority != priority) {
log_dbg("Keyslot %d priority %d != %d (required), skipped.",
keyslot, slot_priority, priority);
continue;
}
r = LUKS2_open_and_verify(cd, hdr, keyslot, segment, password, password_len, vk);
/* Do not retry for errors that are no -EPERM or -ENOENT,
former meaning password wrong, latter key slot unusable for segment */
if ((r != -EPERM) && (r != -ENOENT))
break;
}
return r;
}
int LUKS2_keyslot_open(struct crypt_device *cd,
int keyslot,
int segment,
const char *password,
size_t password_len,
struct volume_key **vk)
{
struct luks2_hdr *hdr;
int r_prio, r = -EINVAL;
hdr = crypt_get_hdr(cd, CRYPT_LUKS2);
if (keyslot == CRYPT_ANY_SLOT) {
r_prio = LUKS2_keyslot_open_priority(cd, hdr, CRYPT_SLOT_PRIORITY_PREFER,
password, password_len, segment, vk);
if (r_prio >= 0)
r = r_prio;
else if (r_prio < 0 && (r_prio != -EPERM) && (r_prio != -ENOENT))
r = r_prio;
else
r = LUKS2_keyslot_open_priority(cd, hdr, CRYPT_SLOT_PRIORITY_NORMAL,
password, password_len, segment, vk);
/* Prefer password wrong to no entry from priority slot */
if (r_prio == -EPERM && r == -ENOENT)
r = r_prio;
} else
r = LUKS2_open_and_verify(cd, hdr, keyslot, segment, password, password_len, vk);
return r;
}
int LUKS2_keyslot_store(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot,
const char *password,
size_t password_len,
const struct volume_key *vk)
{
const keyslot_handler *h;
int r;
if (keyslot == CRYPT_ANY_SLOT)
return -EINVAL;
if (!LUKS2_get_keyslot_jobj(hdr, keyslot)) {
/* Try to allocate default and empty keyslot type */
h = LUKS2_keyslot_handler_type(cd, "luks2");
if (!h)
return -EINVAL;
r = h->alloc(cd, keyslot, vk->keylength);
if (r)
return r;
} else if (!(h = LUKS2_keyslot_handler(cd, keyslot)))
return -EINVAL;
r = h->validate(cd, keyslot);
if (r) {
log_dbg("Keyslot validation failed.");
return r;
}
return h->store(cd, keyslot, password, password_len,
vk->key, vk->keylength);
}
int LUKS2_keyslot_wipe(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot,
int wipe_area_only)
{
struct device *device = crypt_metadata_device(cd);
uint64_t area_offset, area_length;
char num[16];
int r;
json_object *jobj_keyslot, *jobj_keyslots;
const keyslot_handler *h;
h = LUKS2_keyslot_handler(cd, keyslot);
if (!json_object_object_get_ex(hdr->jobj, "keyslots", &jobj_keyslots))
return -EINVAL;
jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot);
if (!jobj_keyslot)
return -ENOENT;
if (wipe_area_only)
log_dbg("Wiping keyslot %d area only.", keyslot);
/* Just check that nobody uses the metadata now */
r = device_write_lock(cd, device);
if (r) {
log_err(cd, _("Failed to acquire write lock on device %s.\n"),
device_path(device));
return r;
}
device_write_unlock(device);
/* secure deletion of possible key material in keyslot area */
r = crypt_keyslot_area(cd, keyslot, &area_offset, &area_length);
if (r && r != -ENOENT)
return r;
/* We can destroy the binary keyslot area now without lock */
if (!r) {
r = crypt_wipe_device(cd, device, CRYPT_WIPE_SPECIAL, area_offset,
area_length, area_length, NULL, NULL);
if (r) {
if (r == -EACCES) {
log_err(cd, _("Cannot write to device %s, permission denied.\n"),
device_path(device));
r = -EINVAL;
} else
log_err(cd, _("Cannot wipe device %s.\n"), device_path(device));
return r;
}
}
if (wipe_area_only)
return r;
/* Slot specific wipe */
if (h) {
r = h->wipe(cd, keyslot);
if (r < 0)
return r;
} else
log_dbg("Wiping keyslot %d without specific-slot handler loaded.", keyslot);
snprintf(num, sizeof(num), "%d", keyslot);
json_object_object_del(jobj_keyslots, num);
return LUKS2_hdr_write(cd, hdr);
}
int LUKS2_keyslot_dump(struct crypt_device *cd, int keyslot)
{
const keyslot_handler *h;
if (!(h = LUKS2_keyslot_handler(cd, keyslot)))
return -EINVAL;
return h->dump(cd, keyslot);
}
crypt_keyslot_priority LUKS2_keyslot_priority_get(struct crypt_device *cd,
struct luks2_hdr *hdr, int keyslot)
{
json_object *jobj_keyslot, *jobj_priority;
jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot);
if (!jobj_keyslot)
return CRYPT_SLOT_PRIORITY_INVALID;
if (!json_object_object_get_ex(jobj_keyslot, "priority", &jobj_priority))
return CRYPT_SLOT_PRIORITY_NORMAL;
return json_object_get_int(jobj_priority);
}
int LUKS2_keyslot_priority_set(struct crypt_device *cd, struct luks2_hdr *hdr,
int keyslot, crypt_keyslot_priority priority, int commit)
{
json_object *jobj_keyslot;
jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot);
if (!jobj_keyslot)
return -EINVAL;
if (priority == CRYPT_SLOT_PRIORITY_NORMAL)
json_object_object_del(jobj_keyslot, "priority");
else
json_object_object_add(jobj_keyslot, "priority", json_object_new_int(priority));
return commit ? LUKS2_hdr_write(cd, hdr) : 0;
}

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