mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-06 08:20:07 +01:00
Compare commits
231 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e2637c5d49 | ||
|
|
4a72695241 | ||
|
|
af31af5e3d | ||
|
|
2aa0bb7eac | ||
|
|
8ae62715a8 | ||
|
|
506ba27358 | ||
|
|
4384e50578 | ||
|
|
1623ee71ab | ||
|
|
f425d07ec7 | ||
|
|
d260be02d4 | ||
|
|
4609fd87d7 | ||
|
|
9e90d91446 | ||
|
|
7bbf0796b5 | ||
|
|
fe3148f074 | ||
|
|
5e9c27118e | ||
|
|
c362ba9293 | ||
|
|
e97048dd32 | ||
|
|
5ea0ba61be | ||
|
|
7ae863e380 | ||
|
|
f238e8c075 | ||
|
|
7d9a14fd24 | ||
|
|
2f964d95d8 | ||
|
|
00f419e5ea | ||
|
|
cc698dcde3 | ||
|
|
edced6cfed | ||
|
|
4fb11976d2 | ||
|
|
68ba5b2b36 | ||
|
|
65fa22ff23 | ||
|
|
c25d81d2a1 | ||
|
|
57d16a7a55 | ||
|
|
def397d0c8 | ||
|
|
7843415243 | ||
|
|
5a8b045bdd | ||
|
|
ab62f45d57 | ||
|
|
e521edd6ca | ||
|
|
3a0293a299 | ||
|
|
8a4db1ad7b | ||
|
|
1aba9ab444 | ||
|
|
dfa2755aba | ||
|
|
6e82bdd9a5 | ||
|
|
0dc245401f | ||
|
|
a57f1b1b64 | ||
|
|
1a50fee1d0 | ||
|
|
046e0e5280 | ||
|
|
656b55cd4b | ||
|
|
8d7af433d8 | ||
|
|
dc3de39eb7 | ||
|
|
3d403a7bd0 | ||
|
|
91f6296699 | ||
|
|
bd94eb36b3 | ||
|
|
1a19329b18 | ||
|
|
78a43c053a | ||
|
|
d7d76e72f7 | ||
|
|
dd0dcc05df | ||
|
|
3be8731fef | ||
|
|
86d0ff1a2b | ||
|
|
3adfe80601 | ||
|
|
0bc437d92c | ||
|
|
6b10f30eb9 | ||
|
|
fedd5bc969 | ||
|
|
8aee4f95fb | ||
|
|
1f2d8de95f | ||
|
|
dced269426 | ||
|
|
b834a59eaf | ||
|
|
4f7b413638 | ||
|
|
e4355c2973 | ||
|
|
31a4d552a2 | ||
|
|
6d51e8ab69 | ||
|
|
8157e47ad4 | ||
|
|
62b0138dad | ||
|
|
c13a8003fa | ||
|
|
979aec773e | ||
|
|
b789b011a2 | ||
|
|
ea8864badf | ||
|
|
49335b600f | ||
|
|
7245af59d3 | ||
|
|
f7b61b2617 | ||
|
|
dc40b91cdf | ||
|
|
eccf347568 | ||
|
|
e24a72f84c | ||
|
|
2c70c057d6 | ||
|
|
f16f37233f | ||
|
|
3cffadb508 | ||
|
|
ce30d5f1fd | ||
|
|
6e0f0408a0 | ||
|
|
3d6bcae84c | ||
|
|
b8beedb621 | ||
|
|
fd5c2a5000 | ||
|
|
69bc154fca | ||
|
|
387041ccf2 | ||
|
|
64d6b339a0 | ||
|
|
4f5f1b78c4 | ||
|
|
3e886ecf57 | ||
|
|
210ea612b3 | ||
|
|
3350ff017f | ||
|
|
7b42254975 | ||
|
|
e84b1ed7c0 | ||
|
|
f3f1bfd73a | ||
|
|
89f795d7b4 | ||
|
|
c36a7968f4 | ||
|
|
3762c8b76e | ||
|
|
872becdbbd | ||
|
|
c9694437d2 | ||
|
|
64ad90f73c | ||
|
|
166d23a813 | ||
|
|
59fdf2a6bb | ||
|
|
3640eaa726 | ||
|
|
2250d5f71f | ||
|
|
d9678325a2 | ||
|
|
dc8c47d936 | ||
|
|
5b7100ff87 | ||
|
|
4afa592160 | ||
|
|
54c7a2b0aa | ||
|
|
9cabc9bf05 | ||
|
|
dfd46df8a5 | ||
|
|
25cd4f3a1d | ||
|
|
d5b594dd12 | ||
|
|
803686ea4b | ||
|
|
3add769b51 | ||
|
|
d5a72cd65a | ||
|
|
d63163e46c | ||
|
|
62d690492c | ||
|
|
54d81a6258 | ||
|
|
56679a6e4a | ||
|
|
e0788d9d61 | ||
|
|
833e066853 | ||
|
|
02f860140d | ||
|
|
027cebade3 | ||
|
|
bb8dbfdf5b | ||
|
|
8e380183f8 | ||
|
|
4f89028c67 | ||
|
|
6b4c33d3a5 | ||
|
|
7a2e6990ca | ||
|
|
98ba2f2333 | ||
|
|
4e4d933d7b | ||
|
|
91c739958c | ||
|
|
1a6e1ae918 | ||
|
|
aedf39a9ca | ||
|
|
a274cd3a74 | ||
|
|
6be21469fb | ||
|
|
e0d3ff8aeb | ||
|
|
0614ab6b07 | ||
|
|
49e55c0f42 | ||
|
|
be4edbb460 | ||
|
|
4d30237f7a | ||
|
|
a3c0f6784b | ||
|
|
6d4c2db3b1 | ||
|
|
1436f2a0a0 | ||
|
|
e6a46bf827 | ||
|
|
9563aa33c8 | ||
|
|
6225c901fe | ||
|
|
cad0cbf0c8 | ||
|
|
1fc441f091 | ||
|
|
22849ccd11 | ||
|
|
a809224ec7 | ||
|
|
ae23ecb9b2 | ||
|
|
0db77f3ace | ||
|
|
779c80c581 | ||
|
|
00ced59c1a | ||
|
|
20595f4b14 | ||
|
|
2e97d8f8e8 | ||
|
|
7effba0f71 | ||
|
|
2ad69eba90 | ||
|
|
4d218e4cbd | ||
|
|
a0346a09ce | ||
|
|
f6e85be3ed | ||
|
|
04e921846f | ||
|
|
e37f3728d7 | ||
|
|
2062ece2ab | ||
|
|
a5fa6f1015 | ||
|
|
9bdd5bf4fe | ||
|
|
110ce5607e | ||
|
|
78f938b0e9 | ||
|
|
ad2f50316f | ||
|
|
cf534f3759 | ||
|
|
75c105f853 | ||
|
|
680eb76e45 | ||
|
|
e364041b40 | ||
|
|
de37457a75 | ||
|
|
057db3b3b3 | ||
|
|
461011ad2a | ||
|
|
aa7346bb36 | ||
|
|
5206543902 | ||
|
|
7f93a49cc3 | ||
|
|
bec86e3d5a | ||
|
|
3ba95a822f | ||
|
|
486ec44c3e | ||
|
|
8dc4877697 | ||
|
|
7415c5858d | ||
|
|
8e5411f468 | ||
|
|
3bf40bb8dd | ||
|
|
79956a4d47 | ||
|
|
2d755335de | ||
|
|
d7762c09dd | ||
|
|
957201e758 | ||
|
|
004dc271a4 | ||
|
|
a9b24ccc82 | ||
|
|
c57071a43a | ||
|
|
df27f04f61 | ||
|
|
f3e398afc5 | ||
|
|
65877efe8b | ||
|
|
96acd87f0b | ||
|
|
fcb35d4e73 | ||
|
|
0d47e5eb76 | ||
|
|
f30bbbffe7 | ||
|
|
6b88461553 | ||
|
|
700b558fb6 | ||
|
|
58b5be440f | ||
|
|
626801f7df | ||
|
|
77a345d4cb | ||
|
|
18901fd501 | ||
|
|
5b86cb5cc2 | ||
|
|
ce23225e46 | ||
|
|
09c229fe6c | ||
|
|
db56125708 | ||
|
|
5736b0a114 | ||
|
|
a21c0503f8 | ||
|
|
e52d5f3d98 | ||
|
|
0e96b9d010 | ||
|
|
dcba8c28f2 | ||
|
|
da93a3320b | ||
|
|
53607a0274 | ||
|
|
67d19f3570 | ||
|
|
54c1f71bd3 | ||
|
|
a7e2809466 | ||
|
|
3f66e9fe4b | ||
|
|
f547d0fac3 | ||
|
|
cdf272315e | ||
|
|
31303718da | ||
|
|
4192bdd731 | ||
|
|
c18aa03552 |
2
AUTHORS
2
AUTHORS
@@ -1,3 +1,3 @@
|
||||
Christophe Saout <christophe@saout.de>
|
||||
Jana Saout <jana@saout.de>
|
||||
Clemens Fruhwirth <clemens@endorphin.org>
|
||||
Milan Broz <gmazyland@gmail.com>
|
||||
|
||||
10
README
10
README
@@ -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):
|
||||
|
||||
|
||||
79
README.md
Normal file
79
README.md
Normal file
@@ -0,0 +1,79 @@
|
||||

|
||||
|
||||
What the ...?
|
||||
=============
|
||||
**Cryptsetup** is utility used to conveniently setup disk encryption based
|
||||
on [DMCrypt](https://gitlab.com/cryptsetup/cryptsetup/wikis/DMCrypt) kernel module.
|
||||
|
||||
These include **plain** **dm-crypt** volumes, **LUKS** volumes, **loop-AES**
|
||||
and **TrueCrypt** (including **VeraCrypt** extension) format.
|
||||
|
||||
Project also includes **veritysetup** utility used to conveniently setup
|
||||
[DMVerity](https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity) block integrity checking kernel module.
|
||||
|
||||
LUKS Design
|
||||
-----------
|
||||
**LUKS** is the standard for Linux hard disk encryption. By providing a standard on-disk-format, it does not
|
||||
only facilitate compatibility among distributions, but also provides secure management of multiple user passwords.
|
||||
In contrast to existing solution, LUKS stores all setup necessary setup information in the partition header,
|
||||
enabling the user to transport or migrate his data seamlessly.
|
||||
|
||||
Why LUKS?
|
||||
---------
|
||||
* compatiblity via standardization,
|
||||
* secure against low entropy attacks,
|
||||
* support for multiple keys,
|
||||
* effective passphrase revocation,
|
||||
* free.
|
||||
|
||||
[Project home page](https://gitlab.com/cryptsetup/cryptsetup/).
|
||||
-----------------
|
||||
|
||||
[Frequently asked questions (FAQ)](https://gitlab.com/cryptsetup/cryptsetup/wikis/FrequentlyAskedQuestions)
|
||||
--------------------------------
|
||||
|
||||
Download
|
||||
--------
|
||||
All release tarballs and release notes are hosted on [kernel.org](https://www.kernel.org/pub/linux/utils/cryptsetup/).
|
||||
|
||||
**The latest cryptsetup version is 1.7.0**
|
||||
* [cryptsetup-1.7.0.tar.xz](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.7/cryptsetup-1.7.0.tar.xz)
|
||||
* Signature [cryptsetup-1.7.0.tar.sign](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.7/cryptsetup-1.7.0.tar.sign)
|
||||
_(You need to decompress file first to check signature.)_
|
||||
* [Cryptsetup 1.7.0 Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.7/v1.7.0-ReleaseNotes).
|
||||
|
||||
Previous versions
|
||||
* [Version 1.6.8](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.6/cryptsetup-1.6.8.tar.xz) -
|
||||
[Signature](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.6/cryptsetup-1.6.8.tar.sign) -
|
||||
[Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.6/v1.6.8-ReleaseNotes).
|
||||
* [Version 1.6.7](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.6/cryptsetup-1.6.7.tar.xz) -
|
||||
[Signature](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.6/cryptsetup-1.6.7.tar.sign) -
|
||||
[Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.6/v1.6.7-ReleaseNotes).
|
||||
* [Version 1.6.6](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.6/cryptsetup-1.6.6.tar.xz) -
|
||||
[Signature](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.6/cryptsetup-1.6.6.tar.sign) -
|
||||
[Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.6/v1.6.6-ReleaseNotes).
|
||||
* [Version 1.6.5](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.6/cryptsetup-1.6.5.tar.xz) -
|
||||
[Signature](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.6/cryptsetup-1.6.5.tar.sign) -
|
||||
[Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.6/v1.6.5-ReleaseNotes).
|
||||
* [Version 1.6.4](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.6/cryptsetup-1.6.4.tar.xz) -
|
||||
[Signature](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.6/cryptsetup-1.6.4.tar.sign) -
|
||||
[Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.6/v1.6.4-ReleaseNotes).
|
||||
|
||||
Source and API docs
|
||||
-------------------
|
||||
For development version code, please refer to [source](https://gitlab.com/cryptsetup/cryptsetup/tree/master) page,
|
||||
mirror on [kernel.org](https://git.kernel.org/cgit/utils/cryptsetup/cryptsetup.git/) or [GitHub](https://github.com/mbroz/cryptsetup).
|
||||
|
||||
For libcryptsetup documentation see [libcryptsetup API](https://gitlab.com/cryptsetup/cryptsetup/wikis/API/index.html) page.
|
||||
|
||||
NLS PO files are maintained by [TranslationProject](http://translationproject.org/domain/cryptsetup.html).
|
||||
|
||||
Help!
|
||||
-----
|
||||
Please always read [FAQ](https://gitlab.com/cryptsetup/cryptsetup/wikis/FrequentlyAskedQuestions) first.
|
||||
For cryptsetup and LUKS related questions, please use the dm-crypt mailing list, [dm-crypt@saout.de](mailto:dm-crypt@saout.de).
|
||||
|
||||
If you want to subscribe just send an empty mail to [dm-crypt-subscribe@saout.de](mailto:dm-crypt-subscribe@saout.de).
|
||||
|
||||
You can also browse [list archive](http://www.saout.de/pipermail/dm-crypt/) or read it through
|
||||
[web interface](http://news.gmane.org/gmane.linux.kernel.device-mapper.dm-crypt).
|
||||
4
TODO
4
TODO
@@ -4,5 +4,5 @@ Version 1.7:
|
||||
- TRIM for keyslots
|
||||
- Do we need crypt_data_path() - path to data device (if differs)?
|
||||
- Resync ETA time is not accurate, calculate it better (last minute window?).
|
||||
- Crypt benchmark cannot ttest ECB mode.
|
||||
- Log doesn't work yet in early binary start (FIPS message).
|
||||
- Extend existing LUKS header to use another KDF? (https://password-hashing.net/)
|
||||
- Fix all crazy automake warnings (or switch to Cmake).
|
||||
|
||||
102
configure.ac
102
configure.ac
@@ -1,12 +1,11 @@
|
||||
AC_PREREQ([2.67])
|
||||
AC_INIT([cryptsetup],[1.6.2])
|
||||
AC_INIT([cryptsetup],[1.7.0])
|
||||
|
||||
dnl library version from <major>.<minor>.<release>[-<suffix>]
|
||||
LIBCRYPTSETUP_VERSION=$(echo $PACKAGE_VERSION | cut -f1 -d-)
|
||||
LIBCRYPTSETUP_VERSION_INFO=9:0:5
|
||||
dnl library file name for FIPS selfcheck
|
||||
LIBCRYPTSETUP_VERSION_FIPS="libcryptsetup.so.4"
|
||||
LIBCRYPTSETUP_VERSION_INFO=11:0:7
|
||||
|
||||
AM_SILENT_RULES([yes])
|
||||
AC_CONFIG_SRCDIR(src/cryptsetup.c)
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
||||
@@ -16,8 +15,8 @@ AC_CONFIG_HEADERS([config.h:config.h.in])
|
||||
# http://lists.gnu.org/archive/html/automake/2013-01/msg00060.html
|
||||
|
||||
# For old automake use this
|
||||
#AM_INIT_AUTOMAKE(dist-bzip2)
|
||||
AM_INIT_AUTOMAKE([dist-bzip2 1.12 serial-tests])
|
||||
#AM_INIT_AUTOMAKE(dist-xz)
|
||||
AM_INIT_AUTOMAKE([dist-xz 1.12 serial-tests])
|
||||
|
||||
if test "x$prefix" = "xNONE"; then
|
||||
sysconfdir=/etc
|
||||
@@ -48,7 +47,8 @@ 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.])
|
||||
@@ -60,6 +60,7 @@ AC_TYPE_OFF_T
|
||||
AC_SYS_LARGEFILE
|
||||
AC_FUNC_FSEEKO
|
||||
AC_PROG_GCC_TRADITIONAL
|
||||
AC_FUNC_STRERROR_R
|
||||
|
||||
dnl ==========================================================================
|
||||
|
||||
@@ -75,25 +76,17 @@ AC_SUBST(POPT_LIBS, $LIBS)
|
||||
LIBS=$saved_LIBS
|
||||
|
||||
dnl ==========================================================================
|
||||
dnl FIPS extensions
|
||||
dnl FIPS extensions (only for RHEL)
|
||||
AC_ARG_ENABLE([fips], AS_HELP_STRING([--enable-fips],[enable FIPS mode restrictions]),
|
||||
[with_fips=$enableval],
|
||||
[with_fips=no])
|
||||
|
||||
if test "x$with_fips" = "xyes"; then
|
||||
AC_DEFINE(ENABLE_FIPS, 1, [Enable FIPS mode restrictions])
|
||||
AC_DEFINE_UNQUOTED(LIBCRYPTSETUP_VERSION_FIPS, ["$LIBCRYPTSETUP_VERSION_FIPS"],
|
||||
[library file name for FIPS selfcheck])
|
||||
|
||||
if test "x$enable_static" = "xyes" -o "x$enable_static_cryptsetup" = "xyes" ; then
|
||||
AC_MSG_ERROR([Static build is not compatible with FIPS.])
|
||||
fi
|
||||
|
||||
saved_LIBS=$LIBS
|
||||
AC_CHECK_LIB(fipscheck, FIPSCHECK_verify, ,[AC_MSG_ERROR([You need the fipscheck library.])])
|
||||
AC_SUBST(FIPSCHECK_LIBS, $LIBS)
|
||||
LIBS=$saved_LIBS
|
||||
|
||||
fi
|
||||
|
||||
AC_DEFUN([NO_FIPS], [
|
||||
@@ -104,12 +97,14 @@ AC_DEFUN([NO_FIPS], [
|
||||
|
||||
dnl ==========================================================================
|
||||
dnl pwquality library (cryptsetup CLI only)
|
||||
AC_ARG_ENABLE([pwquality], AS_HELP_STRING([--enable-pwquality],[enable password quality checking]),
|
||||
[with_pwquality=$enableval],
|
||||
[with_pwquality=no])
|
||||
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])
|
||||
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.]))
|
||||
|
||||
@@ -117,6 +112,31 @@ if test "x$with_pwquality" = "xyes"; then
|
||||
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
|
||||
|
||||
@@ -128,10 +148,22 @@ AC_DEFUN([CONFIGURE_GCRYPT], [
|
||||
fi
|
||||
dnl Check if we can use gcrypt PBKDF2 (1.6.0 supports empty password)
|
||||
AC_ARG_ENABLE([gcrypt-pbkdf2], AS_HELP_STRING([--enable-gcrypt-pbkdf2],[force enable internal gcrypt PBKDF2]),
|
||||
[use_internal_pbkdf2=0],
|
||||
[AM_PATH_LIBGCRYPT([1.6.0], [use_internal_pbkdf2=0], [use_internal_pbkdf2=1])])
|
||||
if test "x$enableval" = "xyes"; then
|
||||
[use_internal_pbkdf2=0]
|
||||
else
|
||||
[use_internal_pbkdf2=1]
|
||||
fi,
|
||||
[AM_PATH_LIBGCRYPT([1.6.1], [use_internal_pbkdf2=0], [use_internal_pbkdf2=1])])
|
||||
AM_PATH_LIBGCRYPT($GCRYPT_REQ_VERSION,,[AC_MSG_ERROR([You need the gcrypt library.])])
|
||||
|
||||
AC_MSG_CHECKING([if internal cryptsetup PBKDF2 is compiled-in])
|
||||
if test $use_internal_pbkdf2 = 0; then
|
||||
AC_MSG_RESULT([no])
|
||||
else
|
||||
AC_MSG_RESULT([yes])
|
||||
NO_FIPS([])
|
||||
fi
|
||||
|
||||
if test x$enable_static_cryptsetup = xyes; then
|
||||
saved_LIBS=$LIBS
|
||||
LIBS="$saved_LIBS $LIBGCRYPT_LIBS -static"
|
||||
@@ -159,8 +191,8 @@ AC_DEFUN([CONFIGURE_OPENSSL], [
|
||||
if test x$enable_static_cryptsetup = xyes; then
|
||||
saved_PKG_CONFIG=$PKG_CONFIG
|
||||
PKG_CONFIG="$PKG_CONFIG --static"
|
||||
PKG_CHECK_MODULES([OPENSSL], [openssl])
|
||||
CRYPTO_STATIC_LIBS=$OPENSSL_LIBS
|
||||
PKG_CHECK_MODULES([OPENSSL_STATIC], [openssl])
|
||||
CRYPTO_STATIC_LIBS=$OPENSSL_STATIC_LIBS
|
||||
PKG_CONFIG=$saved_PKG_CONFIG
|
||||
fi
|
||||
NO_FIPS([])
|
||||
@@ -202,13 +234,13 @@ AC_DEFUN([CONFIGURE_NETTLE], [
|
||||
[AC_MSG_ERROR([You need Nettle cryptographic library.])])
|
||||
|
||||
saved_LIBS=$LIBS
|
||||
AC_CHECK_LIB(nettle, nettle_ripemd160_init,,
|
||||
[AC_MSG_ERROR([You need Nettle library version 2.4 or more recent.])])
|
||||
AC_CHECK_LIB(nettle, nettle_pbkdf2_hmac_sha256,,
|
||||
[AC_MSG_ERROR([You need Nettle library version 2.6 or more recent.])])
|
||||
CRYPTO_LIBS=$LIBS
|
||||
LIBS=$saved_LIBS
|
||||
|
||||
CRYPTO_STATIC_LIBS=$CRYPTO_LIBS
|
||||
use_internal_pbkdf2=1
|
||||
use_internal_pbkdf2=0
|
||||
NO_FIPS([])
|
||||
])
|
||||
|
||||
@@ -340,13 +372,14 @@ 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([LIBCRYPTSETUP_VERSION])
|
||||
AC_SUBST([LIBCRYPTSETUP_VERSION_INFO])
|
||||
AC_SUBST([LIBCRYPTSETUP_VERSION_FIPS])
|
||||
|
||||
dnl ==========================================================================
|
||||
AC_ARG_ENABLE([dev-random], AS_HELP_STRING([--enable-dev-random],
|
||||
@@ -377,8 +410,12 @@ AC_ARG_ENABLE([python], AS_HELP_STRING([--enable-python],[enable Python bindings
|
||||
[with_python=$enableval],
|
||||
[with_python=no])
|
||||
|
||||
AC_ARG_WITH([python_version],
|
||||
AS_HELP_STRING([--with-python_version=VERSION], [required Python version [2.6]]),
|
||||
[PYTHON_VERSION=$withval], [PYTHON_VERSION=2.6])
|
||||
|
||||
if test "x$with_python" = "xyes"; then
|
||||
AM_PATH_PYTHON([2.4])
|
||||
AM_PATH_PYTHON([$PYTHON_VERSION])
|
||||
|
||||
if ! test -x "$PYTHON-config" ; then
|
||||
AC_MSG_ERROR([Cannot find python development packages to build bindings])
|
||||
@@ -386,6 +423,9 @@ if test "x$with_python" = "xyes"; then
|
||||
|
||||
PYTHON_INCLUDES=$($PYTHON-config --includes)
|
||||
AC_SUBST(PYTHON_INCLUDES)
|
||||
|
||||
PYTHON_LIBS=$($PYTHON-config --libs)
|
||||
AC_SUBST(PYTHON_LIBS)
|
||||
fi
|
||||
AM_CONDITIONAL([PYTHON_CRYPTSETUP], [test "x$with_python" = "xyes"])
|
||||
|
||||
@@ -395,11 +435,11 @@ 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], [xts-plain64])
|
||||
CS_NUM_WITH([luks1-keybits],[key length in bits for LUKS1], [256])
|
||||
CS_NUM_WITH([luks1-iter-time],[PBKDF2 iteration time for LUKS1 (in ms)], [1000])
|
||||
CS_NUM_WITH([luks1-iter-time],[PBKDF2 iteration time for LUKS1 (in ms)], [2000])
|
||||
|
||||
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])
|
||||
|
||||
@@ -834,16 +834,16 @@
|
||||
* lib/utils.c: Add read|write_blockwise functions, to use in
|
||||
O_DIRECT file accesses.
|
||||
|
||||
2004-03-11 Thursday 15:52 Christophe Saout <christophe@saout.de>
|
||||
2004-03-11 Thursday 15:52 Jana Saout <jana@saout.de>
|
||||
|
||||
* lib/blockdev.h: BLKGETSIZE64 really uses size_t as third
|
||||
argument, the rest is wrong.
|
||||
|
||||
2004-03-10 Wednesday 17:50 Christophe Saout <christophe@saout.de>
|
||||
2004-03-10 Wednesday 17:50 Jana Saout <jana@saout.de>
|
||||
|
||||
* lib/: libcryptsetup.h, libdevmapper.c: Small fixes.
|
||||
|
||||
2004-03-09 Tuesday 21:41 Christophe Saout <christophe@saout.de>
|
||||
2004-03-09 Tuesday 21:41 Jana Saout <jana@saout.de>
|
||||
|
||||
* lib/internal.h, lib/libcryptsetup.h, lib/libdevmapper.c,
|
||||
lib/setup.c, po/de.po, src/cryptsetup.c: Added internal flags to
|
||||
@@ -851,7 +851,7 @@
|
||||
add a function to free the memory. Also add a readonly flag to
|
||||
libcryptsetup.
|
||||
|
||||
2004-03-09 Tuesday 16:03 Christophe Saout <christophe@saout.de>
|
||||
2004-03-09 Tuesday 16:03 Jana Saout <jana@saout.de>
|
||||
|
||||
* ChangeLog, configure.in, setup-gettext, lib/Makefile.am,
|
||||
lib/backends.c, lib/blockdev.h, lib/gcrypt.c, lib/internal.h,
|
||||
@@ -859,7 +859,7 @@
|
||||
lib/utils.c, po/de.po, src/Makefile.am, src/cryptsetup.c: More
|
||||
reorganization work.
|
||||
|
||||
2004-03-08 Monday 01:38 Christophe Saout <christophe@saout.de>
|
||||
2004-03-08 Monday 01:38 Jana Saout <jana@saout.de>
|
||||
|
||||
* ChangeLog, Makefile.am, acinclude.m4, configure.in,
|
||||
lib/Makefile.am, lib/backends.c, lib/blockdev.h, lib/gcrypt.c,
|
||||
@@ -867,19 +867,19 @@
|
||||
src/Makefile.am: BLKGETSIZE64 fixes and started modularity
|
||||
enhancements
|
||||
|
||||
2004-03-04 Thursday 21:06 Christophe Saout <christophe@saout.de>
|
||||
2004-03-04 Thursday 21:06 Jana Saout <jana@saout.de>
|
||||
|
||||
* Makefile.am, po/de.po, src/cryptsetup.c, src/cryptsetup.h: First
|
||||
backward compatible working version.
|
||||
|
||||
2004-03-04 Thursday 00:42 Christophe Saout <christophe@saout.de>
|
||||
2004-03-04 Thursday 00:42 Jana Saout <jana@saout.de>
|
||||
|
||||
* NEWS, AUTHORS, ChangeLog, Makefile.am, README, autogen.sh,
|
||||
configure.in, setup-gettext, po/ChangeLog, po/LINGUAS,
|
||||
po/POTFILES.in, po/de.po, src/cryptsetup.c, src/cryptsetup.h,
|
||||
src/Makefile.am (utags: initial): Initial checkin.
|
||||
|
||||
2004-03-04 Thursday 00:42 Christophe Saout <christophe@saout.de>
|
||||
2004-03-04 Thursday 00:42 Jana Saout <jana@saout.de>
|
||||
|
||||
* NEWS, AUTHORS, ChangeLog, Makefile.am, README, autogen.sh,
|
||||
configure.in, setup-gettext, po/ChangeLog, po/LINGUAS,
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
* in a persistent way on the device. Keyslot area is an array beyond LUKS header, where
|
||||
* volume key is stored in the encrypted form using user input passphrase. For more info about
|
||||
* LUKS keyslots and how it's actually protected, please look at
|
||||
* <A HREF="http://code.google.com/p/cryptsetup/wiki/Specification">LUKS specification</A>.
|
||||
* <A HREF="https://gitlab.com/cryptsetup/cryptsetup/wikis/Specification">LUKS specification</A>.
|
||||
* There are two basic methods to create a new keyslot:
|
||||
*
|
||||
* @subsection ckeyslot_vol crypt_keyslot_add_by_volume_key()
|
||||
|
||||
50
docs/v1.6.3-ReleaseNotes
Normal file
50
docs/v1.6.3-ReleaseNotes
Normal 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
57
docs/v1.6.4-ReleaseNotes
Normal 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
54
docs/v1.6.5-ReleaseNotes
Normal 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
29
docs/v1.6.6-ReleaseNotes
Normal 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
84
docs/v1.6.7-ReleaseNotes
Normal 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
47
docs/v1.6.8-ReleaseNotes
Normal 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
81
docs/v1.7.0-ReleaseNotes
Normal 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.
|
||||
@@ -39,7 +39,6 @@ libcryptsetup_la_LIBADD = \
|
||||
@UUID_LIBS@ \
|
||||
@DEVMAPPER_LIBS@ \
|
||||
@CRYPTO_LIBS@ \
|
||||
@FIPSCHECK_LIBS@ \
|
||||
$(common_ldadd)
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* cryptsetup plain device helper functions
|
||||
*
|
||||
* Copyright (C) 2004, Christophe Saout <christophe@saout.de>
|
||||
* Copyright (C) 2004, Jana Saout <jana@saout.de>
|
||||
* Copyright (C) 2010-2012 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2010-2012, Milan Broz
|
||||
*
|
||||
@@ -21,7 +21,7 @@
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "libcryptsetup.h"
|
||||
@@ -83,7 +83,11 @@ int crypt_plain_hash(struct crypt_device *ctx __attribute__((unused)),
|
||||
/* hash[:hash_length] */
|
||||
if ((s = strchr(hash_name_buf, ':'))) {
|
||||
*s = '\0';
|
||||
hash_size = atoi(++s);
|
||||
s++;
|
||||
if (!*s || sscanf(s, "%zd", &hash_size) != 1) {
|
||||
log_dbg("Hash length is not a number");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (hash_size > key_size) {
|
||||
log_dbg("Hash length %zd > key length %zd",
|
||||
hash_size, key_size);
|
||||
@@ -95,7 +99,16 @@ int crypt_plain_hash(struct crypt_device *ctx __attribute__((unused)),
|
||||
pad_size = 0;
|
||||
}
|
||||
|
||||
r = hash(hash_name_buf, hash_size, key, passphrase_size, passphrase);
|
||||
/* No hash, copy passphrase directly */
|
||||
if (!strcmp(hash_name_buf, "plain")) {
|
||||
if (passphrase_size < hash_size) {
|
||||
log_dbg("Too short plain passphrase.");
|
||||
return -EINVAL;
|
||||
}
|
||||
memcpy(key, passphrase, hash_size);
|
||||
r = 0;
|
||||
} else
|
||||
r = hash(hash_name_buf, hash_size, key, passphrase_size, passphrase);
|
||||
|
||||
if (r == 0 && pad_size)
|
||||
memset(key + hash_size, 0, pad_size);
|
||||
|
||||
@@ -5,7 +5,7 @@ noinst_LTLIBRARIES = libcrypto_backend.la
|
||||
libcrypto_backend_la_CFLAGS = $(AM_CFLAGS) -Wall @CRYPTO_CFLAGS@
|
||||
|
||||
libcrypto_backend_la_SOURCES = crypto_backend.h \
|
||||
crypto_cipher_kernel.c pbkdf_check.c crc32.c
|
||||
crypto_cipher_kernel.c crypto_storage.c pbkdf_check.c crc32.c
|
||||
|
||||
if CRYPTO_BACKEND_GCRYPT
|
||||
libcrypto_backend_la_SOURCES += crypto_gcrypt.c
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* crypto backend implementation
|
||||
*
|
||||
* Copyright (C) 2010-2012, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2010-2012, Milan Broz
|
||||
* Copyright (C) 2010-2014, Milan Broz
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -28,6 +28,7 @@ struct crypt_device;
|
||||
struct crypt_hash;
|
||||
struct crypt_hmac;
|
||||
struct crypt_cipher;
|
||||
struct crypt_storage;
|
||||
|
||||
int crypt_backend_init(struct crypt_device *ctx);
|
||||
|
||||
@@ -57,9 +58,9 @@ int crypt_backend_rng(char *buffer, size_t length, int quality, int fips);
|
||||
|
||||
/* PBKDF*/
|
||||
int crypt_pbkdf_check(const char *kdf, const char *hash,
|
||||
const char *password, size_t password_size,
|
||||
const char *salt, size_t salt_size,
|
||||
uint64_t *iter_secs);
|
||||
const char *password, size_t password_length,
|
||||
const char *salt, size_t salt_length,
|
||||
size_t key_length, uint64_t *iter_secs);
|
||||
int crypt_pbkdf(const char *kdf, const char *hash,
|
||||
const char *password, size_t password_length,
|
||||
const char *salt, size_t salt_length,
|
||||
@@ -72,13 +73,15 @@ int pkcs5_pbkdf2(const char *hash,
|
||||
const char *P, size_t Plen,
|
||||
const char *S, size_t Slen,
|
||||
unsigned int c,
|
||||
unsigned int dkLen,char *DK);
|
||||
unsigned int dkLen, char *DK,
|
||||
unsigned int hash_block_size);
|
||||
#endif
|
||||
|
||||
/* CRC32 */
|
||||
uint32_t crypt_crc32(uint32_t seed, const unsigned char *buf, size_t len);
|
||||
|
||||
/* ciphers */
|
||||
int crypt_cipher_blocksize(const char *name);
|
||||
int crypt_cipher_init(struct crypt_cipher **ctx, const char *name,
|
||||
const char *mode, const void *buffer, size_t length);
|
||||
int crypt_cipher_destroy(struct crypt_cipher *ctx);
|
||||
@@ -89,4 +92,21 @@ int crypt_cipher_decrypt(struct crypt_cipher *ctx,
|
||||
const char *in, char *out, size_t length,
|
||||
const char *iv, size_t iv_length);
|
||||
|
||||
/* storage encryption wrappers */
|
||||
int crypt_storage_init(struct crypt_storage **ctx, uint64_t sector_start,
|
||||
const char *cipher, const char *cipher_mode,
|
||||
char *key, size_t key_length);
|
||||
int crypt_storage_destroy(struct crypt_storage *ctx);
|
||||
int crypt_storage_decrypt(struct crypt_storage *ctx, uint64_t sector,
|
||||
size_t count, char *buffer);
|
||||
int crypt_storage_encrypt(struct crypt_storage *ctx, uint64_t sector,
|
||||
size_t count, char *buffer);
|
||||
|
||||
/* Memzero helper (memset on stack can be optimized out) */
|
||||
static inline void crypt_backend_memzero(void *s, size_t n)
|
||||
{
|
||||
volatile uint8_t *p = (volatile uint8_t *)s;
|
||||
while(n--) *p++ = 0;
|
||||
}
|
||||
|
||||
#endif /* _CRYPTO_BACKEND_H */
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Linux kernel userspace API crypto backend implementation (skcipher)
|
||||
*
|
||||
* Copyright (C) 2012, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2012, Milan Broz
|
||||
* Copyright (C) 2012-2014, Milan Broz
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -44,6 +44,50 @@ struct crypt_cipher {
|
||||
int opfd;
|
||||
};
|
||||
|
||||
struct cipher_alg {
|
||||
const char *name;
|
||||
int blocksize;
|
||||
};
|
||||
|
||||
/* FIXME: Getting block size should be dynamic from cipher backend. */
|
||||
static struct cipher_alg cipher_algs[] = {
|
||||
{ "cipher_null", 16 },
|
||||
{ "aes", 16 },
|
||||
{ "serpent", 16 },
|
||||
{ "twofish", 16 },
|
||||
{ "anubis", 16 },
|
||||
{ "blowfish", 8 },
|
||||
{ "camellia", 16 },
|
||||
{ "cast5", 8 },
|
||||
{ "cast6", 16 },
|
||||
{ "des", 8 },
|
||||
{ "des3_ede", 8 },
|
||||
{ "khazad", 8 },
|
||||
{ "seed", 16 },
|
||||
{ "tea", 8 },
|
||||
{ "xtea", 8 },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
static struct cipher_alg *_get_alg(const char *name)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (name && cipher_algs[i].name) {
|
||||
if (!strcasecmp(name, cipher_algs[i].name))
|
||||
return &cipher_algs[i];
|
||||
i++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int crypt_cipher_blocksize(const char *name)
|
||||
{
|
||||
struct cipher_alg *ca = _get_alg(name);
|
||||
|
||||
return ca ? ca->blocksize : -EINVAL;
|
||||
}
|
||||
|
||||
/* Shared with hash kernel backend */
|
||||
int crypt_kernel_socket_init(struct sockaddr_alg *sa, int *tfmfd, int *opfd);
|
||||
|
||||
@@ -99,7 +143,8 @@ int crypt_cipher_init(struct crypt_cipher **ctx, const char *name,
|
||||
return r;
|
||||
}
|
||||
|
||||
if (setsockopt(h->tfmfd, SOL_ALG, ALG_SET_KEY, buffer, length) == -1) {
|
||||
if (length && strcmp(name, "cipher_null") &&
|
||||
setsockopt(h->tfmfd, SOL_ALG, ALG_SET_KEY, buffer, length) == -1) {
|
||||
crypt_cipher_destroy(h);
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -142,6 +187,9 @@ static int crypt_cipher_crypt(struct crypt_cipher *ctx,
|
||||
|
||||
/* Set encrypt/decrypt operation */
|
||||
header = CMSG_FIRSTHDR(&msg);
|
||||
if (!header)
|
||||
return -EINVAL;
|
||||
|
||||
header->cmsg_level = SOL_ALG;
|
||||
header->cmsg_type = ALG_SET_OP;
|
||||
header->cmsg_len = CMSG_LEN(sizeof(*type));
|
||||
@@ -169,7 +217,7 @@ static int crypt_cipher_crypt(struct crypt_cipher *ctx,
|
||||
if (len != (ssize_t)length)
|
||||
r = -EIO;
|
||||
bad:
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
crypt_backend_memzero(buffer, sizeof(buffer));
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -202,6 +250,11 @@ int crypt_cipher_destroy(struct crypt_cipher *ctx)
|
||||
|
||||
#else /* ENABLE_AF_ALG */
|
||||
|
||||
int crypt_cipher_blocksize(const char *name)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int crypt_cipher_init(struct crypt_cipher **ctx, const char *name,
|
||||
const char *mode, const void *buffer, size_t length)
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* GCRYPT crypto backend implementation
|
||||
*
|
||||
* Copyright (C) 2010-2012, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2010-2012, Milan Broz
|
||||
* Copyright (C) 2010-2014, Milan Broz
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
static int crypto_backend_initialised = 0;
|
||||
static int crypto_backend_secmem = 1;
|
||||
static int crypto_backend_whirlpool_bug = -1;
|
||||
static char version[64];
|
||||
|
||||
struct crypt_hash {
|
||||
@@ -42,6 +43,44 @@ struct crypt_hmac {
|
||||
int hash_len;
|
||||
};
|
||||
|
||||
/*
|
||||
* Test for wrong Whirlpool variant,
|
||||
* Ref: http://lists.gnupg.org/pipermail/gcrypt-devel/2014-January/002889.html
|
||||
*/
|
||||
static void crypt_hash_test_whirlpool_bug(void)
|
||||
{
|
||||
struct crypt_hash *h;
|
||||
char buf[2] = "\0\0", hash_out1[64], hash_out2[64];
|
||||
int r;
|
||||
|
||||
if (crypto_backend_whirlpool_bug >= 0)
|
||||
return;
|
||||
|
||||
crypto_backend_whirlpool_bug = 0;
|
||||
if (crypt_hash_init(&h, "whirlpool"))
|
||||
return;
|
||||
|
||||
/* One shot */
|
||||
if ((r = crypt_hash_write(h, &buf[0], 2)) ||
|
||||
(r = crypt_hash_final(h, hash_out1, 64))) {
|
||||
crypt_hash_destroy(h);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Split buf (crypt_hash_final resets hash state) */
|
||||
if ((r = crypt_hash_write(h, &buf[0], 1)) ||
|
||||
(r = crypt_hash_write(h, &buf[1], 1)) ||
|
||||
(r = crypt_hash_final(h, hash_out2, 64))) {
|
||||
crypt_hash_destroy(h);
|
||||
return;
|
||||
}
|
||||
|
||||
crypt_hash_destroy(h);
|
||||
|
||||
if (memcmp(hash_out1, hash_out2, 64))
|
||||
crypto_backend_whirlpool_bug = 1;
|
||||
}
|
||||
|
||||
int crypt_backend_init(struct crypt_device *ctx)
|
||||
{
|
||||
if (crypto_backend_initialised)
|
||||
@@ -70,10 +109,15 @@ int crypt_backend_init(struct crypt_device *ctx)
|
||||
gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
|
||||
}
|
||||
|
||||
snprintf(version, 64, "gcrypt %s%s",
|
||||
gcry_check_version(NULL),
|
||||
crypto_backend_secmem ? "" : ", secmem disabled");
|
||||
crypto_backend_initialised = 1;
|
||||
crypt_hash_test_whirlpool_bug();
|
||||
|
||||
snprintf(version, 64, "gcrypt %s%s%s",
|
||||
gcry_check_version(NULL),
|
||||
crypto_backend_secmem ? "" : ", secmem disabled",
|
||||
crypto_backend_whirlpool_bug > 0 ? ", flawed whirlpool" : ""
|
||||
);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -87,6 +131,23 @@ uint32_t crypt_backend_flags(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *crypt_hash_compat_name(const char *name, unsigned int *flags)
|
||||
{
|
||||
const char *hash_name = name;
|
||||
|
||||
/* "whirlpool_gcryptbug" is out shortcut to flawed whirlpool
|
||||
* in libgcrypt < 1.6.0 */
|
||||
if (name && !strcasecmp(name, "whirlpool_gcryptbug")) {
|
||||
#if GCRYPT_VERSION_NUMBER >= 0x010601
|
||||
if (flags)
|
||||
*flags |= GCRY_MD_FLAG_BUGEMU1;
|
||||
#endif
|
||||
hash_name = "whirlpool";
|
||||
}
|
||||
|
||||
return hash_name;
|
||||
}
|
||||
|
||||
/* HASH */
|
||||
int crypt_hash_size(const char *name)
|
||||
{
|
||||
@@ -94,7 +155,7 @@ int crypt_hash_size(const char *name)
|
||||
|
||||
assert(crypto_backend_initialised);
|
||||
|
||||
hash_id = gcry_md_map_name(name);
|
||||
hash_id = gcry_md_map_name(crypt_hash_compat_name(name, NULL));
|
||||
if (!hash_id)
|
||||
return -EINVAL;
|
||||
|
||||
@@ -104,6 +165,7 @@ int crypt_hash_size(const char *name)
|
||||
int crypt_hash_init(struct crypt_hash **ctx, const char *name)
|
||||
{
|
||||
struct crypt_hash *h;
|
||||
unsigned int flags = 0;
|
||||
|
||||
assert(crypto_backend_initialised);
|
||||
|
||||
@@ -111,13 +173,13 @@ int crypt_hash_init(struct crypt_hash **ctx, const char *name)
|
||||
if (!h)
|
||||
return -ENOMEM;
|
||||
|
||||
h->hash_id = gcry_md_map_name(name);
|
||||
h->hash_id = gcry_md_map_name(crypt_hash_compat_name(name, &flags));
|
||||
if (!h->hash_id) {
|
||||
free(h);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (gcry_md_open(&h->hd, h->hash_id, 0)) {
|
||||
if (gcry_md_open(&h->hd, h->hash_id, flags)) {
|
||||
free(h);
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -173,6 +235,7 @@ int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
|
||||
const void *buffer, size_t length)
|
||||
{
|
||||
struct crypt_hmac *h;
|
||||
unsigned int flags = GCRY_MD_FLAG_HMAC;
|
||||
|
||||
assert(crypto_backend_initialised);
|
||||
|
||||
@@ -180,13 +243,13 @@ int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
|
||||
if (!h)
|
||||
return -ENOMEM;
|
||||
|
||||
h->hash_id = gcry_md_map_name(name);
|
||||
h->hash_id = gcry_md_map_name(crypt_hash_compat_name(name, &flags));
|
||||
if (!h->hash_id) {
|
||||
free(h);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (gcry_md_open(&h->hd, h->hash_id, GCRY_MD_FLAG_HMAC)) {
|
||||
if (gcry_md_open(&h->hd, h->hash_id, flags)) {
|
||||
free(h);
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -261,15 +324,17 @@ int crypt_pbkdf(const char *kdf, const char *hash,
|
||||
char *key, size_t key_length,
|
||||
unsigned int iterations)
|
||||
{
|
||||
const char *hash_name = crypt_hash_compat_name(hash, NULL);
|
||||
|
||||
#if USE_INTERNAL_PBKDF2
|
||||
if (!kdf || strncmp(kdf, "pbkdf2", 6))
|
||||
return -EINVAL;
|
||||
|
||||
return pkcs5_pbkdf2(hash, password, password_length, salt, salt_length,
|
||||
iterations, key_length, key);
|
||||
return pkcs5_pbkdf2(hash_name, password, password_length, salt, salt_length,
|
||||
iterations, key_length, key, 0);
|
||||
|
||||
#else /* USE_INTERNAL_PBKDF2 */
|
||||
int hash_id = gcry_md_map_name(hash);
|
||||
int hash_id = gcry_md_map_name(hash_name);
|
||||
int kdf_id;
|
||||
|
||||
if (!hash_id)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Linux kernel userspace API crypto backend implementation
|
||||
*
|
||||
* Copyright (C) 2010-2012, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2010-2012, Milan Broz
|
||||
* Copyright (C) 2010-2014, Milan Broz
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -44,15 +44,16 @@ struct hash_alg {
|
||||
const char *name;
|
||||
const char *kernel_name;
|
||||
int length;
|
||||
unsigned int block_length;
|
||||
};
|
||||
|
||||
static struct hash_alg hash_algs[] = {
|
||||
{ "sha1", "sha1", 20 },
|
||||
{ "sha256", "sha256", 32 },
|
||||
{ "sha512", "sha512", 64 },
|
||||
{ "ripemd160", "rmd160", 20 },
|
||||
{ "whirlpool", "wp512", 64 },
|
||||
{ NULL, NULL, 0 }
|
||||
{ "sha1", "sha1", 20, 64 },
|
||||
{ "sha256", "sha256", 32, 64 },
|
||||
{ "sha512", "sha512", 64, 128 },
|
||||
{ "ripemd160", "rmd160", 20, 64 },
|
||||
{ "whirlpool", "wp512", 64, 64 },
|
||||
{ NULL, NULL, 0, 0 }
|
||||
};
|
||||
|
||||
struct crypt_hash {
|
||||
@@ -76,7 +77,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;
|
||||
|
||||
@@ -289,9 +290,11 @@ int crypt_pbkdf(const char *kdf, const char *hash,
|
||||
char *key, size_t key_length,
|
||||
unsigned int iterations)
|
||||
{
|
||||
if (!kdf || strncmp(kdf, "pbkdf2", 6))
|
||||
struct hash_alg *ha = _get_alg(hash);
|
||||
|
||||
if (!ha || !kdf || strncmp(kdf, "pbkdf2", 6))
|
||||
return -EINVAL;
|
||||
|
||||
return pkcs5_pbkdf2(hash, password, password_length, salt, salt_length,
|
||||
iterations, key_length, key);
|
||||
iterations, key_length, key, ha->block_length);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Nettle crypto backend implementation
|
||||
*
|
||||
* Copyright (C) 2011-2012 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2011-2012, Milan Broz
|
||||
* Copyright (C) 2011-2014, Milan Broz
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <errno.h>
|
||||
#include <nettle/sha.h>
|
||||
#include <nettle/hmac.h>
|
||||
#include <nettle/pbkdf2.h>
|
||||
#include "crypto_backend.h"
|
||||
|
||||
static char *version = "Nettle";
|
||||
@@ -265,8 +266,8 @@ int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length)
|
||||
int crypt_hmac_destroy(struct crypt_hmac *ctx)
|
||||
{
|
||||
memset(ctx->key, 0, ctx->key_length);
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
free(ctx->key);
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
free(ctx);
|
||||
return 0;
|
||||
}
|
||||
@@ -284,10 +285,21 @@ int crypt_pbkdf(const char *kdf, const char *hash,
|
||||
char *key, size_t key_length,
|
||||
unsigned int iterations)
|
||||
{
|
||||
struct crypt_hmac *h;
|
||||
int r;
|
||||
|
||||
if (!kdf || strncmp(kdf, "pbkdf2", 6))
|
||||
return -EINVAL;
|
||||
|
||||
/* FIXME: switch to internal implementation in Nettle 2.6 */
|
||||
return pkcs5_pbkdf2(hash, password, password_length, salt, salt_length,
|
||||
iterations, key_length, key);
|
||||
r = crypt_hmac_init(&h, hash, password, password_length);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
nettle_pbkdf2(&h->nettle_ctx, h->hash->nettle_hmac_update,
|
||||
h->hash->nettle_hmac_digest, h->hash->length, iterations,
|
||||
salt_length, (const uint8_t *)salt, key_length,
|
||||
(uint8_t *)key);
|
||||
crypt_hmac_destroy(h);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* NSS crypto backend implementation
|
||||
*
|
||||
* Copyright (C) 2010-2012, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2010-2012, Milan Broz
|
||||
* Copyright (C) 2010-2014, Milan Broz
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -35,14 +35,15 @@ struct hash_alg {
|
||||
SECOidTag oid;
|
||||
CK_MECHANISM_TYPE ck_type;
|
||||
int length;
|
||||
unsigned int block_length;
|
||||
};
|
||||
|
||||
static struct hash_alg hash_algs[] = {
|
||||
{ "sha1", SEC_OID_SHA1, CKM_SHA_1_HMAC, 20 },
|
||||
{ "sha256", SEC_OID_SHA256, CKM_SHA256_HMAC, 32 },
|
||||
{ "sha384", SEC_OID_SHA384, CKM_SHA384_HMAC, 48 },
|
||||
{ "sha512", SEC_OID_SHA512, CKM_SHA512_HMAC, 64 },
|
||||
// { "ripemd160", SEC_OID_RIPEMD160, CKM_RIPEMD160_HMAC, 20 },
|
||||
{ "sha1", SEC_OID_SHA1, CKM_SHA_1_HMAC, 20, 64 },
|
||||
{ "sha256", SEC_OID_SHA256, CKM_SHA256_HMAC, 32, 64 },
|
||||
{ "sha384", SEC_OID_SHA384, CKM_SHA384_HMAC, 48, 128 },
|
||||
{ "sha512", SEC_OID_SHA512, CKM_SHA512_HMAC, 64, 128 },
|
||||
// { "ripemd160", SEC_OID_RIPEMD160, CKM_RIPEMD160_HMAC, 20, 64 },
|
||||
{ NULL, 0, 0, 0 }
|
||||
};
|
||||
|
||||
@@ -163,7 +164,7 @@ int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length)
|
||||
return -EINVAL;
|
||||
|
||||
memcpy(buffer, tmp, length);
|
||||
memset(tmp, 0, sizeof(tmp));
|
||||
crypt_backend_memzero(tmp, sizeof(tmp));
|
||||
|
||||
if (tmp_len < length)
|
||||
return -EINVAL;
|
||||
@@ -265,7 +266,7 @@ int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length)
|
||||
return -EINVAL;
|
||||
|
||||
memcpy(buffer, tmp, length);
|
||||
memset(tmp, 0, sizeof(tmp));
|
||||
crypt_backend_memzero(tmp, sizeof(tmp));
|
||||
|
||||
if (tmp_len < length)
|
||||
return -EINVAL;
|
||||
@@ -308,9 +309,11 @@ int crypt_pbkdf(const char *kdf, const char *hash,
|
||||
char *key, size_t key_length,
|
||||
unsigned int iterations)
|
||||
{
|
||||
if (!kdf || strncmp(kdf, "pbkdf2", 6))
|
||||
struct hash_alg *ha = _get_alg(hash);
|
||||
|
||||
if (!ha || !kdf || strncmp(kdf, "pbkdf2", 6))
|
||||
return -EINVAL;
|
||||
|
||||
return pkcs5_pbkdf2(hash, password, password_length, salt, salt_length,
|
||||
iterations, key_length, key);
|
||||
iterations, key_length, key, ha->block_length);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* OPENSSL crypto backend implementation
|
||||
*
|
||||
* Copyright (C) 2010-2012, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2010-2012, Milan Broz
|
||||
* Copyright (C) 2010-2014, Milan Broz
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -133,7 +133,7 @@ int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length)
|
||||
return -EINVAL;
|
||||
|
||||
memcpy(buffer, tmp, length);
|
||||
memset(tmp, 0, sizeof(tmp));
|
||||
crypt_backend_memzero(tmp, sizeof(tmp));
|
||||
|
||||
if (tmp_len < length)
|
||||
return -EINVAL;
|
||||
@@ -203,7 +203,7 @@ int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length)
|
||||
HMAC_Final(&ctx->md, tmp, &tmp_len);
|
||||
|
||||
memcpy(buffer, tmp, length);
|
||||
memset(tmp, 0, sizeof(tmp));
|
||||
crypt_backend_memzero(tmp, sizeof(tmp));
|
||||
|
||||
if (tmp_len < length)
|
||||
return -EINVAL;
|
||||
|
||||
293
lib/crypto_backend/crypto_storage.c
Normal file
293
lib/crypto_backend/crypto_storage.c
Normal file
@@ -0,0 +1,293 @@
|
||||
/*
|
||||
* Generic wrapper for storage encryption modes and Initial Vectors
|
||||
* (reimplementation of some functions from Linux dm-crypt kernel)
|
||||
*
|
||||
* Copyright (C) 2014, Milan Broz
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this file; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include "bitops.h"
|
||||
#include "crypto_backend.h"
|
||||
|
||||
#define SECTOR_SHIFT 9
|
||||
#define SECTOR_SIZE (1 << SECTOR_SHIFT)
|
||||
|
||||
/*
|
||||
* Internal IV helper
|
||||
* IV documentation: https://gitlab.com/cryptsetup/cryptsetup/wikis/DMCrypt
|
||||
*/
|
||||
struct crypt_sector_iv {
|
||||
enum { IV_NONE, IV_NULL, IV_PLAIN, IV_PLAIN64, IV_ESSIV, IV_BENBI } type;
|
||||
int iv_size;
|
||||
char *iv;
|
||||
struct crypt_cipher *essiv_cipher;
|
||||
int benbi_shift;
|
||||
};
|
||||
|
||||
/* Block encryption storage context */
|
||||
struct crypt_storage {
|
||||
uint64_t sector_start;
|
||||
struct crypt_cipher *cipher;
|
||||
struct crypt_sector_iv cipher_iv;
|
||||
};
|
||||
|
||||
static int int_log2(unsigned int x)
|
||||
{
|
||||
int r = 0;
|
||||
for (x >>= 1; x > 0; x >>= 1)
|
||||
r++;
|
||||
return r;
|
||||
}
|
||||
|
||||
static int crypt_sector_iv_init(struct crypt_sector_iv *ctx,
|
||||
const char *cipher_name, const char *mode_name,
|
||||
const char *iv_name, char *key, size_t key_length)
|
||||
{
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
|
||||
ctx->iv_size = crypt_cipher_blocksize(cipher_name);
|
||||
if (ctx->iv_size < 0)
|
||||
return -ENOENT;
|
||||
|
||||
if (!iv_name ||
|
||||
!strcmp(cipher_name, "cipher_null") ||
|
||||
!strcmp(mode_name, "ecb")) {
|
||||
ctx->type = IV_NONE;
|
||||
ctx->iv_size = 0;
|
||||
return 0;
|
||||
} else if (!strcasecmp(iv_name, "null")) {
|
||||
ctx->type = IV_NULL;
|
||||
} else if (!strcasecmp(iv_name, "plain64")) {
|
||||
ctx->type = IV_PLAIN64;
|
||||
} else if (!strcasecmp(iv_name, "plain")) {
|
||||
ctx->type = IV_PLAIN;
|
||||
} else if (!strncasecmp(iv_name, "essiv:", 6)) {
|
||||
struct crypt_hash *h = NULL;
|
||||
char *hash_name = strchr(iv_name, ':');
|
||||
int hash_size;
|
||||
char tmp[256];
|
||||
int r;
|
||||
|
||||
if (!hash_name)
|
||||
return -EINVAL;
|
||||
|
||||
hash_size = crypt_hash_size(++hash_name);
|
||||
if (hash_size < 0)
|
||||
return -ENOENT;
|
||||
|
||||
if ((unsigned)hash_size > sizeof(tmp))
|
||||
return -EINVAL;
|
||||
|
||||
if (crypt_hash_init(&h, hash_name))
|
||||
return -EINVAL;
|
||||
|
||||
r = crypt_hash_write(h, key, key_length);
|
||||
if (r) {
|
||||
crypt_hash_destroy(h);
|
||||
return r;
|
||||
}
|
||||
|
||||
r = crypt_hash_final(h, tmp, hash_size);
|
||||
crypt_hash_destroy(h);
|
||||
if (r) {
|
||||
crypt_backend_memzero(tmp, sizeof(tmp));
|
||||
return r;
|
||||
}
|
||||
|
||||
r = crypt_cipher_init(&ctx->essiv_cipher, cipher_name, "ecb",
|
||||
tmp, hash_size);
|
||||
crypt_backend_memzero(tmp, sizeof(tmp));
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
ctx->type = IV_ESSIV;
|
||||
} else if (!strncasecmp(iv_name, "benbi", 5)) {
|
||||
int log = int_log2(ctx->iv_size);
|
||||
if (log > SECTOR_SHIFT)
|
||||
return -EINVAL;
|
||||
|
||||
ctx->type = IV_BENBI;
|
||||
ctx->benbi_shift = SECTOR_SHIFT - log;
|
||||
} else
|
||||
return -ENOENT;
|
||||
|
||||
ctx->iv = malloc(ctx->iv_size);
|
||||
if (!ctx->iv)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int crypt_sector_iv_generate(struct crypt_sector_iv *ctx, uint64_t sector)
|
||||
{
|
||||
uint64_t val;
|
||||
|
||||
switch (ctx->type) {
|
||||
case IV_NONE:
|
||||
break;
|
||||
case IV_NULL:
|
||||
memset(ctx->iv, 0, ctx->iv_size);
|
||||
break;
|
||||
case IV_PLAIN:
|
||||
memset(ctx->iv, 0, ctx->iv_size);
|
||||
*(uint32_t *)ctx->iv = cpu_to_le32(sector & 0xffffffff);
|
||||
break;
|
||||
case IV_PLAIN64:
|
||||
memset(ctx->iv, 0, ctx->iv_size);
|
||||
*(uint64_t *)ctx->iv = cpu_to_le64(sector);
|
||||
break;
|
||||
case IV_ESSIV:
|
||||
memset(ctx->iv, 0, ctx->iv_size);
|
||||
*(uint64_t *)ctx->iv = cpu_to_le64(sector);
|
||||
return crypt_cipher_encrypt(ctx->essiv_cipher,
|
||||
ctx->iv, ctx->iv, ctx->iv_size, NULL, 0);
|
||||
break;
|
||||
case IV_BENBI:
|
||||
memset(ctx->iv, 0, ctx->iv_size);
|
||||
val = cpu_to_be64((sector << ctx->benbi_shift) + 1);
|
||||
memcpy(ctx->iv + ctx->iv_size - sizeof(val), &val, sizeof(val));
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int crypt_sector_iv_destroy(struct crypt_sector_iv *ctx)
|
||||
{
|
||||
if (ctx->type == IV_ESSIV)
|
||||
crypt_cipher_destroy(ctx->essiv_cipher);
|
||||
|
||||
if (ctx->iv) {
|
||||
memset(ctx->iv, 0, ctx->iv_size);
|
||||
free(ctx->iv);
|
||||
}
|
||||
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Block encryption storage wrappers */
|
||||
|
||||
int crypt_storage_init(struct crypt_storage **ctx,
|
||||
uint64_t sector_start,
|
||||
const char *cipher,
|
||||
const char *cipher_mode,
|
||||
char *key, size_t key_length)
|
||||
{
|
||||
struct crypt_storage *s;
|
||||
char mode_name[64];
|
||||
char *cipher_iv = NULL;
|
||||
int r = -EIO;
|
||||
|
||||
s = malloc(sizeof(*s));
|
||||
if (!s)
|
||||
return -ENOMEM;
|
||||
memset(s, 0, sizeof(*s));
|
||||
|
||||
/* Remove IV if present */
|
||||
strncpy(mode_name, cipher_mode, sizeof(mode_name));
|
||||
mode_name[sizeof(mode_name) - 1] = 0;
|
||||
cipher_iv = strchr(mode_name, '-');
|
||||
if (cipher_iv) {
|
||||
*cipher_iv = '\0';
|
||||
cipher_iv++;
|
||||
}
|
||||
|
||||
r = crypt_cipher_init(&s->cipher, cipher, mode_name, key, key_length);
|
||||
if (r) {
|
||||
crypt_storage_destroy(s);
|
||||
return r;
|
||||
}
|
||||
|
||||
r = crypt_sector_iv_init(&s->cipher_iv, cipher, mode_name, cipher_iv, key, key_length);
|
||||
if (r) {
|
||||
crypt_storage_destroy(s);
|
||||
return r;
|
||||
}
|
||||
|
||||
s->sector_start = sector_start;
|
||||
|
||||
*ctx = s;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crypt_storage_decrypt(struct crypt_storage *ctx,
|
||||
uint64_t sector, size_t count,
|
||||
char *buffer)
|
||||
{
|
||||
unsigned int i;
|
||||
int r = 0;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
r = crypt_sector_iv_generate(&ctx->cipher_iv, sector + i);
|
||||
if (r)
|
||||
break;
|
||||
r = crypt_cipher_decrypt(ctx->cipher,
|
||||
&buffer[i * SECTOR_SIZE],
|
||||
&buffer[i * SECTOR_SIZE],
|
||||
SECTOR_SIZE,
|
||||
ctx->cipher_iv.iv,
|
||||
ctx->cipher_iv.iv_size);
|
||||
if (r)
|
||||
break;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int crypt_storage_encrypt(struct crypt_storage *ctx,
|
||||
uint64_t sector, size_t count,
|
||||
char *buffer)
|
||||
{
|
||||
unsigned int i;
|
||||
int r = 0;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
r = crypt_sector_iv_generate(&ctx->cipher_iv, sector + i);
|
||||
if (r)
|
||||
break;
|
||||
r = crypt_cipher_encrypt(ctx->cipher,
|
||||
&buffer[i * SECTOR_SIZE],
|
||||
&buffer[i * SECTOR_SIZE],
|
||||
SECTOR_SIZE,
|
||||
ctx->cipher_iv.iv,
|
||||
ctx->cipher_iv.iv_size);
|
||||
if (r)
|
||||
break;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int crypt_storage_destroy(struct crypt_storage *ctx)
|
||||
{
|
||||
if (!ctx)
|
||||
return 0;
|
||||
|
||||
crypt_sector_iv_destroy(&ctx->cipher_iv);
|
||||
|
||||
if (ctx->cipher)
|
||||
crypt_cipher_destroy(ctx->cipher);
|
||||
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
free(ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
*
|
||||
* cryptsetup related changes
|
||||
* Copyright (C) 2012, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2012-2014, Milan Broz
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -26,6 +27,25 @@
|
||||
#include <alloca.h>
|
||||
#include "crypto_backend.h"
|
||||
|
||||
static int hash_buf(const char *src, size_t src_len,
|
||||
char *dst, size_t dst_len,
|
||||
const char *hash_name)
|
||||
{
|
||||
struct crypt_hash *hd = NULL;
|
||||
int r;
|
||||
|
||||
if (crypt_hash_init(&hd, hash_name))
|
||||
return -EINVAL;
|
||||
|
||||
r = crypt_hash_write(hd, src, src_len);
|
||||
|
||||
if (!r)
|
||||
r = crypt_hash_final(hd, dst, dst_len);
|
||||
|
||||
crypt_hash_destroy(hd);
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* 5.2 PBKDF2
|
||||
*
|
||||
@@ -52,17 +72,26 @@
|
||||
* Output: DK derived key, a dkLen-octet string
|
||||
*/
|
||||
|
||||
/*
|
||||
* if hash_block_size is not zero, the HMAC key is pre-hashed
|
||||
* inside this function.
|
||||
* This prevents situation when crypto backend doesn't support
|
||||
* long HMAC keys or it tries hash long key in every iteration
|
||||
* (because of crypt_final() cannot do simple key reset.
|
||||
*/
|
||||
|
||||
#define MAX_PRF_BLOCK_LEN 80
|
||||
|
||||
int pkcs5_pbkdf2(const char *hash,
|
||||
const char *P, size_t Plen,
|
||||
const char *S, size_t Slen,
|
||||
unsigned int c, unsigned int dkLen,
|
||||
char *DK)
|
||||
char *DK, unsigned int hash_block_size)
|
||||
{
|
||||
struct crypt_hmac *hmac;
|
||||
char U[MAX_PRF_BLOCK_LEN];
|
||||
char T[MAX_PRF_BLOCK_LEN];
|
||||
char P_hash[MAX_PRF_BLOCK_LEN];
|
||||
int i, k, rc = -EINVAL;
|
||||
unsigned int u, hLen, l, r;
|
||||
size_t tmplen = Slen + 4;
|
||||
@@ -152,8 +181,18 @@ int pkcs5_pbkdf2(const char *hash,
|
||||
*
|
||||
*/
|
||||
|
||||
if (crypt_hmac_init(&hmac, hash, P, Plen))
|
||||
return -EINVAL;
|
||||
/* If hash_block_size is provided, hash password in advance. */
|
||||
if (hash_block_size > 0 && Plen > hash_block_size) {
|
||||
if (hash_buf(P, Plen, P_hash, hLen, hash))
|
||||
return -EINVAL;
|
||||
|
||||
if (crypt_hmac_init(&hmac, hash, P_hash, hLen))
|
||||
return -EINVAL;
|
||||
crypt_backend_memzero(P_hash, sizeof(P_hash));
|
||||
} else {
|
||||
if (crypt_hmac_init(&hmac, hash, P, Plen))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 1; (unsigned int) i <= l; i++) {
|
||||
memset(T, 0, hLen);
|
||||
@@ -185,5 +224,203 @@ int pkcs5_pbkdf2(const char *hash,
|
||||
rc = 0;
|
||||
out:
|
||||
crypt_hmac_destroy(hmac);
|
||||
crypt_backend_memzero(U, sizeof(U));
|
||||
crypt_backend_memzero(T, sizeof(T));
|
||||
crypt_backend_memzero(tmp, tmplen);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
#if 0
|
||||
#include <stdio.h>
|
||||
|
||||
struct test_vector {
|
||||
const char *hash;
|
||||
unsigned int hash_block_length;
|
||||
unsigned int iterations;
|
||||
const char *password;
|
||||
unsigned int password_length;
|
||||
const char *salt;
|
||||
unsigned int salt_length;
|
||||
const char *output;
|
||||
unsigned int output_length;
|
||||
};
|
||||
|
||||
struct test_vector test_vectors[] = {
|
||||
/* RFC 3962 */
|
||||
{
|
||||
"sha1", 64, 1,
|
||||
"password", 8,
|
||||
"ATHENA.MIT.EDUraeburn", 21,
|
||||
"\xcd\xed\xb5\x28\x1b\xb2\xf8\x01"
|
||||
"\x56\x5a\x11\x22\xb2\x56\x35\x15"
|
||||
"\x0a\xd1\xf7\xa0\x4b\xb9\xf3\xa3"
|
||||
"\x33\xec\xc0\xe2\xe1\xf7\x08\x37", 32
|
||||
}, {
|
||||
"sha1", 64, 2,
|
||||
"password", 8,
|
||||
"ATHENA.MIT.EDUraeburn", 21,
|
||||
"\x01\xdb\xee\x7f\x4a\x9e\x24\x3e"
|
||||
"\x98\x8b\x62\xc7\x3c\xda\x93\x5d"
|
||||
"\xa0\x53\x78\xb9\x32\x44\xec\x8f"
|
||||
"\x48\xa9\x9e\x61\xad\x79\x9d\x86", 32
|
||||
}, {
|
||||
"sha1", 64, 1200,
|
||||
"password", 8,
|
||||
"ATHENA.MIT.EDUraeburn", 21,
|
||||
"\x5c\x08\xeb\x61\xfd\xf7\x1e\x4e"
|
||||
"\x4e\xc3\xcf\x6b\xa1\xf5\x51\x2b"
|
||||
"\xa7\xe5\x2d\xdb\xc5\xe5\x14\x2f"
|
||||
"\x70\x8a\x31\xe2\xe6\x2b\x1e\x13", 32
|
||||
}, {
|
||||
"sha1", 64, 5,
|
||||
"password", 8,
|
||||
"\0224VxxV4\022", 8, // "\x1234567878563412
|
||||
"\xd1\xda\xa7\x86\x15\xf2\x87\xe6"
|
||||
"\xa1\xc8\xb1\x20\xd7\x06\x2a\x49"
|
||||
"\x3f\x98\xd2\x03\xe6\xbe\x49\xa6"
|
||||
"\xad\xf4\xfa\x57\x4b\x6e\x64\xee", 32
|
||||
}, {
|
||||
"sha1", 64, 1200,
|
||||
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
|
||||
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 64,
|
||||
"pass phrase equals block size", 29,
|
||||
"\x13\x9c\x30\xc0\x96\x6b\xc3\x2b"
|
||||
"\xa5\x5f\xdb\xf2\x12\x53\x0a\xc9"
|
||||
"\xc5\xec\x59\xf1\xa4\x52\xf5\xcc"
|
||||
"\x9a\xd9\x40\xfe\xa0\x59\x8e\xd1", 32
|
||||
}, {
|
||||
"sha1", 64, 1200,
|
||||
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
|
||||
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 65,
|
||||
"pass phrase exceeds block size", 30,
|
||||
"\x9c\xca\xd6\xd4\x68\x77\x0c\xd5"
|
||||
"\x1b\x10\xe6\xa6\x87\x21\xbe\x61"
|
||||
"\x1a\x8b\x4d\x28\x26\x01\xdb\x3b"
|
||||
"\x36\xbe\x92\x46\x91\x5e\xc8\x2a", 32
|
||||
}, {
|
||||
"sha1", 64, 50,
|
||||
"\360\235\204\236", 4, // g-clef ("\xf09d849e)
|
||||
"EXAMPLE.COMpianist", 18,
|
||||
"\x6b\x9c\xf2\x6d\x45\x45\x5a\x43"
|
||||
"\xa5\xb8\xbb\x27\x6a\x40\x3b\x39"
|
||||
"\xe7\xfe\x37\xa0\xc4\x1e\x02\xc2"
|
||||
"\x81\xff\x30\x69\xe1\xe9\x4f\x52", 32
|
||||
}, {
|
||||
/* RFC-6070 */
|
||||
"sha1", 64, 1,
|
||||
"password", 8,
|
||||
"salt", 4,
|
||||
"\x0c\x60\xc8\x0f\x96\x1f\x0e\x71\xf3\xa9"
|
||||
"\xb5\x24\xaf\x60\x12\x06\x2f\xe0\x37\xa6", 20
|
||||
}, {
|
||||
"sha1", 64, 2,
|
||||
"password", 8,
|
||||
"salt", 4,
|
||||
"\xea\x6c\x01\x4d\xc7\x2d\x6f\x8c\xcd\x1e"
|
||||
"\xd9\x2a\xce\x1d\x41\xf0\xd8\xde\x89\x57", 20
|
||||
}, {
|
||||
"sha1", 64, 4096,
|
||||
"password", 8,
|
||||
"salt", 4,
|
||||
"\x4b\x00\x79\x01\xb7\x65\x48\x9a\xbe\xad"
|
||||
"\x49\xd9\x26\xf7\x21\xd0\x65\xa4\x29\xc1", 20
|
||||
}, {
|
||||
"sha1", 64, 16777216,
|
||||
"password", 8,
|
||||
"salt", 4,
|
||||
"\xee\xfe\x3d\x61\xcd\x4d\xa4\xe4\xe9\x94"
|
||||
"\x5b\x3d\x6b\xa2\x15\x8c\x26\x34\xe9\x84", 20
|
||||
}, {
|
||||
"sha1", 64, 4096,
|
||||
"passwordPASSWORDpassword", 24,
|
||||
"saltSALTsaltSALTsaltSALTsaltSALTsalt", 36,
|
||||
"\x3d\x2e\xec\x4f\xe4\x1c\x84\x9b\x80\xc8"
|
||||
"\xd8\x36\x62\xc0\xe4\x4a\x8b\x29\x1a\x96"
|
||||
"\x4c\xf2\xf0\x70\x38", 25
|
||||
}, {
|
||||
"sha1", 64, 4096,
|
||||
"pass\0word", 9,
|
||||
"sa\0lt", 5,
|
||||
"\x56\xfa\x6a\xa7\x55\x48\x09\x9d\xcc\x37"
|
||||
"\xd7\xf0\x34\x25\xe0\xc3", 16
|
||||
}, {
|
||||
/* empty password test */
|
||||
"sha1", 64, 2,
|
||||
"", 0,
|
||||
"salt", 4,
|
||||
"\x13\x3a\x4c\xe8\x37\xb4\xd2\x52\x1e\xe2"
|
||||
"\xbf\x03\xe1\x1c\x71\xca\x79\x4e\x07\x97", 20
|
||||
}, {
|
||||
/* Password exceeds block size test */
|
||||
"sha256", 64, 1200,
|
||||
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
|
||||
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 65,
|
||||
"pass phrase exceeds block size", 30,
|
||||
"\x22\x34\x4b\xc4\xb6\xe3\x26\x75"
|
||||
"\xa8\x09\x0f\x3e\xa8\x0b\xe0\x1d"
|
||||
"\x5f\x95\x12\x6a\x2c\xdd\xc3\xfa"
|
||||
"\xcc\x4a\x5e\x6d\xca\x04\xec\x58", 32
|
||||
}, {
|
||||
"sha512", 128, 1200,
|
||||
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
|
||||
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
|
||||
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
|
||||
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 129,
|
||||
"pass phrase exceeds block size", 30,
|
||||
"\x0f\xb2\xed\x2c\x0e\x6e\xfb\x7d"
|
||||
"\x7d\x8e\xdd\x58\x01\xb4\x59\x72"
|
||||
"\x99\x92\x16\x30\x5e\xa4\x36\x8d"
|
||||
"\x76\x14\x80\xf3\xe3\x7a\x22\xb9", 32
|
||||
}, {
|
||||
"whirlpool", 64, 1200,
|
||||
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
|
||||
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 65,
|
||||
"pass phrase exceeds block size", 30,
|
||||
"\x9c\x1c\x74\xf5\x88\x26\xe7\x6a"
|
||||
"\x53\x58\xf4\x0c\x39\xe7\x80\x89"
|
||||
"\x07\xc0\x31\x19\x9a\x50\xa2\x48"
|
||||
"\xf1\xd9\xfe\x78\x64\xe5\x84\x50", 32
|
||||
}
|
||||
};
|
||||
|
||||
static void printhex(const char *s, const char *buf, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
printf("%s: ", s);
|
||||
for (i = 0; i < len; i++)
|
||||
printf("\\x%02x", (unsigned char)buf[i]);
|
||||
printf("\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
static int pkcs5_pbkdf2_test_vectors(void)
|
||||
{
|
||||
char result[64];
|
||||
unsigned int i, j;
|
||||
struct test_vector *vec;
|
||||
|
||||
for (i = 0; i < (sizeof(test_vectors) / sizeof(*test_vectors)); i++) {
|
||||
vec = &test_vectors[i];
|
||||
for (j = 1; j <= vec->output_length; j++) {
|
||||
if (pkcs5_pbkdf2(vec->hash,
|
||||
vec->password, vec->password_length,
|
||||
vec->salt, vec->salt_length,
|
||||
vec->iterations,
|
||||
j, result, vec->hash_block_length)) {
|
||||
printf("pbkdf2 failed, vector %d\n", i);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (memcmp(result, vec->output, j) != 0) {
|
||||
printf("vector %u\n", i);
|
||||
printhex(" got", result, j);
|
||||
printhex("want", vec->output, j);
|
||||
return -EINVAL;
|
||||
}
|
||||
memset(result, 0, sizeof(result));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* PBKDF performance check
|
||||
* Copyright (C) 2012, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2012, Milan Broz
|
||||
* Copyright (C) 2012-2014, Milan Broz
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -18,6 +18,7 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
@@ -25,12 +26,24 @@
|
||||
|
||||
static long time_ms(struct rusage *start, struct rusage *end)
|
||||
{
|
||||
int count_kernel_time = 0;
|
||||
long ms;
|
||||
|
||||
if (crypt_backend_flags() & CRYPT_BACKEND_KERNEL)
|
||||
count_kernel_time = 1;
|
||||
|
||||
/*
|
||||
* FIXME: if there is no self usage info, count system time.
|
||||
* This seem like getrusage() bug in some hypervisors...
|
||||
*/
|
||||
if (!end->ru_utime.tv_sec && !start->ru_utime.tv_sec &&
|
||||
!end->ru_utime.tv_usec && !start->ru_utime.tv_usec)
|
||||
count_kernel_time = 1;
|
||||
|
||||
ms = (end->ru_utime.tv_sec - start->ru_utime.tv_sec) * 1000;
|
||||
ms += (end->ru_utime.tv_usec - start->ru_utime.tv_usec) / 1000;
|
||||
|
||||
if (crypt_backend_flags() & CRYPT_BACKEND_KERNEL) {
|
||||
if (count_kernel_time) {
|
||||
ms += (end->ru_stime.tv_sec - start->ru_stime.tv_sec) * 1000;
|
||||
ms += (end->ru_stime.tv_usec - start->ru_stime.tv_usec) / 1000;
|
||||
}
|
||||
@@ -40,31 +53,39 @@ static long time_ms(struct rusage *start, struct rusage *end)
|
||||
|
||||
/* This code benchmarks PBKDF and returns iterations/second using specified hash */
|
||||
int crypt_pbkdf_check(const char *kdf, const char *hash,
|
||||
const char *password, size_t password_size,
|
||||
const char *salt, size_t salt_size,
|
||||
uint64_t *iter_secs)
|
||||
const char *password, size_t password_length,
|
||||
const char *salt, size_t salt_length,
|
||||
size_t key_length, uint64_t *iter_secs)
|
||||
{
|
||||
struct rusage rstart, rend;
|
||||
int r = 0, step = 0;
|
||||
long ms = 0;
|
||||
char buf;
|
||||
char *key = NULL;
|
||||
unsigned int iterations;
|
||||
|
||||
if (!kdf || !hash)
|
||||
if (!kdf || !hash || key_length <= 0)
|
||||
return -EINVAL;
|
||||
|
||||
key = malloc(key_length);
|
||||
if (!key)
|
||||
return -ENOMEM;
|
||||
|
||||
iterations = 1 << 15;
|
||||
while (ms < 500) {
|
||||
if (getrusage(RUSAGE_SELF, &rstart) < 0)
|
||||
return -EINVAL;
|
||||
if (getrusage(RUSAGE_SELF, &rstart) < 0) {
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
r = crypt_pbkdf(kdf, hash, password, password_size, salt,
|
||||
salt_size, &buf, 1, iterations);
|
||||
r = crypt_pbkdf(kdf, hash, password, password_length, salt,
|
||||
salt_length, key, key_length, iterations);
|
||||
if (r < 0)
|
||||
return r;
|
||||
goto out;
|
||||
|
||||
if (getrusage(RUSAGE_SELF, &rend) < 0)
|
||||
return -EINVAL;
|
||||
if (getrusage(RUSAGE_SELF, &rend) < 0) {
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ms = time_ms(&rstart, &rend);
|
||||
if (ms > 500)
|
||||
@@ -79,11 +100,18 @@ int crypt_pbkdf_check(const char *kdf, const char *hash,
|
||||
else
|
||||
iterations <<= 1;
|
||||
|
||||
if (++step > 10 || !iterations)
|
||||
return -EINVAL;
|
||||
if (++step > 10 || !iterations) {
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (iter_secs)
|
||||
*iter_secs = (iterations * 1000) / ms;
|
||||
out:
|
||||
if (key) {
|
||||
crypt_backend_memzero(key, key_length);
|
||||
free(key);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* libcryptsetup - cryptsetup library internal
|
||||
*
|
||||
* Copyright (C) 2004, Christophe Saout <christophe@saout.de>
|
||||
* Copyright (C) 2004, Jana Saout <jana@saout.de>
|
||||
* Copyright (C) 2004-2007, Clemens Fruhwirth <clemens@endorphin.org>
|
||||
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2009-2012, Milan Broz
|
||||
@@ -95,6 +95,8 @@ char *crypt_lookup_dev(const char *dev_id);
|
||||
int crypt_dev_is_rotational(int major, int minor);
|
||||
int crypt_dev_is_partition(const char *dev_path);
|
||||
char *crypt_get_partition_device(const char *dev_path, uint64_t offset, uint64_t size);
|
||||
char *crypt_get_base_device(const char *dev_path);
|
||||
uint64_t crypt_dev_partition_offset(const char *dev_path);
|
||||
|
||||
ssize_t write_blockwise(int fd, int bsize, void *buf, size_t count);
|
||||
ssize_t read_blockwise(int fd, int bsize, void *_buf, size_t count);
|
||||
@@ -103,7 +105,7 @@ ssize_t write_lseek_blockwise(int fd, int bsize, char *buf, size_t count, off_t
|
||||
unsigned crypt_getpagesize(void);
|
||||
int init_crypto(struct crypt_device *ctx);
|
||||
|
||||
void logger(struct crypt_device *cd, int class, const char *file, int line, const char *format, ...);
|
||||
void logger(struct crypt_device *cd, int class, const char *file, int line, const char *format, ...) __attribute__ ((format (printf, 5, 6)));
|
||||
#define log_dbg(x...) logger(NULL, CRYPT_LOG_DEBUG, __FILE__, __LINE__, x)
|
||||
#define log_std(c, x...) logger(c, CRYPT_LOG_NORMAL, __FILE__, __LINE__, x)
|
||||
#define log_verbose(c, x...) logger(c, CRYPT_LOG_VERBOSE, __FILE__, __LINE__, x)
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
/*
|
||||
* libcryptsetup - cryptsetup library
|
||||
*
|
||||
* Copyright (C) 2004, Christophe Saout <christophe@saout.de>
|
||||
* Copyright (C) 2004, Jana Saout <jana@saout.de>
|
||||
* Copyright (C) 2004-2007, Clemens Fruhwirth <clemens@endorphin.org>
|
||||
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2009-2012, Milan Broz
|
||||
* Copyright (C) 2009-2015, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2009-2015, Milan Broz
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -136,7 +136,7 @@ void crypt_log(struct crypt_device *cd, int level, const char *msg);
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* Set confirmation callback (yes/no)
|
||||
* Set confirmation callback (yes/no).
|
||||
*
|
||||
* If code need confirmation (like resetting uuid or restoring LUKS header from file)
|
||||
* this function is called. If not defined, everything is confirmed.
|
||||
@@ -156,7 +156,7 @@ void crypt_set_confirm_callback(struct crypt_device *cd,
|
||||
void *usrptr);
|
||||
|
||||
/**
|
||||
* Set password query callback.
|
||||
* Set password query callback. DEPRECATED
|
||||
*
|
||||
* If code need @e _interactive_ query for password, this callback is called.
|
||||
* If not defined, compiled-in default is called (uses terminal input).
|
||||
@@ -176,6 +176,7 @@ void crypt_set_confirm_callback(struct crypt_device *cd,
|
||||
* @note Only zero terminated passwords can be entered this way, for complex
|
||||
* use API functions directly.
|
||||
* @note Maximal length of password is limited to @e length @e - @e 1 (minimal 511 chars)
|
||||
* @note This function is DEPRECATED and will be removed in future versions.
|
||||
*
|
||||
* @see Callback function is used in these call provided, that certain conditions are met:
|
||||
* @li crypt_keyslot_add_by_passphrase
|
||||
@@ -192,7 +193,7 @@ void crypt_set_password_callback(struct crypt_device *cd,
|
||||
|
||||
/**
|
||||
* Set timeout for interactive password entry using default
|
||||
* password callback
|
||||
* password callback. DEPRECATED
|
||||
*
|
||||
* @param cd crypt device handle
|
||||
* @param timeout_sec timeout in seconds
|
||||
@@ -200,16 +201,18 @@ void crypt_set_password_callback(struct crypt_device *cd,
|
||||
void crypt_set_timeout(struct crypt_device *cd, uint64_t timeout_sec);
|
||||
|
||||
/**
|
||||
* Set number of retries in case password input has been incorrect
|
||||
* Set number of retries in case password input has been incorrect. DEPRECATED.
|
||||
*
|
||||
* @param cd crypt device handle
|
||||
* @param tries the number
|
||||
*
|
||||
* @note This function is DEPRECATED and will be removed in future versions.
|
||||
*/
|
||||
void crypt_set_password_retry(struct crypt_device *cd, int tries);
|
||||
|
||||
/**
|
||||
* Set how long should cryptsetup iterate in PBKDF2 function.
|
||||
* Default value heads towards the iterations which takes around 1 second
|
||||
* Default value heads towards the iterations which takes around 1 second.
|
||||
*
|
||||
* @param cd crypt device handle
|
||||
* @param iteration_time_ms the time in ms
|
||||
@@ -220,10 +223,12 @@ void crypt_set_iterarion_time(struct crypt_device *cd, uint64_t iteration_time_m
|
||||
|
||||
/**
|
||||
* Set whether passphrase will be verified on input
|
||||
* (user has to input same passphrase twice)
|
||||
* (user has to input same passphrase twice). DEPRECATED
|
||||
*
|
||||
* @param cd crypt device handle
|
||||
* @param password_verify @e 0 = false, @e !0 true
|
||||
*
|
||||
* @note This function is DEPRECATED and will be removed in future versions.
|
||||
*/
|
||||
void crypt_set_password_verify(struct crypt_device *cd, int password_verify);
|
||||
|
||||
@@ -261,7 +266,7 @@ int crypt_set_data_device(struct crypt_device *cd, const char *device);
|
||||
void crypt_set_rng_type(struct crypt_device *cd, int rng_type);
|
||||
|
||||
/**
|
||||
* Get which RNG (random number generator) is used for generating long term key
|
||||
* Get which RNG (random number generator) is used for generating long term key.
|
||||
*
|
||||
* @param cd crypt device handle
|
||||
* @return RNG type on success or negative errno value otherwise.
|
||||
@@ -272,7 +277,7 @@ int crypt_get_rng_type(struct crypt_device *cd);
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* Helper to lock/unlock memory to avoid swap sensitive data to disk
|
||||
* Helper to lock/unlock memory to avoid swap sensitive data to disk.
|
||||
*
|
||||
* @param cd crypt device handle, can be @e NULL
|
||||
* @param lock 0 to unlock otherwise lock memory
|
||||
@@ -304,7 +309,7 @@ int crypt_memory_lock(struct crypt_device *cd, int lock);
|
||||
#define CRYPT_LOOPAES "LOOPAES"
|
||||
/** dm-verity mode */
|
||||
#define CRYPT_VERITY "VERITY"
|
||||
/** TCRYPT (TrueCrypt-compatible) mode */
|
||||
/** TCRYPT (TrueCrypt-compatible and VeraCrypt-compatible) mode */
|
||||
#define CRYPT_TCRYPT "TCRYPT"
|
||||
|
||||
/**
|
||||
@@ -317,7 +322,7 @@ const char *crypt_get_type(struct crypt_device *cd);
|
||||
|
||||
/**
|
||||
*
|
||||
* Structure used as parameter for PLAIN device type
|
||||
* Structure used as parameter for PLAIN device type.
|
||||
*
|
||||
* @see crypt_format
|
||||
*/
|
||||
@@ -329,7 +334,7 @@ struct crypt_params_plain {
|
||||
};
|
||||
|
||||
/**
|
||||
* Structure used as parameter for LUKS device type
|
||||
* Structure used as parameter for LUKS device type.
|
||||
*
|
||||
* @see crypt_format, crypt_load
|
||||
*
|
||||
@@ -345,7 +350,7 @@ struct crypt_params_luks1 {
|
||||
|
||||
/**
|
||||
*
|
||||
* Structure used as parameter for loop-AES device type
|
||||
* Structure used as parameter for loop-AES device type.
|
||||
*
|
||||
* @see crypt_format
|
||||
*
|
||||
@@ -358,7 +363,7 @@ struct crypt_params_loopaes {
|
||||
|
||||
/**
|
||||
*
|
||||
* Structure used as parameter for dm-verity device type
|
||||
* Structure used as parameter for dm-verity device type.
|
||||
*
|
||||
* @see crypt_format, crypt_load
|
||||
*
|
||||
@@ -386,7 +391,7 @@ struct crypt_params_verity {
|
||||
|
||||
/**
|
||||
*
|
||||
* Structure used as parameter for TCRYPT device type
|
||||
* Structure used as parameter for TCRYPT device type.
|
||||
*
|
||||
* @see crypt_load
|
||||
*
|
||||
@@ -403,7 +408,7 @@ struct crypt_params_tcrypt {
|
||||
uint32_t flags; /**< CRYPT_TCRYPT* flags */
|
||||
};
|
||||
|
||||
/** Include legacy modes ehn scannig for header*/
|
||||
/** Include legacy modes when scanning for header */
|
||||
#define CRYPT_TCRYPT_LEGACY_MODES (1 << 0)
|
||||
/** Try to load hidden header (describing hidden device) */
|
||||
#define CRYPT_TCRYPT_HIDDEN_HEADER (1 << 1)
|
||||
@@ -411,11 +416,16 @@ struct crypt_params_tcrypt {
|
||||
#define CRYPT_TCRYPT_BACKUP_HEADER (1 << 2)
|
||||
/** Device contains encrypted system (with boot loader) */
|
||||
#define CRYPT_TCRYPT_SYSTEM_HEADER (1 << 3)
|
||||
/** Include VeraCrypt modes when scanning for header,
|
||||
* all other TCRYPT flags applies as well.
|
||||
* VeraCrypt device is reported as TCRYPT type.
|
||||
*/
|
||||
#define CRYPT_TCRYPT_VERA_MODES (1 << 4)
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* Create (format) new crypt device (and possible header on-disk) but not activates it.
|
||||
* Create (format) new crypt device (and possible header on-disk) but do not activate it.
|
||||
*
|
||||
* @pre @e cd contains initialized and not formatted device context (device type must @b not be set)
|
||||
*
|
||||
@@ -445,7 +455,7 @@ int crypt_format(struct crypt_device *cd,
|
||||
void *params);
|
||||
|
||||
/**
|
||||
* Set new UUID for already existing device
|
||||
* Set new UUID for already existing device.
|
||||
*
|
||||
* @param cd crypt device handle
|
||||
* @param uuid requested UUID or @e NULL if it should be generated
|
||||
@@ -458,7 +468,7 @@ int crypt_set_uuid(struct crypt_device *cd,
|
||||
const char *uuid);
|
||||
|
||||
/**
|
||||
* Load crypt device parameters from on-disk header
|
||||
* Load crypt device parameters from on-disk header.
|
||||
*
|
||||
* @param cd crypt device handle
|
||||
* @param requested_type @link crypt_type @endlink or @e NULL for all known
|
||||
@@ -477,7 +487,7 @@ int crypt_load(struct crypt_device *cd,
|
||||
void *params);
|
||||
|
||||
/**
|
||||
* Try to repair crypt device on-disk header if invalid
|
||||
* Try to repair crypt device on-disk header if invalid.
|
||||
*
|
||||
* @param cd crypt device handle
|
||||
* @param requested_type @link crypt_type @endlink or @e NULL for all known
|
||||
@@ -491,7 +501,7 @@ int crypt_repair(struct crypt_device *cd,
|
||||
void *params);
|
||||
|
||||
/**
|
||||
* Resize crypt device
|
||||
* Resize crypt device.
|
||||
*
|
||||
* @param cd - crypt device handle
|
||||
* @param name - name of device to resize
|
||||
@@ -504,7 +514,7 @@ int crypt_resize(struct crypt_device *cd,
|
||||
uint64_t new_size);
|
||||
|
||||
/**
|
||||
* Suspends crypt device.
|
||||
* Suspend crypt device.
|
||||
*
|
||||
* @param cd crypt device handle, can be @e NULL
|
||||
* @param name name of device to suspend
|
||||
@@ -518,7 +528,7 @@ int crypt_suspend(struct crypt_device *cd,
|
||||
const char *name);
|
||||
|
||||
/**
|
||||
* Resumes crypt device using passphrase.
|
||||
* Resume crypt device using passphrase.
|
||||
*
|
||||
*
|
||||
* @param cd crypt device handle
|
||||
@@ -530,6 +540,8 @@ int crypt_suspend(struct crypt_device *cd,
|
||||
* @return unlocked key slot number or negative errno otherwise.
|
||||
*
|
||||
* @note Only LUKS device type is supported
|
||||
* @note If passphrase is @e NULL always use crypt_set_password_callback.
|
||||
* Internal terminal password query is DEPRECATED and will be removed in next version.
|
||||
*/
|
||||
int crypt_resume_by_passphrase(struct crypt_device *cd,
|
||||
const char *name,
|
||||
@@ -538,7 +550,7 @@ int crypt_resume_by_passphrase(struct crypt_device *cd,
|
||||
size_t passphrase_size);
|
||||
|
||||
/**
|
||||
* Resumes crypt device using key file.
|
||||
* Resume crypt device using key file.
|
||||
*
|
||||
* @param cd crypt device handle
|
||||
* @param name name of device to resume
|
||||
@@ -548,6 +560,9 @@ int crypt_resume_by_passphrase(struct crypt_device *cd,
|
||||
* @param keyfile_offset number of bytes to skip at start of keyfile
|
||||
*
|
||||
* @return unlocked key slot number or negative errno otherwise.
|
||||
*
|
||||
* @note If passphrase is @e NULL always use crypt_set_password_callback.
|
||||
* Internal terminal password query is DEPRECATED and will be removed in next version.
|
||||
*/
|
||||
int crypt_resume_by_keyfile_offset(struct crypt_device *cd,
|
||||
const char *name,
|
||||
@@ -565,7 +580,7 @@ int crypt_resume_by_keyfile(struct crypt_device *cd,
|
||||
size_t keyfile_size);
|
||||
|
||||
/**
|
||||
* Releases crypt device context and used memory.
|
||||
* Release crypt device context and used memory.
|
||||
*
|
||||
* @param cd crypt device handle
|
||||
*/
|
||||
@@ -582,7 +597,7 @@ void crypt_free(struct crypt_device *cd);
|
||||
#define CRYPT_ANY_SLOT -1
|
||||
|
||||
/**
|
||||
* Add key slot using provided passphrase
|
||||
* Add key slot using provided passphrase.
|
||||
*
|
||||
* @pre @e cd contains initialized and formatted LUKS device context
|
||||
*
|
||||
@@ -594,6 +609,9 @@ void crypt_free(struct crypt_device *cd);
|
||||
* @param new_passphrase_size size of @e new_passphrase (binary data)
|
||||
*
|
||||
* @return allocated key slot number or negative errno otherwise.
|
||||
*
|
||||
* @note If passphrase is @e NULL always use crypt_set_password_callback.
|
||||
* Internal terminal password query is DEPRECATED and will be removed in next version.
|
||||
*/
|
||||
int crypt_keyslot_add_by_passphrase(struct crypt_device *cd,
|
||||
int keyslot,
|
||||
@@ -603,7 +621,7 @@ int crypt_keyslot_add_by_passphrase(struct crypt_device *cd,
|
||||
size_t new_passphrase_size);
|
||||
|
||||
/**
|
||||
* Change defined key slot using provided passphrase
|
||||
* Change defined key slot using provided passphrase.
|
||||
*
|
||||
* @pre @e cd contains initialized and formatted LUKS device context
|
||||
*
|
||||
@@ -620,6 +638,9 @@ int crypt_keyslot_add_by_passphrase(struct crypt_device *cd,
|
||||
* @note This function is just internal implementation of luksChange
|
||||
* command to avoid reading of volume key outside libcryptsetup boundary
|
||||
* in FIPS mode.
|
||||
*
|
||||
* @note If passphrase is @e NULL always use crypt_set_password_callback.
|
||||
* Internal terminal password query is DEPRECATED and will be removed in next version.
|
||||
*/
|
||||
int crypt_keyslot_change_by_passphrase(struct crypt_device *cd,
|
||||
int keyslot_old,
|
||||
@@ -630,7 +651,7 @@ int crypt_keyslot_change_by_passphrase(struct crypt_device *cd,
|
||||
size_t new_passphrase_size);
|
||||
|
||||
/**
|
||||
* Add key slot using provided key file path
|
||||
* Add key slot using provided key file path.
|
||||
*
|
||||
* @pre @e cd contains initialized and formatted LUKS device context
|
||||
*
|
||||
@@ -645,8 +666,8 @@ int crypt_keyslot_change_by_passphrase(struct crypt_device *cd,
|
||||
*
|
||||
* @return allocated key slot number or negative errno otherwise.
|
||||
*
|
||||
* @note Note that @e keyfile can be "-" for STDIN
|
||||
*
|
||||
* @note Note that @e keyfile can be "-" for STDIN. This special handling is DEPRECATED
|
||||
* and will be removed in next version.
|
||||
*/
|
||||
int crypt_keyslot_add_by_keyfile_offset(struct crypt_device *cd,
|
||||
int keyslot,
|
||||
@@ -667,7 +688,7 @@ int crypt_keyslot_add_by_keyfile(struct crypt_device *cd,
|
||||
size_t new_keyfile_size);
|
||||
|
||||
/**
|
||||
* Add key slot using provided volume key
|
||||
* Add key slot using provided volume key.
|
||||
*
|
||||
* @pre @e cd contains initialized and formatted LUKS device context
|
||||
*
|
||||
@@ -680,6 +701,8 @@ int crypt_keyslot_add_by_keyfile(struct crypt_device *cd,
|
||||
*
|
||||
* @return allocated key slot number or negative errno otherwise.
|
||||
*
|
||||
* @note If passphrase is @e NULL always use crypt_set_password_callback.
|
||||
* Internal terminal password query is DEPRECATED and will be removed in next version.
|
||||
*/
|
||||
int crypt_keyslot_add_by_volume_key(struct crypt_device *cd,
|
||||
int keyslot,
|
||||
@@ -689,7 +712,7 @@ int crypt_keyslot_add_by_volume_key(struct crypt_device *cd,
|
||||
size_t passphrase_size);
|
||||
|
||||
/**
|
||||
* Destroy (and disable) key slot
|
||||
* Destroy (and disable) key slot.
|
||||
*
|
||||
* @pre @e cd contains initialized and formatted LUKS device context
|
||||
*
|
||||
@@ -725,6 +748,11 @@ int crypt_keyslot_destroy(struct crypt_device *cd, int keyslot);
|
||||
#define CRYPT_ACTIVATE_PRIVATE (1 << 4)
|
||||
/** corruption detected (verity), output only */
|
||||
#define CRYPT_ACTIVATE_CORRUPTED (1 << 5)
|
||||
/** use same_cpu_crypt option for dm-crypt */
|
||||
#define CRYPT_ACTIVATE_SAME_CPU_CRYPT (1 << 6)
|
||||
/** use submit_from_crypt_cpus for dm-crypt */
|
||||
#define CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS (1 << 7)
|
||||
|
||||
|
||||
/**
|
||||
* Active device runtime attributes
|
||||
@@ -737,7 +765,7 @@ struct crypt_active_device {
|
||||
};
|
||||
|
||||
/**
|
||||
* Receives runtime attributes of active crypt device
|
||||
* Receive runtime attributes of active crypt device.
|
||||
*
|
||||
* @param cd crypt device handle (can be @e NULL)
|
||||
* @param name name of active device
|
||||
@@ -753,7 +781,7 @@ int crypt_get_active_device(struct crypt_device *cd,
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* Activate device or check passphrase
|
||||
* Activate device or check passphrase.
|
||||
*
|
||||
* @param cd crypt device handle
|
||||
* @param name name of device to create, if @e NULL only check passphrase
|
||||
@@ -763,6 +791,9 @@ int crypt_get_active_device(struct crypt_device *cd,
|
||||
* @param flags activation flags
|
||||
*
|
||||
* @return unlocked key slot number or negative errno otherwise.
|
||||
*
|
||||
* @note If passphrase is @e NULL always use crypt_set_password_callback.
|
||||
* Internal terminal password query is DEPRECATED and will be removed in next version.
|
||||
*/
|
||||
int crypt_activate_by_passphrase(struct crypt_device *cd,
|
||||
const char *name,
|
||||
@@ -772,7 +803,7 @@ int crypt_activate_by_passphrase(struct crypt_device *cd,
|
||||
uint32_t flags);
|
||||
|
||||
/**
|
||||
* Activate device or check using key file
|
||||
* Activate device or check using key file.
|
||||
*
|
||||
* @param cd crypt device handle
|
||||
* @param name name of device to create, if @e NULL only check keyfile
|
||||
@@ -802,7 +833,7 @@ int crypt_activate_by_keyfile(struct crypt_device *cd,
|
||||
uint32_t flags);
|
||||
|
||||
/**
|
||||
* Activate device using provided volume key
|
||||
* Activate device using provided volume key.
|
||||
*
|
||||
*
|
||||
* @param cd crypt device handle
|
||||
@@ -842,7 +873,7 @@ int crypt_activate_by_volume_key(struct crypt_device *cd,
|
||||
int crypt_deactivate(struct crypt_device *cd, const char *name);
|
||||
|
||||
/**
|
||||
* Get volume key from of crypt device
|
||||
* Get volume key from crypt device.
|
||||
*
|
||||
* @param cd crypt device handle
|
||||
* @param keyslot use this keyslot or @e CRYPT_ANY_SLOT
|
||||
@@ -865,7 +896,7 @@ int crypt_volume_key_get(struct crypt_device *cd,
|
||||
size_t passphrase_size);
|
||||
|
||||
/**
|
||||
* Verify that provided volume key is valid for crypt device
|
||||
* Verify that provided volume key is valid for crypt device.
|
||||
*
|
||||
* @param cd crypt device handle
|
||||
* @param volume_key provided volume key
|
||||
@@ -894,7 +925,7 @@ typedef enum {
|
||||
} crypt_status_info;
|
||||
|
||||
/**
|
||||
* Get status info about device name
|
||||
* Get status info about device name.
|
||||
*
|
||||
* @param cd crypt device handle, can be @e NULL
|
||||
* @param name crypt device name
|
||||
@@ -905,7 +936,7 @@ typedef enum {
|
||||
crypt_status_info crypt_status(struct crypt_device *cd, const char *name);
|
||||
|
||||
/**
|
||||
* Dump text-formatted information about crypt or verity device to log output
|
||||
* Dump text-formatted information about crypt or verity device to log output.
|
||||
*
|
||||
* @param cd crypt device handle
|
||||
*
|
||||
@@ -914,7 +945,7 @@ crypt_status_info crypt_status(struct crypt_device *cd, const char *name);
|
||||
int crypt_dump(struct crypt_device *cd);
|
||||
|
||||
/**
|
||||
* Get cipher used in device
|
||||
* Get cipher used in device.
|
||||
*
|
||||
* @param cd crypt device handle
|
||||
*
|
||||
@@ -924,7 +955,7 @@ int crypt_dump(struct crypt_device *cd);
|
||||
const char *crypt_get_cipher(struct crypt_device *cd);
|
||||
|
||||
/**
|
||||
* Get cipher mode used in device
|
||||
* Get cipher mode used in device.
|
||||
*
|
||||
* @param cd crypt device handle
|
||||
*
|
||||
@@ -934,7 +965,7 @@ const char *crypt_get_cipher(struct crypt_device *cd);
|
||||
const char *crypt_get_cipher_mode(struct crypt_device *cd);
|
||||
|
||||
/**
|
||||
* Get device UUID
|
||||
* Get device UUID.
|
||||
*
|
||||
* @param cd crypt device handle
|
||||
*
|
||||
@@ -944,7 +975,7 @@ const char *crypt_get_cipher_mode(struct crypt_device *cd);
|
||||
const char *crypt_get_uuid(struct crypt_device *cd);
|
||||
|
||||
/**
|
||||
* Get path to underlaying device
|
||||
* Get path to underlaying device.
|
||||
*
|
||||
* @param cd crypt device handle
|
||||
*
|
||||
@@ -954,7 +985,7 @@ const char *crypt_get_uuid(struct crypt_device *cd);
|
||||
const char *crypt_get_device_name(struct crypt_device *cd);
|
||||
|
||||
/**
|
||||
* Get device offset in sectors where real data starts on underlying device)
|
||||
* Get device offset in sectors where real data starts (on underlying device).
|
||||
*
|
||||
* @param cd crypt device handle
|
||||
*
|
||||
@@ -964,7 +995,7 @@ const char *crypt_get_device_name(struct crypt_device *cd);
|
||||
uint64_t crypt_get_data_offset(struct crypt_device *cd);
|
||||
|
||||
/**
|
||||
* Get IV offset in sectors (skip)
|
||||
* Get IV offset in sectors (skip).
|
||||
*
|
||||
* @param cd crypt device handle
|
||||
*
|
||||
@@ -974,7 +1005,7 @@ uint64_t crypt_get_data_offset(struct crypt_device *cd);
|
||||
uint64_t crypt_get_iv_offset(struct crypt_device *cd);
|
||||
|
||||
/**
|
||||
* Get size (in bytes) of volume key for crypt device
|
||||
* Get size (in bytes) of volume key for crypt device.
|
||||
*
|
||||
* @param cd crypt device handle
|
||||
*
|
||||
@@ -984,7 +1015,7 @@ uint64_t crypt_get_iv_offset(struct crypt_device *cd);
|
||||
int crypt_get_volume_key_size(struct crypt_device *cd);
|
||||
|
||||
/**
|
||||
* Get device parameters for VERITY device
|
||||
* Get device parameters for VERITY device.
|
||||
*
|
||||
* @param cd crypt device handle
|
||||
* @param vp verity device info
|
||||
@@ -1007,7 +1038,7 @@ int crypt_get_verity_info(struct crypt_device *cd,
|
||||
*/
|
||||
|
||||
/**
|
||||
* Informational benchmark for ciphers
|
||||
* Informational benchmark for ciphers.
|
||||
*
|
||||
* @param cd crypt device handle
|
||||
* @param cipher (e.g. "aes")
|
||||
@@ -1019,6 +1050,9 @@ int crypt_get_verity_info(struct crypt_device *cd,
|
||||
* @param decryption_mbs measured decryption speed in MiB/s
|
||||
*
|
||||
* @return @e 0 on success or negative errno value otherwise.
|
||||
*
|
||||
* @note If encryption_buffer_size is too small and encryption time
|
||||
* cannot be properly measured, -ERANGE is returned.
|
||||
*/
|
||||
int crypt_benchmark(struct crypt_device *cd,
|
||||
const char *cipher,
|
||||
@@ -1030,7 +1064,7 @@ int crypt_benchmark(struct crypt_device *cd,
|
||||
double *decryption_mbs);
|
||||
|
||||
/**
|
||||
* Informational benchmark for KDF
|
||||
* Informational benchmark for KDF.
|
||||
*
|
||||
* @param cd crypt device handle
|
||||
* @param kdf Key derivation function (e.g. "pbkdf2")
|
||||
@@ -1071,7 +1105,7 @@ typedef enum {
|
||||
} crypt_keyslot_info;
|
||||
|
||||
/**
|
||||
* Get information about particular key slot
|
||||
* Get information about particular key slot.
|
||||
*
|
||||
*
|
||||
* @param cd crypt device handle
|
||||
@@ -1094,7 +1128,7 @@ crypt_keyslot_info crypt_keyslot_status(struct crypt_device *cd, int keyslot);
|
||||
int crypt_keyslot_max(const char *type);
|
||||
|
||||
/**
|
||||
* Get keyslot area pointers (relative to metadata device)
|
||||
* Get keyslot area pointers (relative to metadata device).
|
||||
*
|
||||
* @param cd crypt device handle
|
||||
* @param keyslot keyslot number
|
||||
@@ -1110,7 +1144,7 @@ int crypt_keyslot_area(struct crypt_device *cd,
|
||||
uint64_t *length);
|
||||
|
||||
/**
|
||||
* Backup header and keyslots to file
|
||||
* Backup header and keyslots to file.
|
||||
*
|
||||
* @param cd crypt device handle
|
||||
* @param requested_type @link crypt_type @endlink or @e NULL for all known
|
||||
@@ -1124,7 +1158,7 @@ int crypt_header_backup(struct crypt_device *cd,
|
||||
const char *backup_file);
|
||||
|
||||
/**
|
||||
* Restore header and keyslots from backup file
|
||||
* Restore header and keyslots from backup file.
|
||||
*
|
||||
*
|
||||
* @param cd crypt device handle
|
||||
@@ -1139,14 +1173,14 @@ int crypt_header_restore(struct crypt_device *cd,
|
||||
const char *backup_file);
|
||||
|
||||
/**
|
||||
* Receives last reported error
|
||||
* Receive last reported error, DEPRECATED.
|
||||
*
|
||||
* @param cd crypt device handle
|
||||
* @param buf buffef for message
|
||||
* @param size size of buffer
|
||||
*
|
||||
* @note Note that this is old API function using global context.
|
||||
* All error messages are reported also through log callback.
|
||||
* @note This function is DEPRECATED and will be removed in future versions.
|
||||
* @note All error messages are reported also through log callback.
|
||||
*/
|
||||
void crypt_last_error(struct crypt_device *cd, char *buf, size_t size);
|
||||
|
||||
@@ -1156,8 +1190,7 @@ void crypt_last_error(struct crypt_device *cd, char *buf, size_t size);
|
||||
* @param buf buffef for message
|
||||
* @param size size of buffer
|
||||
*
|
||||
* @note Note that this is old API function using global context.
|
||||
* All error messages are reported also through log callback.
|
||||
* @note This function is DEPRECATED and will be removed in future versions.
|
||||
*/
|
||||
void crypt_get_error(char *buf, size_t size);
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
/*
|
||||
* libdevmapper - device-mapper backend for cryptsetup
|
||||
*
|
||||
* Copyright (C) 2004, Christophe Saout <christophe@saout.de>
|
||||
* Copyright (C) 2004, Jana Saout <jana@saout.de>
|
||||
* Copyright (C) 2004-2007, Clemens Fruhwirth <clemens@endorphin.org>
|
||||
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2009-2012, Milan Broz
|
||||
* Copyright (C) 2009-2015, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2009-2015, Milan Broz
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -28,7 +28,7 @@
|
||||
#include <fcntl.h>
|
||||
#include <linux/fs.h>
|
||||
#include <uuid/uuid.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
@@ -86,12 +86,12 @@ static void set_dm_error(int level,
|
||||
va_start(va, f);
|
||||
if (vasprintf(&msg, f, va) > 0) {
|
||||
if (level < 4 && !_quiet_log) {
|
||||
log_err(_context, msg);
|
||||
log_err(_context, "%s", msg);
|
||||
log_err(_context, "\n");
|
||||
} else {
|
||||
/* We do not use DM visual stack backtrace here */
|
||||
if (strncmp(msg, "<backtrace>", 11))
|
||||
log_dbg(msg);
|
||||
log_dbg("%s", msg);
|
||||
}
|
||||
}
|
||||
free(msg);
|
||||
@@ -100,6 +100,18 @@ static void set_dm_error(int level,
|
||||
|
||||
static int _dm_simple(int task, const char *name, int udev_wait);
|
||||
|
||||
static int _dm_satisfies_version(unsigned target_maj, unsigned target_min,
|
||||
unsigned actual_maj, unsigned actual_min)
|
||||
{
|
||||
if (actual_maj > target_maj)
|
||||
return 1;
|
||||
|
||||
if (actual_maj == target_maj && actual_min >= target_min)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _dm_set_crypt_compat(const char *dm_version, unsigned crypt_maj,
|
||||
unsigned crypt_min, unsigned crypt_patch)
|
||||
{
|
||||
@@ -111,24 +123,32 @@ static void _dm_set_crypt_compat(const char *dm_version, unsigned crypt_maj,
|
||||
log_dbg("Detected dm-crypt version %i.%i.%i, dm-ioctl version %u.%u.%u.",
|
||||
crypt_maj, crypt_min, crypt_patch, dm_maj, dm_min, dm_patch);
|
||||
|
||||
if (crypt_maj >= 1 && crypt_min >= 2)
|
||||
if (_dm_satisfies_version(1, 2, crypt_maj, crypt_min))
|
||||
_dm_crypt_flags |= DM_KEY_WIPE_SUPPORTED;
|
||||
else
|
||||
log_dbg("Suspend and resume disabled, no wipe key support.");
|
||||
|
||||
if (crypt_maj >= 1 && crypt_min >= 10)
|
||||
if (_dm_satisfies_version(1, 10, crypt_maj, crypt_min))
|
||||
_dm_crypt_flags |= DM_LMK_SUPPORTED;
|
||||
|
||||
if (dm_maj >= 4 && dm_min >= 20)
|
||||
if (_dm_satisfies_version(4, 20, dm_maj, dm_min))
|
||||
_dm_crypt_flags |= DM_SECURE_SUPPORTED;
|
||||
|
||||
/* not perfect, 2.6.33 supports with 1.7.0 */
|
||||
if (crypt_maj >= 1 && crypt_min >= 8)
|
||||
if (_dm_satisfies_version(1, 8, crypt_maj, crypt_min))
|
||||
_dm_crypt_flags |= DM_PLAIN64_SUPPORTED;
|
||||
|
||||
if (crypt_maj >= 1 && crypt_min >= 11)
|
||||
if (_dm_satisfies_version(1, 11, crypt_maj, crypt_min))
|
||||
_dm_crypt_flags |= DM_DISCARDS_SUPPORTED;
|
||||
|
||||
if (_dm_satisfies_version(1, 13, crypt_maj, crypt_min))
|
||||
_dm_crypt_flags |= DM_TCW_SUPPORTED;
|
||||
|
||||
if (_dm_satisfies_version(1, 14, crypt_maj, crypt_min)) {
|
||||
_dm_crypt_flags |= DM_SAME_CPU_CRYPT_SUPPORTED;
|
||||
_dm_crypt_flags |= DM_SUBMIT_FROM_CRYPT_CPUS_SUPPORTED;
|
||||
}
|
||||
|
||||
/* Repeat test if dm-crypt is not present */
|
||||
if (crypt_maj > 0)
|
||||
_dm_crypt_checked = 1;
|
||||
@@ -144,16 +164,6 @@ static void _dm_set_verity_compat(const char *dm_version, unsigned verity_maj,
|
||||
verity_maj, verity_min, verity_patch);
|
||||
}
|
||||
|
||||
static void _dm_kernel_info(void)
|
||||
{
|
||||
struct utsname uts;
|
||||
|
||||
if (!uname(&uts))
|
||||
log_dbg("Detected kernel %s %s %s.",
|
||||
uts.sysname, uts.release, uts.machine);
|
||||
|
||||
}
|
||||
|
||||
static int _dm_check_versions(void)
|
||||
{
|
||||
struct dm_task *dmt;
|
||||
@@ -164,8 +174,6 @@ static int _dm_check_versions(void)
|
||||
if (_dm_crypt_checked)
|
||||
return 1;
|
||||
|
||||
_dm_kernel_info();
|
||||
|
||||
/* Shut up DM while checking */
|
||||
_quiet_log = 1;
|
||||
|
||||
@@ -290,23 +298,30 @@ static void hex_key(char *hexkey, size_t key_size, const char *key)
|
||||
sprintf(&hexkey[i * 2], "%02x", (unsigned char)key[i]);
|
||||
}
|
||||
|
||||
/* http://code.google.com/p/cryptsetup/wiki/DMCrypt */
|
||||
static char *get_dm_crypt_params(struct crypt_dm_active_device *dmd)
|
||||
/* https://gitlab.com/cryptsetup/cryptsetup/wikis/DMCrypt */
|
||||
static char *get_dm_crypt_params(struct crypt_dm_active_device *dmd, uint32_t flags)
|
||||
{
|
||||
int r, max_size, null_cipher = 0;
|
||||
int r, max_size, null_cipher = 0, num_options = 0;
|
||||
char *params, *hexkey;
|
||||
const char *features = "";
|
||||
char features[256];
|
||||
|
||||
if (!dmd)
|
||||
return NULL;
|
||||
|
||||
if (dmd->flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) {
|
||||
if (dm_flags() & DM_DISCARDS_SUPPORTED) {
|
||||
features = " 1 allow_discards";
|
||||
log_dbg("Discard/TRIM is allowed.");
|
||||
} else
|
||||
log_dbg("Discard/TRIM is not supported by the kernel.");
|
||||
}
|
||||
if (flags & CRYPT_ACTIVATE_ALLOW_DISCARDS)
|
||||
num_options++;
|
||||
if (flags & CRYPT_ACTIVATE_SAME_CPU_CRYPT)
|
||||
num_options++;
|
||||
if (flags & CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS)
|
||||
num_options++;
|
||||
|
||||
if (num_options)
|
||||
snprintf(features, sizeof(features)-1, " %d%s%s%s", num_options,
|
||||
(flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) ? " allow_discards" : "",
|
||||
(flags & CRYPT_ACTIVATE_SAME_CPU_CRYPT) ? " same_cpu_crypt" : "",
|
||||
(flags & CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS) ? " submit_from_crypt_cpus" : "");
|
||||
else
|
||||
*features = '\0';
|
||||
|
||||
if (!strncmp(dmd->u.crypt.cipher, "cipher_null-", 12))
|
||||
null_cipher = 1;
|
||||
@@ -340,7 +355,7 @@ out:
|
||||
return params;
|
||||
}
|
||||
|
||||
/* http://code.google.com/p/cryptsetup/wiki/DMVerity */
|
||||
/* https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity */
|
||||
static char *get_dm_verity_params(struct crypt_params_verity *vp,
|
||||
struct crypt_dm_active_device *dmd)
|
||||
{
|
||||
@@ -516,7 +531,7 @@ static int dm_prepare_uuid(const char *name, const char *type, const char *uuid,
|
||||
if (uuid) {
|
||||
if (uuid_parse(uuid, uu) < 0) {
|
||||
log_dbg("Requested UUID %s has invalid format.", uuid);
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (ptr = uuid2, i = 0; i < UUID_LEN; i++)
|
||||
@@ -535,7 +550,7 @@ static int dm_prepare_uuid(const char *name, const char *type, const char *uuid,
|
||||
if (i >= buflen)
|
||||
log_err(NULL, _("DM-UUID for device %s was truncated.\n"), name);
|
||||
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _dm_create_device(const char *name, const char *type,
|
||||
@@ -551,6 +566,9 @@ static int _dm_create_device(const char *name, const char *type,
|
||||
uint32_t cookie = 0;
|
||||
uint16_t udev_flags = 0;
|
||||
|
||||
if (!params)
|
||||
return -EINVAL;
|
||||
|
||||
if (flags & CRYPT_ACTIVATE_PRIVATE)
|
||||
udev_flags = CRYPT_TEMP_UDEV_FLAGS;
|
||||
|
||||
@@ -562,9 +580,8 @@ static int _dm_create_device(const char *name, const char *type,
|
||||
if (!dm_task_set_name(dmt, name))
|
||||
goto out_no_removal;
|
||||
} else {
|
||||
r = dm_prepare_uuid(name, type, uuid, dev_uuid, sizeof(dev_uuid));
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (!dm_prepare_uuid(name, type, uuid, dev_uuid, sizeof(dev_uuid)))
|
||||
goto out_no_removal;
|
||||
|
||||
if (!(dmt = dm_task_create(DM_DEVICE_CREATE)))
|
||||
goto out_no_removal;
|
||||
@@ -628,12 +645,14 @@ out_no_removal:
|
||||
if (cookie && _dm_use_udev())
|
||||
(void)_dm_udev_wait(cookie);
|
||||
|
||||
if (params)
|
||||
crypt_safe_free(params);
|
||||
if (dmt)
|
||||
dm_task_destroy(dmt);
|
||||
|
||||
dm_task_update_nodes();
|
||||
|
||||
/* If code just loaded target module, update versions */
|
||||
_dm_check_versions();
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -643,7 +662,8 @@ int dm_create_device(struct crypt_device *cd, const char *name,
|
||||
int reload)
|
||||
{
|
||||
char *table_params = NULL;
|
||||
int r = -EINVAL;
|
||||
uint32_t dmd_flags;
|
||||
int r;
|
||||
|
||||
if (!type)
|
||||
return -EINVAL;
|
||||
@@ -651,15 +671,34 @@ int dm_create_device(struct crypt_device *cd, const char *name,
|
||||
if (dm_init_context(cd))
|
||||
return -ENOTSUP;
|
||||
|
||||
dmd_flags = dmd->flags;
|
||||
|
||||
if (dmd->target == DM_CRYPT)
|
||||
table_params = get_dm_crypt_params(dmd);
|
||||
table_params = get_dm_crypt_params(dmd, dmd_flags);
|
||||
else if (dmd->target == DM_VERITY)
|
||||
table_params = get_dm_verity_params(dmd->u.verity.vp, dmd);
|
||||
|
||||
if (table_params)
|
||||
r = _dm_create_device(name, type, dmd->data_device,
|
||||
dmd->flags, dmd->uuid, dmd->size,
|
||||
table_params, reload);
|
||||
r = _dm_create_device(name, type, dmd->data_device, dmd_flags,
|
||||
dmd->uuid, dmd->size, table_params, reload);
|
||||
|
||||
/* If discard not supported try to load without discard */
|
||||
if (!reload && r && dmd->target == DM_CRYPT &&
|
||||
(dmd->flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) &&
|
||||
!(dm_flags() & DM_DISCARDS_SUPPORTED)) {
|
||||
log_dbg("Discard/TRIM is not supported, retrying activation.");
|
||||
dmd_flags = dmd_flags & ~CRYPT_ACTIVATE_ALLOW_DISCARDS;
|
||||
crypt_safe_free(table_params);
|
||||
table_params = get_dm_crypt_params(dmd, dmd_flags);
|
||||
r = _dm_create_device(name, type, dmd->data_device, dmd_flags,
|
||||
dmd->uuid, dmd->size, table_params, reload);
|
||||
}
|
||||
|
||||
if (r == -EINVAL &&
|
||||
dmd_flags & (CRYPT_ACTIVATE_SAME_CPU_CRYPT|CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS) &&
|
||||
!(dm_flags() & (DM_SAME_CPU_CRYPT_SUPPORTED|DM_SUBMIT_FROM_CRYPT_CPUS_SUPPORTED)))
|
||||
log_err(cd, _("Requested dmcrypt performance options are not supported.\n"));
|
||||
|
||||
crypt_safe_free(table_params);
|
||||
dm_exit_context();
|
||||
return r;
|
||||
}
|
||||
@@ -846,6 +885,10 @@ static int _dm_query_crypt(uint32_t get_flags,
|
||||
arg = strsep(¶ms, " ");
|
||||
if (!strcasecmp(arg, "allow_discards"))
|
||||
dmd->flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS;
|
||||
else if (!strcasecmp(arg, "same_cpu_crypt"))
|
||||
dmd->flags |= CRYPT_ACTIVATE_SAME_CPU_CRYPT;
|
||||
else if (!strcasecmp(arg, "submit_from_crypt_cpus"))
|
||||
dmd->flags |= CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS;
|
||||
else /* unknown option */
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ int LOOPAES_parse_keyfile(struct crypt_device *cd,
|
||||
unsigned int key_lengths[LOOPAES_KEYS_MAX];
|
||||
unsigned int i, key_index, key_len, offset;
|
||||
|
||||
log_dbg("Parsing loop-AES keyfile of size %d.", buffer_len);
|
||||
log_dbg("Parsing loop-AES keyfile of size %zu.", buffer_len);
|
||||
|
||||
if (!buffer_len)
|
||||
return -EINVAL;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 2004-2006, Clemens Fruhwirth <clemens@endorphin.org>
|
||||
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2012-2014, Milan Broz
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -26,8 +27,13 @@
|
||||
#include "internal.h"
|
||||
|
||||
static void _error_hint(struct crypt_device *ctx, const char *device,
|
||||
const char *cipher_spec, const char *mode, size_t keyLength)
|
||||
const char *cipher, const char *mode, size_t keyLength)
|
||||
{
|
||||
char cipher_spec[MAX_CIPHER_LEN * 3];
|
||||
|
||||
if (snprintf(cipher_spec, sizeof(cipher_spec), "%s-%s", cipher, mode) < 0)
|
||||
return;
|
||||
|
||||
log_err(ctx, _("Failed to setup dm-crypt key mapping for device %s.\n"
|
||||
"Check that kernel supports %s cipher (check syslog for more info).\n"),
|
||||
device, cipher_spec);
|
||||
@@ -60,6 +66,8 @@ static int LUKS_endec_template(char *src, size_t srcLength,
|
||||
};
|
||||
int r, bsize, devfd = -1;
|
||||
|
||||
log_dbg("Using dmcrypt to access keyslot area.");
|
||||
|
||||
bsize = device_block_size(dmd.data_device);
|
||||
if (bsize <= 0)
|
||||
return -EINVAL;
|
||||
@@ -94,7 +102,7 @@ static int LUKS_endec_template(char *src, size_t srcLength,
|
||||
if (r < 0) {
|
||||
if (r != -EACCES && r != -ENOTSUP)
|
||||
_error_hint(ctx, device_path(dmd.data_device),
|
||||
cipher_spec, cipher_mode, vk->keylength * 8);
|
||||
cipher, cipher_mode, vk->keylength * 8);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@@ -125,8 +133,64 @@ int LUKS_encrypt_to_storage(char *src, size_t srcLength,
|
||||
unsigned int sector,
|
||||
struct crypt_device *ctx)
|
||||
{
|
||||
return LUKS_endec_template(src, srcLength, cipher, cipher_mode,
|
||||
vk, sector, write_blockwise, O_RDWR, ctx);
|
||||
|
||||
struct device *device = crypt_metadata_device(ctx);
|
||||
struct crypt_storage *s;
|
||||
int devfd = -1, bsize, r = 0;
|
||||
|
||||
/* Only whole sector writes supported */
|
||||
if (srcLength % SECTOR_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
/* Encrypt buffer */
|
||||
r = crypt_storage_init(&s, 0, cipher, cipher_mode, vk->key, vk->keylength);
|
||||
|
||||
if (r)
|
||||
log_dbg("Userspace crypto wrapper cannot use %s-%s (%d).",
|
||||
cipher, cipher_mode, r);
|
||||
|
||||
/* Fallback to old temporary dmcrypt device */
|
||||
if (r == -ENOTSUP || r == -ENOENT)
|
||||
return LUKS_endec_template(src, srcLength, cipher, cipher_mode,
|
||||
vk, sector, write_blockwise, O_RDWR, ctx);
|
||||
|
||||
if (r) {
|
||||
_error_hint(ctx, device_path(device), cipher, cipher_mode,
|
||||
vk->keylength * 8);
|
||||
return r;
|
||||
}
|
||||
|
||||
log_dbg("Using userspace crypto wrapper to access keyslot area.");
|
||||
|
||||
r = crypt_storage_encrypt(s, 0, srcLength / SECTOR_SIZE, src);
|
||||
crypt_storage_destroy(s);
|
||||
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = -EIO;
|
||||
|
||||
/* Write buffer to device */
|
||||
bsize = device_block_size(device);
|
||||
if (bsize <= 0)
|
||||
goto out;
|
||||
|
||||
devfd = device_open(device, O_RDWR);
|
||||
if (devfd == -1)
|
||||
goto out;
|
||||
|
||||
if (lseek(devfd, sector * SECTOR_SIZE, SEEK_SET) == -1 ||
|
||||
write_blockwise(devfd, bsize, src, srcLength) == -1)
|
||||
goto out;
|
||||
|
||||
r = 0;
|
||||
out:
|
||||
if(devfd != -1)
|
||||
close(devfd);
|
||||
if (r)
|
||||
log_err(ctx, _("IO error while encrypting keyslot.\n"));
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int LUKS_decrypt_from_storage(char *dst, size_t dstLength,
|
||||
@@ -136,6 +200,61 @@ int LUKS_decrypt_from_storage(char *dst, size_t dstLength,
|
||||
unsigned int sector,
|
||||
struct crypt_device *ctx)
|
||||
{
|
||||
return LUKS_endec_template(dst, dstLength, cipher, cipher_mode,
|
||||
vk, sector, read_blockwise, O_RDONLY, ctx);
|
||||
struct device *device = crypt_metadata_device(ctx);
|
||||
struct crypt_storage *s;
|
||||
int devfd = -1, bsize, r = 0;
|
||||
|
||||
/* Only whole sector reads supported */
|
||||
if (dstLength % SECTOR_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
r = crypt_storage_init(&s, 0, cipher, cipher_mode, vk->key, vk->keylength);
|
||||
|
||||
if (r)
|
||||
log_dbg("Userspace crypto wrapper cannot use %s-%s (%d).",
|
||||
cipher, cipher_mode, r);
|
||||
|
||||
/* Fallback to old temporary dmcrypt device */
|
||||
if (r == -ENOTSUP || r == -ENOENT)
|
||||
return LUKS_endec_template(dst, dstLength, cipher, cipher_mode,
|
||||
vk, sector, read_blockwise, O_RDONLY, ctx);
|
||||
|
||||
if (r) {
|
||||
_error_hint(ctx, device_path(device), cipher, cipher_mode,
|
||||
vk->keylength * 8);
|
||||
return r;
|
||||
}
|
||||
|
||||
log_dbg("Using userspace crypto wrapper to access keyslot area.");
|
||||
|
||||
r = -EIO;
|
||||
|
||||
/* Read buffer from device */
|
||||
bsize = device_block_size(device);
|
||||
if (bsize <= 0)
|
||||
goto bad;
|
||||
|
||||
devfd = device_open(device, O_RDONLY);
|
||||
if (devfd == -1)
|
||||
goto bad;
|
||||
|
||||
if (lseek(devfd, sector * SECTOR_SIZE, SEEK_SET) == -1 ||
|
||||
read_blockwise(devfd, bsize, dst, dstLength) == -1)
|
||||
goto bad;
|
||||
|
||||
close(devfd);
|
||||
|
||||
/* Decrypt buffer */
|
||||
r = crypt_storage_decrypt(s, 0, dstLength / SECTOR_SIZE, dst);
|
||||
crypt_storage_destroy(s);
|
||||
|
||||
return r;
|
||||
bad:
|
||||
if(devfd != -1)
|
||||
close(devfd);
|
||||
|
||||
log_err(ctx, _("IO error while decrypting keyslot.\n"));
|
||||
crypt_storage_destroy(s);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 2004-2006, Clemens Fruhwirth <clemens@endorphin.org>
|
||||
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2013-2014, Milan Broz
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -82,11 +83,12 @@ static int LUKS_check_device_size(struct crypt_device *ctx, size_t keyLength)
|
||||
|
||||
dev_sectors >>= SECTOR_SHIFT;
|
||||
hdr_sectors = LUKS_device_sectors(keyLength);
|
||||
log_dbg("Key length %u, device size %" PRIu64 " sectors, header size %"
|
||||
log_dbg("Key length %zu, device size %" PRIu64 " sectors, header size %"
|
||||
PRIu64 " sectors.",keyLength, dev_sectors, hdr_sectors);
|
||||
|
||||
if (hdr_sectors > dev_sectors) {
|
||||
log_err(ctx, _("Device %s is too small.\n"), device_path(device));
|
||||
log_err(ctx, _("Device %s is too small. (LUKS requires at least %" PRIu64 " bytes.)\n"),
|
||||
device_path(device), hdr_sectors * SECTOR_SIZE);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -146,29 +148,32 @@ static const char *dbg_slot_state(crypt_keyslot_info ki)
|
||||
}
|
||||
}
|
||||
|
||||
int LUKS_hdr_backup(
|
||||
const char *backup_file,
|
||||
struct luks_phdr *hdr,
|
||||
struct crypt_device *ctx)
|
||||
int LUKS_hdr_backup(const char *backup_file, struct crypt_device *ctx)
|
||||
{
|
||||
struct device *device = crypt_metadata_device(ctx);
|
||||
struct luks_phdr hdr;
|
||||
int r = 0, devfd = -1;
|
||||
ssize_t hdr_size;
|
||||
ssize_t buffer_size;
|
||||
char *buffer = NULL;
|
||||
|
||||
r = LUKS_read_phdr(hdr, 1, 0, ctx);
|
||||
r = LUKS_read_phdr(&hdr, 1, 0, ctx);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
buffer_size = LUKS_device_sectors(hdr->keyBytes) << SECTOR_SHIFT;
|
||||
hdr_size = LUKS_device_sectors(hdr.keyBytes) << SECTOR_SHIFT;
|
||||
buffer_size = size_round_up(hdr_size, crypt_getpagesize());
|
||||
|
||||
buffer = crypt_safe_alloc(buffer_size);
|
||||
if (!buffer || buffer_size < LUKS_ALIGN_KEYSLOTS) {
|
||||
if (!buffer || hdr_size < LUKS_ALIGN_KEYSLOTS || hdr_size > buffer_size) {
|
||||
r = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
log_dbg("Storing backup of header (%u bytes) and keyslot area (%u bytes).",
|
||||
sizeof(*hdr), buffer_size - LUKS_ALIGN_KEYSLOTS);
|
||||
log_dbg("Storing backup of header (%zu bytes) and keyslot area (%zu bytes).",
|
||||
sizeof(hdr), hdr_size - LUKS_ALIGN_KEYSLOTS);
|
||||
|
||||
log_dbg("Output backup file size: %zu bytes.", buffer_size);
|
||||
|
||||
devfd = device_open(device, O_RDONLY);
|
||||
if(devfd == -1) {
|
||||
@@ -177,15 +182,15 @@ int LUKS_hdr_backup(
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (read_blockwise(devfd, device_block_size(device), buffer, buffer_size) < buffer_size) {
|
||||
if (read_blockwise(devfd, device_block_size(device), buffer, hdr_size) < hdr_size) {
|
||||
r = -EIO;
|
||||
goto out;
|
||||
}
|
||||
close(devfd);
|
||||
|
||||
/* Wipe unused area, so backup cannot contain old signatures */
|
||||
if (hdr->keyblock[0].keyMaterialOffset * SECTOR_SIZE == LUKS_ALIGN_KEYSLOTS)
|
||||
memset(buffer + sizeof(*hdr), 0, LUKS_ALIGN_KEYSLOTS - sizeof(*hdr));
|
||||
if (hdr.keyblock[0].keyMaterialOffset * SECTOR_SIZE == LUKS_ALIGN_KEYSLOTS)
|
||||
memset(buffer + sizeof(hdr), 0, LUKS_ALIGN_KEYSLOTS - sizeof(hdr));
|
||||
|
||||
devfd = open(backup_file, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR);
|
||||
if (devfd == -1) {
|
||||
@@ -207,6 +212,7 @@ int LUKS_hdr_backup(
|
||||
out:
|
||||
if (devfd != -1)
|
||||
close(devfd);
|
||||
crypt_memzero(&hdr, sizeof(hdr));
|
||||
crypt_safe_free(buffer);
|
||||
return r;
|
||||
}
|
||||
@@ -281,7 +287,7 @@ int LUKS_hdr_restore(
|
||||
goto out;
|
||||
}
|
||||
|
||||
log_dbg("Storing backup of header (%u bytes) and keyslot area (%u bytes) to device %s.",
|
||||
log_dbg("Storing backup of header (%zu bytes) and keyslot area (%zu bytes) to device %s.",
|
||||
sizeof(*hdr), buffer_size - LUKS_ALIGN_KEYSLOTS, device_path(device));
|
||||
|
||||
devfd = device_open(device, O_RDWR);
|
||||
@@ -392,7 +398,7 @@ static int _keyslot_repair(struct luks_phdr *phdr, struct crypt_device *ctx)
|
||||
}
|
||||
out:
|
||||
crypt_free_volume_key(vk);
|
||||
memset(&temp_phdr, 0, sizeof(temp_phdr));
|
||||
crypt_memzero(&temp_phdr, sizeof(temp_phdr));
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -465,6 +471,13 @@ static void LUKS_fix_header_compatible(struct luks_phdr *header)
|
||||
/* Old cryptsetup expects "sha1", gcrypt allows case insensistive names,
|
||||
* so always convert hash to lower case in header */
|
||||
_to_lower(header->hashSpec, LUKS_HASHSPEC_L);
|
||||
|
||||
/* ECB mode does not use IV but dmcrypt silently allows it.
|
||||
* Drop any IV here if ECB is used (that is not secure anyway).*/
|
||||
if (!strncmp(header->cipherMode, "ecb-", 4)) {
|
||||
memset(header->cipherMode, 0, LUKS_CIPHERMODE_L);
|
||||
strcpy(header->cipherMode, "ecb");
|
||||
}
|
||||
}
|
||||
|
||||
int LUKS_read_phdr_backup(const char *backup_file,
|
||||
@@ -514,7 +527,7 @@ int LUKS_read_phdr(struct luks_phdr *hdr,
|
||||
if (repair && !require_luks_device)
|
||||
return -EINVAL;
|
||||
|
||||
log_dbg("Reading LUKS header of size %d from device %s",
|
||||
log_dbg("Reading LUKS header of size %zu from device %s",
|
||||
hdr_size, device_path(device));
|
||||
|
||||
devfd = device_open(device, O_RDONLY);
|
||||
@@ -546,7 +559,7 @@ int LUKS_write_phdr(struct luks_phdr *hdr,
|
||||
struct luks_phdr convHdr;
|
||||
int r;
|
||||
|
||||
log_dbg("Updating LUKS header of size %d on device %s",
|
||||
log_dbg("Updating LUKS header of size %zu on device %s",
|
||||
sizeof(struct luks_phdr), device_path(device));
|
||||
|
||||
r = LUKS_check_device_size(ctx, hdr->keyBytes);
|
||||
@@ -594,6 +607,28 @@ int LUKS_write_phdr(struct luks_phdr *hdr,
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Check that kernel supports requested cipher by decryption of one sector */
|
||||
static int LUKS_check_cipher(struct luks_phdr *hdr, struct crypt_device *ctx)
|
||||
{
|
||||
int r;
|
||||
struct volume_key *empty_key;
|
||||
char buf[SECTOR_SIZE];
|
||||
|
||||
log_dbg("Checking if cipher %s-%s is usable.", hdr->cipherName, hdr->cipherMode);
|
||||
|
||||
empty_key = crypt_alloc_volume_key(hdr->keyBytes, NULL);
|
||||
if (!empty_key)
|
||||
return -ENOMEM;
|
||||
|
||||
r = LUKS_decrypt_from_storage(buf, sizeof(buf),
|
||||
hdr->cipherName, hdr->cipherMode,
|
||||
empty_key, 0, ctx);
|
||||
|
||||
crypt_free_volume_key(empty_key);
|
||||
crypt_memzero(buf, sizeof(buf));
|
||||
return r;
|
||||
}
|
||||
|
||||
int LUKS_generate_phdr(struct luks_phdr *header,
|
||||
const struct volume_key *vk,
|
||||
const char *cipherName, const char *cipherMode, const char *hashSpec,
|
||||
@@ -647,6 +682,10 @@ int LUKS_generate_phdr(struct luks_phdr *header,
|
||||
|
||||
LUKS_fix_header_compatible(header);
|
||||
|
||||
r = LUKS_check_cipher(header, ctx);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
log_dbg("Generating LUKS header version %d using hash %s, %s, %s, MK %d bytes",
|
||||
header->version, header->hashSpec ,header->cipherName, header->cipherMode,
|
||||
header->keyBytes);
|
||||
@@ -765,14 +804,14 @@ int LUKS_set_key(unsigned int keyIndex,
|
||||
* Avoid floating point operation
|
||||
* Final iteration count is at least LUKS_SLOT_ITERATIONS_MIN
|
||||
*/
|
||||
PBKDF2_temp = (*PBKDF2_per_sec / 2) * (uint64_t)iteration_time_ms;
|
||||
PBKDF2_temp = *PBKDF2_per_sec * (uint64_t)iteration_time_ms;
|
||||
PBKDF2_temp /= 1024;
|
||||
if (PBKDF2_temp > UINT32_MAX)
|
||||
PBKDF2_temp = UINT32_MAX;
|
||||
hdr->keyblock[keyIndex].passwordIterations = at_least((uint32_t)PBKDF2_temp,
|
||||
LUKS_SLOT_ITERATIONS_MIN);
|
||||
|
||||
log_dbg("Key slot %d use %d password iterations.", keyIndex, hdr->keyblock[keyIndex].passwordIterations);
|
||||
log_dbg("Key slot %d use %" PRIu32 " password iterations.", keyIndex, hdr->keyblock[keyIndex].passwordIterations);
|
||||
|
||||
derived_key = crypt_alloc_volume_key(hdr->keyBytes, NULL);
|
||||
if (!derived_key)
|
||||
@@ -907,6 +946,11 @@ static int LUKS_open_key(unsigned int keyIndex,
|
||||
goto out;
|
||||
|
||||
r = LUKS_verify_volume_key(hdr, vk);
|
||||
|
||||
/* Allow only empty passphrase with null cipher */
|
||||
if (!r && !strcmp(hdr->cipherName, "cipher_null") && passwordLen)
|
||||
r = -EPERM;
|
||||
|
||||
if (!r)
|
||||
log_verbose(ctx, _("Key slot %d unlocked.\n"), keyIndex);
|
||||
out:
|
||||
|
||||
@@ -130,7 +130,6 @@ int LUKS_hdr_uuid_set(
|
||||
|
||||
int LUKS_hdr_backup(
|
||||
const char *backup_file,
|
||||
struct luks_phdr *hdr,
|
||||
struct crypt_device *ctx);
|
||||
|
||||
int LUKS_hdr_restore(
|
||||
|
||||
@@ -162,6 +162,9 @@ int crypt_random_init(struct crypt_device *ctx)
|
||||
if(random_fd == -1)
|
||||
goto fail;
|
||||
|
||||
if (crypt_fips_mode())
|
||||
log_verbose(ctx, _("Running in FIPS mode.\n"));
|
||||
|
||||
random_initialised = 1;
|
||||
return 0;
|
||||
fail:
|
||||
|
||||
295
lib/setup.c
295
lib/setup.c
@@ -1,10 +1,10 @@
|
||||
/*
|
||||
* libcryptsetup - cryptsetup library
|
||||
*
|
||||
* Copyright (C) 2004, Christophe Saout <christophe@saout.de>
|
||||
* Copyright (C) 2004, Jana Saout <jana@saout.de>
|
||||
* Copyright (C) 2004-2007, Clemens Fruhwirth <clemens@endorphin.org>
|
||||
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2009-2013, Milan Broz
|
||||
* Copyright (C) 2009-2014, Milan Broz
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
@@ -78,6 +79,13 @@ struct crypt_device {
|
||||
struct crypt_params_tcrypt params;
|
||||
struct tcrypt_phdr hdr;
|
||||
} tcrypt;
|
||||
struct { /* used if initialized without header by name */
|
||||
char *active_name;
|
||||
/* buffers, must refresh from kernel on every query */
|
||||
char cipher[MAX_CIPHER_LEN];
|
||||
char cipher_mode[MAX_CIPHER_LEN];
|
||||
unsigned int key_size;
|
||||
} none;
|
||||
} u;
|
||||
|
||||
/* callbacks definitions */
|
||||
@@ -92,6 +100,9 @@ struct crypt_device {
|
||||
char error[MAX_ERROR_LENGTH];
|
||||
};
|
||||
|
||||
/* Just to suppress redundant messages about crypto backend */
|
||||
static int _crypto_logged = 0;
|
||||
|
||||
/* Global error */
|
||||
/* FIXME: not thread safe, remove this later */
|
||||
static char global_error[MAX_ERROR_LENGTH] = {0};
|
||||
@@ -181,10 +192,9 @@ struct device *crypt_data_device(struct crypt_device *cd)
|
||||
|
||||
int init_crypto(struct crypt_device *ctx)
|
||||
{
|
||||
struct utsname uts;
|
||||
int r;
|
||||
|
||||
crypt_fips_libcryptsetup_check(ctx);
|
||||
|
||||
r = crypt_random_init(ctx);
|
||||
if (r < 0) {
|
||||
log_err(ctx, _("Cannot initialize crypto RNG backend.\n"));
|
||||
@@ -195,7 +205,15 @@ int init_crypto(struct crypt_device *ctx)
|
||||
if (r < 0)
|
||||
log_err(ctx, _("Cannot initialize crypto backend.\n"));
|
||||
|
||||
log_dbg("Crypto backend (%s) initialized.", crypt_backend_version());
|
||||
if (!r && !_crypto_logged) {
|
||||
log_dbg("Crypto backend (%s) initialized in cryptsetup library version %s.",
|
||||
crypt_backend_version(), PACKAGE_VERSION);
|
||||
if (!uname(&uts))
|
||||
log_dbg("Detected kernel %s %s %s.",
|
||||
uts.sysname, uts.release, uts.machine);
|
||||
_crypto_logged = 1;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -259,6 +277,41 @@ static int isTCRYPT(const char *type)
|
||||
return (type && !strcmp(CRYPT_TCRYPT, type));
|
||||
}
|
||||
|
||||
static int onlyLUKS(struct crypt_device *cd)
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
if (cd && !cd->type) {
|
||||
log_err(cd, _("Cannot determine device type. Incompatible activation of device?\n"));
|
||||
r = -EINVAL;
|
||||
}
|
||||
if (!cd || !isLUKS(cd->type)) {
|
||||
log_err(cd, _("This operation is supported only for LUKS device.\n"));
|
||||
r = -EINVAL;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void crypt_set_null_type(struct crypt_device *cd)
|
||||
{
|
||||
if (!cd->type)
|
||||
return;
|
||||
|
||||
free(cd->type);
|
||||
cd->type = NULL;
|
||||
cd->u.none.active_name = NULL;
|
||||
}
|
||||
|
||||
static void crypt_reset_null_type(struct crypt_device *cd)
|
||||
{
|
||||
if (cd->type)
|
||||
return;
|
||||
|
||||
free(cd->u.none.active_name);
|
||||
cd->u.none.active_name = NULL;
|
||||
}
|
||||
|
||||
/* keyslot helpers */
|
||||
static int keyslot_verify_or_find_empty(struct crypt_device *cd, int *keyslot)
|
||||
{
|
||||
@@ -316,6 +369,36 @@ static int crypt_uuid_cmp(const char *dm_uuid, const char *hdr_uuid)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* compares type of active device to provided string (only if there is no explicit type)
|
||||
*/
|
||||
static int crypt_uuid_type_cmp(struct crypt_device *cd, const char *type)
|
||||
{
|
||||
struct crypt_dm_active_device dmd = {};
|
||||
size_t len;
|
||||
int r;
|
||||
|
||||
/* Must user header-on-disk if we know type here */
|
||||
if (cd->type || !cd->u.none.active_name)
|
||||
return -EINVAL;
|
||||
|
||||
log_dbg("Checking if active device %s without header has UUID type %s.",
|
||||
cd->u.none.active_name, type);
|
||||
|
||||
r = dm_query_device(cd, cd->u.none.active_name, DM_ACTIVE_UUID, &dmd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = -ENODEV;
|
||||
len = strlen(type);
|
||||
if (dmd.uuid && strlen(dmd.uuid) > len &&
|
||||
!strncmp(dmd.uuid, type, len) && dmd.uuid[len] == '-')
|
||||
r = 0;
|
||||
|
||||
free(CONST_CAST(void*)dmd.uuid);
|
||||
return r;
|
||||
}
|
||||
|
||||
int PLAIN_activate(struct crypt_device *cd,
|
||||
const char *name,
|
||||
struct volume_key *vk,
|
||||
@@ -706,6 +789,8 @@ static int _init_by_name_crypt(struct crypt_device *cd, const char *name)
|
||||
DM_ACTIVE_CRYPT_KEYSIZE, &dmd);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
if (r > 0)
|
||||
r = 0;
|
||||
|
||||
if (isPLAIN(cd->type)) {
|
||||
cd->u.plain.hdr.hash = NULL; /* no way to get this */
|
||||
@@ -736,8 +821,7 @@ static int _init_by_name_crypt(struct crypt_device *cd, const char *name)
|
||||
r = _crypt_load_luks1(cd, 0, 0);
|
||||
if (r < 0) {
|
||||
log_dbg("LUKS device header does not match active device.");
|
||||
free(cd->type);
|
||||
cd->type = NULL;
|
||||
crypt_set_null_type(cd);
|
||||
r = 0;
|
||||
goto out;
|
||||
}
|
||||
@@ -746,14 +830,12 @@ static int _init_by_name_crypt(struct crypt_device *cd, const char *name)
|
||||
if (r < 0) {
|
||||
log_dbg("LUKS device header uuid: %s mismatches DM returned uuid %s",
|
||||
cd->u.luks1.hdr.uuid, dmd.uuid);
|
||||
free(cd->type);
|
||||
cd->type = NULL;
|
||||
crypt_set_null_type(cd);
|
||||
r = 0;
|
||||
}
|
||||
} else {
|
||||
log_dbg("LUKS device header not available.");
|
||||
free(cd->type);
|
||||
cd->type = NULL;
|
||||
crypt_set_null_type(cd);
|
||||
r = 0;
|
||||
}
|
||||
} else if (isTCRYPT(cd->type)) {
|
||||
@@ -783,6 +865,8 @@ static int _init_by_name_verity(struct crypt_device *cd, const char *name)
|
||||
DM_ACTIVE_VERITY_PARAMS, &dmd);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
if (r > 0)
|
||||
r = 0;
|
||||
|
||||
if (isVERITY(cd->type)) {
|
||||
cd->u.verity.uuid = NULL; // FIXME
|
||||
@@ -885,7 +969,11 @@ out:
|
||||
if (r < 0) {
|
||||
crypt_free(*cd);
|
||||
*cd = NULL;
|
||||
} else if (!(*cd)->type && name) {
|
||||
/* For anonymous device (no header found) remember initialized name */
|
||||
(*cd)->u.none.active_name = strdup(name);
|
||||
}
|
||||
|
||||
device_free(dmd.data_device);
|
||||
free(CONST_CAST(void*)dmd.uuid);
|
||||
return r;
|
||||
@@ -985,13 +1073,8 @@ static int _crypt_format_luks1(struct crypt_device *cd,
|
||||
&required_alignment,
|
||||
&alignment_offset, DEFAULT_DISK_ALIGNMENT);
|
||||
|
||||
/* Check early if we cannot allocate block device for key slot access */
|
||||
r = device_block_adjust(cd, cd->device, DEV_OK, 0, NULL, NULL);
|
||||
if(r < 0)
|
||||
return r;
|
||||
|
||||
r = LUKS_generate_phdr(&cd->u.luks1.hdr, cd->volume_key, cipher, cipher_mode,
|
||||
(params && params->hash) ? params->hash : "sha1",
|
||||
(params && params->hash) ? params->hash : DEFAULT_LUKS1_HASH,
|
||||
uuid, LUKS_STRIPES,
|
||||
required_alignment / SECTOR_SIZE,
|
||||
alignment_offset / SECTOR_SIZE,
|
||||
@@ -1183,6 +1266,8 @@ int crypt_format(struct crypt_device *cd,
|
||||
|
||||
log_dbg("Formatting device %s as type %s.", mdata_device_path(cd) ?: "(none)", type);
|
||||
|
||||
crypt_reset_null_type(cd);
|
||||
|
||||
r = init_crypto(cd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -1203,8 +1288,7 @@ int crypt_format(struct crypt_device *cd,
|
||||
}
|
||||
|
||||
if (r < 0) {
|
||||
free(cd->type);
|
||||
cd->type = NULL;
|
||||
crypt_set_null_type(cd);
|
||||
crypt_free_volume_key(cd->volume_key);
|
||||
cd->volume_key = NULL;
|
||||
}
|
||||
@@ -1224,6 +1308,8 @@ int crypt_load(struct crypt_device *cd,
|
||||
if (!crypt_metadata_device(cd))
|
||||
return -EINVAL;
|
||||
|
||||
crypt_reset_null_type(cd);
|
||||
|
||||
if (!requested_type || isLUKS(requested_type)) {
|
||||
if (cd->type && !isLUKS(cd->type)) {
|
||||
log_dbg("Context is already initialised to type %s", cd->type);
|
||||
@@ -1272,10 +1358,8 @@ int crypt_repair(struct crypt_device *cd,
|
||||
|
||||
/* cd->type and header must be set in context */
|
||||
r = crypt_check_data_device_size(cd);
|
||||
if (r < 0) {
|
||||
free(cd->type);
|
||||
cd->type = NULL;
|
||||
}
|
||||
if (r < 0)
|
||||
crypt_set_null_type(cd);
|
||||
|
||||
return r;
|
||||
}
|
||||
@@ -1304,6 +1388,14 @@ int crypt_resize(struct crypt_device *cd, const char *name, uint64_t new_size)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (crypt_loop_device(crypt_get_device_name(cd))) {
|
||||
log_dbg("Trying to resize underlying loop device %s.",
|
||||
crypt_get_device_name(cd));
|
||||
/* Here we always use default size not new_size */
|
||||
if (crypt_loop_resize(crypt_get_device_name(cd)))
|
||||
log_err(NULL, _("Cannot resize loop device.\n"));
|
||||
}
|
||||
|
||||
r = device_block_adjust(cd, dmd.data_device, DEV_OK,
|
||||
dmd.u.crypt.offset, &new_size, &dmd.flags);
|
||||
if (r)
|
||||
@@ -1364,6 +1456,9 @@ int crypt_header_backup(struct crypt_device *cd,
|
||||
if ((requested_type && !isLUKS(requested_type)) || !backup_file)
|
||||
return -EINVAL;
|
||||
|
||||
if (cd->type && !isLUKS(cd->type))
|
||||
return -EINVAL;
|
||||
|
||||
r = init_crypto(cd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -1371,13 +1466,15 @@ int crypt_header_backup(struct crypt_device *cd,
|
||||
log_dbg("Requested header backup of device %s (%s) to "
|
||||
"file %s.", mdata_device_path(cd), requested_type, backup_file);
|
||||
|
||||
return LUKS_hdr_backup(backup_file, &cd->u.luks1.hdr, cd);
|
||||
r = LUKS_hdr_backup(backup_file, cd);
|
||||
return r;
|
||||
}
|
||||
|
||||
int crypt_header_restore(struct crypt_device *cd,
|
||||
const char *requested_type,
|
||||
const char *backup_file)
|
||||
{
|
||||
struct luks_phdr hdr;
|
||||
int r;
|
||||
|
||||
if (requested_type && !isLUKS(requested_type))
|
||||
@@ -1393,7 +1490,10 @@ int crypt_header_restore(struct crypt_device *cd,
|
||||
log_dbg("Requested header restore to device %s (%s) from "
|
||||
"file %s.", mdata_device_path(cd), requested_type, backup_file);
|
||||
|
||||
return LUKS_hdr_restore(backup_file, &cd->u.luks1.hdr, cd);
|
||||
r = LUKS_hdr_restore(backup_file, isLUKS(cd->type) ? &cd->u.luks1.hdr : &hdr, cd);
|
||||
|
||||
crypt_memzero(&hdr, sizeof(hdr));
|
||||
return r;
|
||||
}
|
||||
|
||||
void crypt_free(struct crypt_device *cd)
|
||||
@@ -1419,11 +1519,13 @@ void crypt_free(struct crypt_device *cd)
|
||||
free(CONST_CAST(void*)cd->u.verity.hdr.salt);
|
||||
free(cd->u.verity.root_hash);
|
||||
free(cd->u.verity.uuid);
|
||||
} else if (!cd->type) {
|
||||
free(cd->u.none.active_name);
|
||||
}
|
||||
|
||||
free(cd->type);
|
||||
/* Some structures can contain keys (TCRYPT), wipe it */
|
||||
memset(cd, 0, sizeof(*cd));
|
||||
crypt_memzero(cd, sizeof(*cd));
|
||||
free(cd);
|
||||
}
|
||||
}
|
||||
@@ -1436,12 +1538,17 @@ int crypt_suspend(struct crypt_device *cd,
|
||||
|
||||
log_dbg("Suspending volume %s.", name);
|
||||
|
||||
if (!cd || !isLUKS(cd->type)) {
|
||||
log_err(cd, _("This operation is supported only for LUKS device.\n"));
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
if (cd->type) {
|
||||
r = onlyLUKS(cd);
|
||||
} else {
|
||||
r = crypt_uuid_type_cmp(cd, CRYPT_LUKS1);
|
||||
if (r < 0)
|
||||
log_err(cd, _("This operation is supported only for LUKS device.\n"));
|
||||
}
|
||||
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
ci = crypt_status(NULL, name);
|
||||
if (ci < CRYPT_ACTIVE) {
|
||||
log_err(cd, _("Volume %s is not active.\n"), name);
|
||||
@@ -1481,11 +1588,9 @@ int crypt_resume_by_passphrase(struct crypt_device *cd,
|
||||
|
||||
log_dbg("Resuming volume %s.", name);
|
||||
|
||||
if (!isLUKS(cd->type)) {
|
||||
log_err(cd, _("This operation is supported only for LUKS device.\n"));
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
r = onlyLUKS(cd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = dm_status_suspended(cd, name);
|
||||
if (r < 0)
|
||||
@@ -1511,7 +1616,7 @@ int crypt_resume_by_passphrase(struct crypt_device *cd,
|
||||
log_err(cd, _("Error during resuming device %s.\n"), name);
|
||||
} else
|
||||
r = keyslot;
|
||||
out:
|
||||
|
||||
crypt_free_volume_key(vk);
|
||||
return r < 0 ? r : keyslot;
|
||||
}
|
||||
@@ -1530,11 +1635,9 @@ int crypt_resume_by_keyfile_offset(struct crypt_device *cd,
|
||||
|
||||
log_dbg("Resuming volume %s.", name);
|
||||
|
||||
if (!isLUKS(cd->type)) {
|
||||
log_err(cd, _("This operation is supported only for LUKS device.\n"));
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
r = onlyLUKS(cd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = dm_status_suspended(cd, name);
|
||||
if (r < 0)
|
||||
@@ -1596,10 +1699,9 @@ int crypt_keyslot_add_by_passphrase(struct crypt_device *cd,
|
||||
"new passphrase %sprovided.",
|
||||
passphrase ? "" : "not ", new_passphrase ? "" : "not ");
|
||||
|
||||
if (!isLUKS(cd->type)) {
|
||||
log_err(cd, _("This operation is supported only for LUKS device.\n"));
|
||||
return -EINVAL;
|
||||
}
|
||||
r = onlyLUKS(cd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = keyslot_verify_or_find_empty(cd, &keyslot);
|
||||
if (r)
|
||||
@@ -1645,14 +1747,15 @@ int crypt_keyslot_add_by_passphrase(struct crypt_device *cd,
|
||||
|
||||
r = LUKS_set_key(keyslot, new_password, new_passwordLen,
|
||||
&cd->u.luks1.hdr, vk, cd->iteration_time, &cd->u.luks1.PBKDF2_per_sec, cd);
|
||||
if(r < 0) goto out;
|
||||
if(r < 0)
|
||||
goto out;
|
||||
|
||||
r = 0;
|
||||
out:
|
||||
if (!new_passphrase)
|
||||
crypt_safe_free(new_password);
|
||||
crypt_free_volume_key(vk);
|
||||
return r ?: keyslot;
|
||||
return r < 0 ? r : keyslot;
|
||||
}
|
||||
|
||||
int crypt_keyslot_change_by_passphrase(struct crypt_device *cd,
|
||||
@@ -1664,15 +1767,14 @@ int crypt_keyslot_change_by_passphrase(struct crypt_device *cd,
|
||||
size_t new_passphrase_size)
|
||||
{
|
||||
struct volume_key *vk = NULL;
|
||||
int r = -EINVAL;
|
||||
int r;
|
||||
|
||||
log_dbg("Changing passphrase from old keyslot %d to new %d.",
|
||||
keyslot_old, keyslot_new);
|
||||
|
||||
if (!isLUKS(cd->type)) {
|
||||
log_err(cd, _("This operation is supported only for LUKS device.\n"));
|
||||
return -EINVAL;
|
||||
}
|
||||
r = onlyLUKS(cd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = LUKS_open_key_with_hdr(keyslot_old, passphrase, passphrase_size,
|
||||
&cd->u.luks1.hdr, &vk, cd);
|
||||
@@ -1702,10 +1804,10 @@ int crypt_keyslot_change_by_passphrase(struct crypt_device *cd,
|
||||
|
||||
if (keyslot_old == keyslot_new) {
|
||||
if (r >= 0)
|
||||
log_verbose(cd, _("Key slot %d changed.\n"), r);
|
||||
log_verbose(cd, _("Key slot %d changed.\n"), keyslot_new);
|
||||
} else {
|
||||
if (r >= 0) {
|
||||
log_verbose(cd, _("Replaced with key slot %d.\n"), r);
|
||||
log_verbose(cd, _("Replaced with key slot %d.\n"), keyslot_new);
|
||||
r = crypt_keyslot_destroy(cd, keyslot_old);
|
||||
}
|
||||
}
|
||||
@@ -1713,7 +1815,7 @@ int crypt_keyslot_change_by_passphrase(struct crypt_device *cd,
|
||||
log_err(cd, _("Failed to swap new key slot.\n"));
|
||||
out:
|
||||
crypt_free_volume_key(vk);
|
||||
return r ?: keyslot_new;
|
||||
return r < 0 ? r : keyslot_new;
|
||||
}
|
||||
|
||||
int crypt_keyslot_add_by_keyfile_offset(struct crypt_device *cd,
|
||||
@@ -1733,10 +1835,9 @@ int crypt_keyslot_add_by_keyfile_offset(struct crypt_device *cd,
|
||||
log_dbg("Adding new keyslot, existing keyfile %s, new keyfile %s.",
|
||||
keyfile ?: "[none]", new_keyfile ?: "[none]");
|
||||
|
||||
if (!isLUKS(cd->type)) {
|
||||
log_err(cd, _("This operation is supported only for LUKS device.\n"));
|
||||
return -EINVAL;
|
||||
}
|
||||
r = onlyLUKS(cd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = keyslot_verify_or_find_empty(cd, &keyslot);
|
||||
if (r)
|
||||
@@ -1809,15 +1910,14 @@ int crypt_keyslot_add_by_volume_key(struct crypt_device *cd,
|
||||
size_t passphrase_size)
|
||||
{
|
||||
struct volume_key *vk = NULL;
|
||||
int r = -EINVAL;
|
||||
int r;
|
||||
char *new_password = NULL; size_t new_passwordLen;
|
||||
|
||||
log_dbg("Adding new keyslot %d using volume key.", keyslot);
|
||||
|
||||
if (!isLUKS(cd->type)) {
|
||||
log_err(cd, _("This operation is supported only for LUKS device.\n"));
|
||||
return -EINVAL;
|
||||
}
|
||||
r = onlyLUKS(cd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (volume_key)
|
||||
vk = crypt_alloc_volume_key(volume_key_size, volume_key);
|
||||
@@ -1857,13 +1957,13 @@ out:
|
||||
int crypt_keyslot_destroy(struct crypt_device *cd, int keyslot)
|
||||
{
|
||||
crypt_keyslot_info ki;
|
||||
int r;
|
||||
|
||||
log_dbg("Destroying keyslot %d.", keyslot);
|
||||
|
||||
if (!isLUKS(cd->type)) {
|
||||
log_err(cd, _("This operation is supported only for LUKS device.\n"));
|
||||
return -EINVAL;
|
||||
}
|
||||
r = onlyLUKS(cd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
ki = crypt_keyslot_status(cd, keyslot);
|
||||
if (ki == CRYPT_SLOT_INVALID) {
|
||||
@@ -2234,10 +2334,9 @@ int crypt_volume_key_verify(struct crypt_device *cd,
|
||||
struct volume_key *vk;
|
||||
int r;
|
||||
|
||||
if (!isLUKS(cd->type)) {
|
||||
log_err(cd, _("This operation is supported only for LUKS device.\n"));
|
||||
return -EINVAL;
|
||||
}
|
||||
r = onlyLUKS(cd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
vk = crypt_alloc_volume_key(volume_key_size, volume_key);
|
||||
if (!vk)
|
||||
@@ -2341,12 +2440,12 @@ static int _luks_dump(struct crypt_device *cd)
|
||||
int i;
|
||||
|
||||
log_std(cd, "LUKS header information for %s\n\n", mdata_device_path(cd));
|
||||
log_std(cd, "Version: \t%d\n", cd->u.luks1.hdr.version);
|
||||
log_std(cd, "Version: \t%" PRIu16 "\n", cd->u.luks1.hdr.version);
|
||||
log_std(cd, "Cipher name: \t%s\n", cd->u.luks1.hdr.cipherName);
|
||||
log_std(cd, "Cipher mode: \t%s\n", cd->u.luks1.hdr.cipherMode);
|
||||
log_std(cd, "Hash spec: \t%s\n", cd->u.luks1.hdr.hashSpec);
|
||||
log_std(cd, "Payload offset:\t%d\n", cd->u.luks1.hdr.payloadOffset);
|
||||
log_std(cd, "MK bits: \t%d\n", cd->u.luks1.hdr.keyBytes * 8);
|
||||
log_std(cd, "Payload offset:\t%" PRIu32 "\n", cd->u.luks1.hdr.payloadOffset);
|
||||
log_std(cd, "MK bits: \t%" PRIu32 "\n", cd->u.luks1.hdr.keyBytes * 8);
|
||||
log_std(cd, "MK digest: \t");
|
||||
hexprint(cd, cd->u.luks1.hdr.mkDigest, LUKS_DIGESTSIZE, " ");
|
||||
log_std(cd, "\n");
|
||||
@@ -2355,12 +2454,12 @@ static int _luks_dump(struct crypt_device *cd)
|
||||
log_std(cd, "\n \t");
|
||||
hexprint(cd, cd->u.luks1.hdr.mkDigestSalt+LUKS_SALTSIZE/2, LUKS_SALTSIZE/2, " ");
|
||||
log_std(cd, "\n");
|
||||
log_std(cd, "MK iterations: \t%d\n", cd->u.luks1.hdr.mkDigestIterations);
|
||||
log_std(cd, "MK iterations: \t%" PRIu32 "\n", cd->u.luks1.hdr.mkDigestIterations);
|
||||
log_std(cd, "UUID: \t%s\n\n", cd->u.luks1.hdr.uuid);
|
||||
for(i = 0; i < LUKS_NUMKEYS; i++) {
|
||||
if(cd->u.luks1.hdr.keyblock[i].active == LUKS_KEY_ENABLED) {
|
||||
log_std(cd, "Key Slot %d: ENABLED\n",i);
|
||||
log_std(cd, "\tIterations: \t%d\n",
|
||||
log_std(cd, "\tIterations: \t%" PRIu32 "\n",
|
||||
cd->u.luks1.hdr.keyblock[i].passwordIterations);
|
||||
log_std(cd, "\tSalt: \t");
|
||||
hexprint(cd, cd->u.luks1.hdr.keyblock[i].passwordSalt,
|
||||
@@ -2370,9 +2469,9 @@ static int _luks_dump(struct crypt_device *cd)
|
||||
LUKS_SALTSIZE/2, LUKS_SALTSIZE/2, " ");
|
||||
log_std(cd, "\n");
|
||||
|
||||
log_std(cd, "\tKey material offset:\t%d\n",
|
||||
log_std(cd, "\tKey material offset:\t%" PRIu32 "\n",
|
||||
cd->u.luks1.hdr.keyblock[i].keyMaterialOffset);
|
||||
log_std(cd, "\tAF stripes: \t%d\n",
|
||||
log_std(cd, "\tAF stripes: \t%" PRIu32 "\n",
|
||||
cd->u.luks1.hdr.keyblock[i].stripes);
|
||||
}
|
||||
else
|
||||
@@ -2417,6 +2516,31 @@ int crypt_dump(struct crypt_device *cd)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
||||
static int _init_by_name_crypt_none(struct crypt_device *cd)
|
||||
{
|
||||
struct crypt_dm_active_device dmd = {};
|
||||
int r;
|
||||
|
||||
if (cd->type || !cd->u.none.active_name)
|
||||
return -EINVAL;
|
||||
|
||||
r = dm_query_device(cd, cd->u.none.active_name,
|
||||
DM_ACTIVE_CRYPT_CIPHER |
|
||||
DM_ACTIVE_CRYPT_KEYSIZE, &dmd);
|
||||
if (r >= 0)
|
||||
r = crypt_parse_name_and_mode(dmd.u.crypt.cipher,
|
||||
cd->u.none.cipher, NULL,
|
||||
cd->u.none.cipher_mode);
|
||||
|
||||
if (!r)
|
||||
cd->u.none.key_size = dmd.u.crypt.vk->keylength;
|
||||
|
||||
crypt_free_volume_key(dmd.u.crypt.vk);
|
||||
free(CONST_CAST(void*)dmd.u.crypt.cipher);
|
||||
return r;
|
||||
}
|
||||
|
||||
const char *crypt_get_cipher(struct crypt_device *cd)
|
||||
{
|
||||
if (isPLAIN(cd->type))
|
||||
@@ -2431,6 +2555,9 @@ const char *crypt_get_cipher(struct crypt_device *cd)
|
||||
if (isTCRYPT(cd->type))
|
||||
return cd->u.tcrypt.params.cipher;
|
||||
|
||||
if (!cd->type && !_init_by_name_crypt_none(cd))
|
||||
return cd->u.none.cipher;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -2448,6 +2575,9 @@ const char *crypt_get_cipher_mode(struct crypt_device *cd)
|
||||
if (isTCRYPT(cd->type))
|
||||
return cd->u.tcrypt.params.mode;
|
||||
|
||||
if (!cd->type && !_init_by_name_crypt_none(cd))
|
||||
return cd->u.none.cipher_mode;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -2489,6 +2619,9 @@ int crypt_get_volume_key_size(struct crypt_device *cd)
|
||||
if (isTCRYPT(cd->type))
|
||||
return cd->u.tcrypt.params.key_size;
|
||||
|
||||
if (!cd->type && !_init_by_name_crypt_none(cd))
|
||||
return cd->u.none.key_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2528,10 +2661,8 @@ uint64_t crypt_get_iv_offset(struct crypt_device *cd)
|
||||
|
||||
crypt_keyslot_info crypt_keyslot_status(struct crypt_device *cd, int keyslot)
|
||||
{
|
||||
if (!isLUKS(cd->type)) {
|
||||
log_err(cd, _("This operation is supported only for LUKS device.\n"));
|
||||
if (onlyLUKS(cd) < 0)
|
||||
return CRYPT_SLOT_INVALID;
|
||||
}
|
||||
|
||||
return LUKS_keyslot_info(&cd->u.luks1.hdr, keyslot);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* TCRYPT (TrueCrypt-compatible) volume handling
|
||||
* TCRYPT (TrueCrypt-compatible) and VeraCrypt volume handling
|
||||
*
|
||||
* Copyright (C) 2012, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2012-2013, Milan Broz
|
||||
* Copyright (C) 2012-2015, Milan Broz
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -33,16 +33,23 @@
|
||||
/* TCRYPT PBKDF variants */
|
||||
static struct {
|
||||
unsigned int legacy:1;
|
||||
unsigned int veracrypt:1;
|
||||
const char *name;
|
||||
const char *hash;
|
||||
unsigned int iterations;
|
||||
} tcrypt_kdf[] = {
|
||||
{ 0, "pbkdf2", "ripemd160", 2000 },
|
||||
{ 0, "pbkdf2", "ripemd160", 1000 },
|
||||
{ 0, "pbkdf2", "sha512", 1000 },
|
||||
{ 0, "pbkdf2", "whirlpool", 1000 },
|
||||
{ 1, "pbkdf2", "sha1", 2000 },
|
||||
{ 0, NULL, NULL, 0 }
|
||||
{ 0, 0, "pbkdf2", "ripemd160", 2000 },
|
||||
{ 0, 0, "pbkdf2", "ripemd160", 1000 },
|
||||
{ 0, 0, "pbkdf2", "sha512", 1000 },
|
||||
{ 0, 0, "pbkdf2", "whirlpool", 1000 },
|
||||
{ 1, 0, "pbkdf2", "sha1", 2000 },
|
||||
{ 0, 1, "pbkdf2", "sha512", 500000 },
|
||||
{ 0, 1, "pbkdf2", "ripemd160", 655331 },
|
||||
{ 0, 1, "pbkdf2", "ripemd160", 327661 }, // boot only
|
||||
{ 0, 1, "pbkdf2", "whirlpool", 500000 },
|
||||
{ 0, 1, "pbkdf2", "sha256", 500000 }, // VeraCrypt 1.0f
|
||||
{ 0, 1, "pbkdf2", "sha256", 200000 }, // boot only
|
||||
{ 0, 0, NULL, NULL, 0 }
|
||||
};
|
||||
|
||||
struct tcrypt_alg {
|
||||
@@ -51,6 +58,7 @@ struct tcrypt_alg {
|
||||
unsigned int iv_size;
|
||||
unsigned int key_offset;
|
||||
unsigned int iv_offset; /* or tweak key offset */
|
||||
unsigned int key_extra_size;
|
||||
};
|
||||
|
||||
struct tcrypt_algs {
|
||||
@@ -66,101 +74,107 @@ struct tcrypt_algs {
|
||||
static struct tcrypt_algs tcrypt_cipher[] = {
|
||||
/* XTS mode */
|
||||
{0,1,64,"aes","xts-plain64",
|
||||
{{"aes", 64,16,0,32}}},
|
||||
{{"aes", 64,16,0,32,0}}},
|
||||
{0,1,64,"serpent","xts-plain64",
|
||||
{{"serpent",64,16,0,32}}},
|
||||
{{"serpent",64,16,0,32,0}}},
|
||||
{0,1,64,"twofish","xts-plain64",
|
||||
{{"twofish",64,16,0,32}}},
|
||||
{{"twofish",64,16,0,32,0}}},
|
||||
{0,2,128,"twofish-aes","xts-plain64",
|
||||
{{"twofish",64,16, 0,64},
|
||||
{"aes", 64,16,32,96}}},
|
||||
{{"twofish",64,16, 0,64,0},
|
||||
{"aes", 64,16,32,96,0}}},
|
||||
{0,3,192,"serpent-twofish-aes","xts-plain64",
|
||||
{{"serpent",64,16, 0, 96},
|
||||
{"twofish",64,16,32,128},
|
||||
{"aes", 64,16,64,160}}},
|
||||
{{"serpent",64,16, 0, 96,0},
|
||||
{"twofish",64,16,32,128,0},
|
||||
{"aes", 64,16,64,160,0}}},
|
||||
{0,2,128,"aes-serpent","xts-plain64",
|
||||
{{"aes", 64,16, 0,64},
|
||||
{"serpent",64,16,32,96}}},
|
||||
{{"aes", 64,16, 0,64,0},
|
||||
{"serpent",64,16,32,96,0}}},
|
||||
{0,3,192,"aes-twofish-serpent","xts-plain64",
|
||||
{{"aes", 64,16, 0, 96},
|
||||
{"twofish",64,16,32,128},
|
||||
{"serpent",64,16,64,160}}},
|
||||
{{"aes", 64,16, 0, 96,0},
|
||||
{"twofish",64,16,32,128,0},
|
||||
{"serpent",64,16,64,160,0}}},
|
||||
{0,2,128,"serpent-twofish","xts-plain64",
|
||||
{{"serpent",64,16, 0,64},
|
||||
{"twofish",64,16,32,96}}},
|
||||
{{"serpent",64,16, 0,64,0},
|
||||
{"twofish",64,16,32,96,0}}},
|
||||
|
||||
/* LRW mode */
|
||||
{0,1,48,"aes","lrw-benbi",
|
||||
{{"aes", 48,16,32,0}}},
|
||||
{{"aes", 48,16,32,0,0}}},
|
||||
{0,1,48,"serpent","lrw-benbi",
|
||||
{{"serpent",48,16,32,0}}},
|
||||
{{"serpent",48,16,32,0,0}}},
|
||||
{0,1,48,"twofish","lrw-benbi",
|
||||
{{"twofish",48,16,32,0}}},
|
||||
{{"twofish",48,16,32,0,0}}},
|
||||
{0,2,96,"twofish-aes","lrw-benbi",
|
||||
{{"twofish",48,16,32,0},
|
||||
{"aes", 48,16,64,0}}},
|
||||
{{"twofish",48,16,32,0,0},
|
||||
{"aes", 48,16,64,0,0}}},
|
||||
{0,3,144,"serpent-twofish-aes","lrw-benbi",
|
||||
{{"serpent",48,16,32,0},
|
||||
{"twofish",48,16,64,0},
|
||||
{"aes", 48,16,96,0}}},
|
||||
{{"serpent",48,16,32,0,0},
|
||||
{"twofish",48,16,64,0,0},
|
||||
{"aes", 48,16,96,0,0}}},
|
||||
{0,2,96,"aes-serpent","lrw-benbi",
|
||||
{{"aes", 48,16,32,0},
|
||||
{"serpent",48,16,64,0}}},
|
||||
{{"aes", 48,16,32,0,0},
|
||||
{"serpent",48,16,64,0,0}}},
|
||||
{0,3,144,"aes-twofish-serpent","lrw-benbi",
|
||||
{{"aes", 48,16,32,0},
|
||||
{"twofish",48,16,64,0},
|
||||
{"serpent",48,16,96,0}}},
|
||||
{{"aes", 48,16,32,0,0},
|
||||
{"twofish",48,16,64,0,0},
|
||||
{"serpent",48,16,96,0,0}}},
|
||||
{0,2,96,"serpent-twofish", "lrw-benbi",
|
||||
{{"serpent",48,16,32,0},
|
||||
{"twofish",48,16,64,0}}},
|
||||
{{"serpent",48,16,32,0,0},
|
||||
{"twofish",48,16,64,0,0}}},
|
||||
|
||||
/* Kernel LRW block size is fixed to 16 bytes for GF(2^128)
|
||||
* thus cannot be used with blowfish where block is 8 bytes.
|
||||
* There also no GF(2^64) support.
|
||||
{1,1,64,"blowfish_le","lrw-benbi",
|
||||
{{"blowfish_le",64,8,32,0}}},
|
||||
{{"blowfish_le",64,8,32,0,0}}},
|
||||
{1,2,112,"blowfish_le-aes","lrw-benbi",
|
||||
{{"blowfish_le",64, 8,32,0},
|
||||
{"aes", 48,16,88,0}}},
|
||||
{{"blowfish_le",64, 8,32,0,0},
|
||||
{"aes", 48,16,88,0,0}}},
|
||||
{1,3,160,"serpent-blowfish_le-aes","lrw-benbi",
|
||||
{{"serpent", 48,16, 32,0},
|
||||
{"blowfish_le",64, 8, 64,0},
|
||||
{"aes", 48,16,120,0}}},*/
|
||||
/* CBC + "outer" CBC (both with whitening) */
|
||||
{1,1,32,"aes","cbc-tcrypt",
|
||||
{{"aes", 32,16,32,0}}},
|
||||
{1,1,32,"serpent","cbc-tcrypt",
|
||||
{{"serpent",32,16,32,0}}},
|
||||
{1,1,32,"twofish","cbc-tcrypt",
|
||||
{{"twofish",32,16,32,0}}},
|
||||
{1,2,64,"twofish-aes","cbci-tcrypt",
|
||||
{{"twofish",32,16,32,0},
|
||||
{"aes", 32,16,64,0}}},
|
||||
{1,3,96,"serpent-twofish-aes","cbci-tcrypt",
|
||||
{{"serpent",32,16,32,0},
|
||||
{"twofish",32,16,64,0},
|
||||
{"aes", 32,16,96,0}}},
|
||||
{1,2,64,"aes-serpent","cbci-tcrypt",
|
||||
{{"aes", 32,16,32,0},
|
||||
{"serpent",32,16,64,0}}},
|
||||
{1,3,96,"aes-twofish-serpent", "cbci-tcrypt",
|
||||
{{"aes", 32,16,32,0},
|
||||
{"twofish",32,16,64,0},
|
||||
{"serpent",32,16,96,0}}},
|
||||
{1,2,64,"serpent-twofish", "cbci-tcrypt",
|
||||
{{"serpent",32,16,32,0},
|
||||
{"twofish",32,16,64,0}}},
|
||||
{1,1,16,"cast5","cbc-tcrypt",
|
||||
{{"cast5", 16,8,32,0}}},
|
||||
{1,1,24,"des3_ede","cbc-tcrypt",
|
||||
{{"des3_ede",24,8,32,0}}},
|
||||
{1,1,56,"blowfish_le","cbc-tcrypt",
|
||||
{{"blowfish_le",56,8,32,0}}},
|
||||
{1,2,88,"blowfish_le-aes","cbc-tcrypt",
|
||||
{{"blowfish_le",56, 8,32,0},
|
||||
{"aes", 32,16,88,0}}},
|
||||
{1,3,120,"serpent-blowfish_le-aes","cbc-tcrypt",
|
||||
{{"serpent", 32,16, 32,0},
|
||||
{"blowfish_le",56, 8, 64,0},
|
||||
{"aes", 32,16,120,0}}},
|
||||
{{"serpent", 48,16, 32,0,0},
|
||||
{"blowfish_le",64, 8, 64,0,0},
|
||||
{"aes", 48,16,120,0,0}}},*/
|
||||
|
||||
/*
|
||||
* CBC + "outer" CBC (both with whitening)
|
||||
* chain_key_size: alg_keys_bytes + IV_seed_bytes + whitening_bytes
|
||||
*/
|
||||
{1,1,32+16+16,"aes","cbc-tcw",
|
||||
{{"aes", 32,16,32,0,32}}},
|
||||
{1,1,32+16+16,"serpent","cbc-tcw",
|
||||
{{"serpent",32,16,32,0,32}}},
|
||||
{1,1,32+16+16,"twofish","cbc-tcw",
|
||||
{{"twofish",32,16,32,0,32}}},
|
||||
{1,2,64+16+16,"twofish-aes","cbci-tcrypt",
|
||||
{{"twofish",32,16,32,0,0},
|
||||
{"aes", 32,16,64,0,32}}},
|
||||
{1,3,96+16+16,"serpent-twofish-aes","cbci-tcrypt",
|
||||
{{"serpent",32,16,32,0,0},
|
||||
{"twofish",32,16,64,0,0},
|
||||
{"aes", 32,16,96,0,32}}},
|
||||
{1,2,64+16+16,"aes-serpent","cbci-tcrypt",
|
||||
{{"aes", 32,16,32,0,0},
|
||||
{"serpent",32,16,64,0,32}}},
|
||||
{1,3,96+16+16,"aes-twofish-serpent", "cbci-tcrypt",
|
||||
{{"aes", 32,16,32,0,0},
|
||||
{"twofish",32,16,64,0,0},
|
||||
{"serpent",32,16,96,0,32}}},
|
||||
{1,2,64+16+16,"serpent-twofish", "cbci-tcrypt",
|
||||
{{"serpent",32,16,32,0,0},
|
||||
{"twofish",32,16,64,0,32}}},
|
||||
{1,1,16+8+16,"cast5","cbc-tcw",
|
||||
{{"cast5", 16,8,32,0,24}}},
|
||||
{1,1,24+8+16,"des3_ede","cbc-tcw",
|
||||
{{"des3_ede",24,8,32,0,24}}},
|
||||
{1,1,56+8+16,"blowfish_le","cbc-tcrypt",
|
||||
{{"blowfish_le",56,8,32,0,24}}},
|
||||
{1,2,88+16+16,"blowfish_le-aes","cbc-tcrypt",
|
||||
{{"blowfish_le",56, 8,32,0,0},
|
||||
{"aes", 32,16,88,0,32}}},
|
||||
{1,3,120+16+16,"serpent-blowfish_le-aes","cbc-tcrypt",
|
||||
{{"serpent", 32,16, 32,0,0},
|
||||
{"blowfish_le",56, 8, 64,0,0},
|
||||
{"aes", 32,16,120,0,32}}},
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -189,7 +203,7 @@ static int TCRYPT_hdr_from_disk(struct tcrypt_phdr *hdr,
|
||||
|
||||
/* Convert header to cpu format */
|
||||
hdr->d.version = be16_to_cpu(hdr->d.version);
|
||||
hdr->d.version_tc = le16_to_cpu(hdr->d.version_tc);
|
||||
hdr->d.version_tc = be16_to_cpu(hdr->d.version_tc);
|
||||
|
||||
hdr->d.keys_crc32 = be32_to_cpu(hdr->d.keys_crc32);
|
||||
|
||||
@@ -262,8 +276,8 @@ static int decrypt_blowfish_le_cbc(struct tcrypt_alg *alg,
|
||||
}
|
||||
|
||||
crypt_cipher_destroy(cipher);
|
||||
memset(iv, 0, bs);
|
||||
memset(iv_old, 0, bs);
|
||||
crypt_memzero(iv, bs);
|
||||
crypt_memzero(iv_old, bs);
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -289,6 +303,9 @@ static void TCRYPT_copy_key(struct tcrypt_alg *alg, const char *mode,
|
||||
memcpy(&out_key[ks2], key, TCRYPT_LRW_IKEY_LEN);
|
||||
} else if (!strncmp(mode, "cbc", 3)) {
|
||||
memcpy(out_key, &key[alg->key_offset], alg->key_size);
|
||||
/* IV + whitening */
|
||||
memcpy(&out_key[alg->key_size], &key[alg->iv_offset],
|
||||
alg->key_extra_size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -326,8 +343,8 @@ static int TCRYPT_decrypt_hdr_one(struct tcrypt_alg *alg, const char *mode,
|
||||
crypt_cipher_destroy(cipher);
|
||||
}
|
||||
|
||||
memset(backend_key, 0, sizeof(backend_key));
|
||||
memset(iv, 0, TCRYPT_HDR_IV_LEN);
|
||||
crypt_memzero(backend_key, sizeof(backend_key));
|
||||
crypt_memzero(iv, TCRYPT_HDR_IV_LEN);
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -377,19 +394,19 @@ out:
|
||||
if (cipher[j])
|
||||
crypt_cipher_destroy(cipher[j]);
|
||||
|
||||
memset(iv, 0, bs);
|
||||
memset(iv_old, 0, bs);
|
||||
crypt_memzero(iv, bs);
|
||||
crypt_memzero(iv_old, bs);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int TCRYPT_decrypt_hdr(struct crypt_device *cd, struct tcrypt_phdr *hdr,
|
||||
const char *key, int legacy_modes)
|
||||
const char *key, uint32_t flags)
|
||||
{
|
||||
struct tcrypt_phdr hdr2;
|
||||
int i, j, r = -EINVAL;
|
||||
|
||||
for (i = 0; tcrypt_cipher[i].chain_count; i++) {
|
||||
if (!legacy_modes && tcrypt_cipher[i].legacy)
|
||||
if (!(flags & CRYPT_TCRYPT_LEGACY_MODES) && tcrypt_cipher[i].legacy)
|
||||
continue;
|
||||
log_dbg("TCRYPT: trying cipher %s-%s",
|
||||
tcrypt_cipher[i].long_name, tcrypt_cipher[i].mode);
|
||||
@@ -421,10 +438,17 @@ static int TCRYPT_decrypt_hdr(struct crypt_device *cd, struct tcrypt_phdr *hdr,
|
||||
r = i;
|
||||
break;
|
||||
}
|
||||
if ((flags & CRYPT_TCRYPT_VERA_MODES) &&
|
||||
!strncmp(hdr2.d.magic, VCRYPT_HDR_MAGIC, TCRYPT_HDR_MAGIC_LEN)) {
|
||||
log_dbg("TCRYPT: Signature magic detected (Veracrypt).");
|
||||
memcpy(&hdr->e, &hdr2.e, TCRYPT_HDR_LEN);
|
||||
r = i;
|
||||
break;
|
||||
}
|
||||
r = -EPERM;
|
||||
}
|
||||
|
||||
memset(&hdr2, 0, sizeof(hdr2));
|
||||
crypt_memzero(&hdr2, sizeof(hdr2));
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -461,8 +485,8 @@ static int TCRYPT_pool_keyfile(struct crypt_device *cd,
|
||||
j %= TCRYPT_KEY_POOL_LEN;
|
||||
}
|
||||
|
||||
memset(&crc, 0, sizeof(crc));
|
||||
memset(data, 0, TCRYPT_KEYFILE_LEN);
|
||||
crypt_memzero(&crc, sizeof(crc));
|
||||
crypt_memzero(data, TCRYPT_KEYFILE_LEN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -475,7 +499,7 @@ static int TCRYPT_init_hdr(struct crypt_device *cd,
|
||||
size_t passphrase_size;
|
||||
char *key;
|
||||
unsigned int i, skipped = 0;
|
||||
int r = -EINVAL, legacy_modes;
|
||||
int r = -EPERM;
|
||||
|
||||
if (posix_memalign((void*)&key, crypt_getpagesize(), TCRYPT_HDR_KEY_LEN))
|
||||
return -ENOMEM;
|
||||
@@ -488,7 +512,7 @@ static int TCRYPT_init_hdr(struct crypt_device *cd,
|
||||
if (params->passphrase_size > TCRYPT_KEY_POOL_LEN) {
|
||||
log_err(cd, _("Maximum TCRYPT passphrase length (%d) exceeded.\n"),
|
||||
TCRYPT_KEY_POOL_LEN);
|
||||
return -EPERM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Calculate pool content from keyfiles */
|
||||
@@ -502,9 +526,10 @@ static int TCRYPT_init_hdr(struct crypt_device *cd,
|
||||
for (i = 0; i < params->passphrase_size; i++)
|
||||
pwd[i] += params->passphrase[i];
|
||||
|
||||
legacy_modes = params->flags & CRYPT_TCRYPT_LEGACY_MODES ? 1 : 0;
|
||||
for (i = 0; tcrypt_kdf[i].name; i++) {
|
||||
if (!legacy_modes && tcrypt_kdf[i].legacy)
|
||||
if (!(params->flags & CRYPT_TCRYPT_LEGACY_MODES) && tcrypt_kdf[i].legacy)
|
||||
continue;
|
||||
if (!(params->flags & CRYPT_TCRYPT_VERA_MODES) && tcrypt_kdf[i].veracrypt)
|
||||
continue;
|
||||
/* Derive header key */
|
||||
log_dbg("TCRYPT: trying KDF: %s-%s-%d.",
|
||||
@@ -523,16 +548,16 @@ static int TCRYPT_init_hdr(struct crypt_device *cd,
|
||||
break;
|
||||
|
||||
/* Decrypt header */
|
||||
r = TCRYPT_decrypt_hdr(cd, hdr, key, legacy_modes);
|
||||
r = TCRYPT_decrypt_hdr(cd, hdr, key, params->flags);
|
||||
if (r == -ENOENT) {
|
||||
skipped++;
|
||||
continue;
|
||||
r = -EPERM;
|
||||
}
|
||||
if (r != -EPERM)
|
||||
break;
|
||||
}
|
||||
|
||||
if ((skipped && skipped == i) || r == -ENOTSUP) {
|
||||
if ((r < 0 && r != -EPERM && skipped && skipped == i) || r == -ENOTSUP) {
|
||||
log_err(cd, _("Required kernel crypto interface not available.\n"));
|
||||
#ifdef ENABLE_AF_ALG
|
||||
log_err(cd, _("Ensure you have algif_skcipher kernel module loaded.\n"));
|
||||
@@ -543,18 +568,19 @@ static int TCRYPT_init_hdr(struct crypt_device *cd,
|
||||
|
||||
r = TCRYPT_hdr_from_disk(hdr, params, i, r);
|
||||
if (!r) {
|
||||
log_dbg("TCRYPT: Header version: %d, req. %d, sector %d"
|
||||
log_dbg("TCRYPT: Magic: %s, Header version: %d, req. %d, sector %d"
|
||||
", mk_offset %" PRIu64 ", hidden_size %" PRIu64
|
||||
", volume size %" PRIu64, (int)hdr->d.version,
|
||||
(int)hdr->d.version_tc, (int)hdr->d.sector_size,
|
||||
", volume size %" PRIu64, tcrypt_kdf[i].veracrypt ?
|
||||
VCRYPT_HDR_MAGIC : TCRYPT_HDR_MAGIC,
|
||||
(int)hdr->d.version, (int)hdr->d.version_tc, (int)hdr->d.sector_size,
|
||||
hdr->d.mk_offset, hdr->d.hidden_volume_size, hdr->d.volume_size);
|
||||
log_dbg("TCRYPT: Header cipher %s-%s, key size %d",
|
||||
log_dbg("TCRYPT: Header cipher %s-%s, key size %zu",
|
||||
params->cipher, params->mode, params->key_size);
|
||||
}
|
||||
out:
|
||||
memset(pwd, 0, TCRYPT_KEY_POOL_LEN);
|
||||
crypt_memzero(pwd, TCRYPT_KEY_POOL_LEN);
|
||||
if (key)
|
||||
memset(key, 0, TCRYPT_HDR_KEY_LEN);
|
||||
crypt_memzero(key, TCRYPT_HDR_KEY_LEN);
|
||||
free(key);
|
||||
return r;
|
||||
}
|
||||
@@ -563,20 +589,37 @@ int TCRYPT_read_phdr(struct crypt_device *cd,
|
||||
struct tcrypt_phdr *hdr,
|
||||
struct crypt_params_tcrypt *params)
|
||||
{
|
||||
struct device *device = crypt_metadata_device(cd);
|
||||
struct device *base_device, *device = crypt_metadata_device(cd);
|
||||
ssize_t hdr_size = sizeof(struct tcrypt_phdr);
|
||||
char *base_device_path;
|
||||
int devfd = 0, r, bs;
|
||||
|
||||
assert(sizeof(struct tcrypt_phdr) == 512);
|
||||
|
||||
log_dbg("Reading TCRYPT header of size %d bytes from device %s.",
|
||||
log_dbg("Reading TCRYPT header of size %zu bytes from device %s.",
|
||||
hdr_size, device_path(device));
|
||||
|
||||
bs = device_block_size(device);
|
||||
if (bs < 0)
|
||||
return bs;
|
||||
|
||||
devfd = device_open(device, O_RDONLY);
|
||||
if (params->flags & CRYPT_TCRYPT_SYSTEM_HEADER &&
|
||||
crypt_dev_is_partition(device_path(device))) {
|
||||
base_device_path = crypt_get_base_device(device_path(device));
|
||||
|
||||
log_dbg("Reading TCRYPT system header from device %s.", base_device_path ?: "?");
|
||||
if (!base_device_path)
|
||||
return -EINVAL;
|
||||
|
||||
r = device_alloc(&base_device, base_device_path);
|
||||
if (r < 0)
|
||||
return r;
|
||||
devfd = device_open(base_device, O_RDONLY);
|
||||
free(base_device_path);
|
||||
device_free(base_device);
|
||||
} else
|
||||
devfd = device_open(device, O_RDONLY);
|
||||
|
||||
if (devfd == -1) {
|
||||
log_err(cd, _("Cannot open device %s.\n"), device_path(device));
|
||||
return -EINVAL;
|
||||
@@ -587,10 +630,6 @@ int TCRYPT_read_phdr(struct crypt_device *cd,
|
||||
if (lseek(devfd, TCRYPT_HDR_SYSTEM_OFFSET, SEEK_SET) >= 0 &&
|
||||
read_blockwise(devfd, bs, hdr, hdr_size) == hdr_size) {
|
||||
r = TCRYPT_init_hdr(cd, hdr, params);
|
||||
if (r == -EPERM && crypt_dev_is_partition(device_path(device)))
|
||||
log_std(cd, _("WARNING: device %s is a partition, for TCRYPT "
|
||||
"system encryption you usually need to use "
|
||||
"whole block device path.\n"), device_path(device));
|
||||
}
|
||||
} else if (params->flags & CRYPT_TCRYPT_HIDDEN_HEADER) {
|
||||
if (params->flags & CRYPT_TCRYPT_BACKUP_HEADER) {
|
||||
@@ -645,6 +684,7 @@ int TCRYPT_activate(struct crypt_device *cd,
|
||||
struct device *device = NULL, *part_device = NULL;
|
||||
unsigned int i;
|
||||
int r;
|
||||
uint32_t req_flags;
|
||||
struct tcrypt_algs *algs;
|
||||
enum devcheck device_check;
|
||||
struct crypt_dm_active_device dmd = {
|
||||
@@ -674,47 +714,61 @@ int TCRYPT_activate(struct crypt_device *cd,
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if (strstr(params->mode, "-tcw"))
|
||||
req_flags = DM_TCW_SUPPORTED;
|
||||
else
|
||||
req_flags = DM_PLAIN64_SUPPORTED;
|
||||
|
||||
algs = TCRYPT_get_algs(params->cipher, params->mode);
|
||||
if (!algs)
|
||||
return -EINVAL;
|
||||
|
||||
if (params->flags & CRYPT_TCRYPT_HIDDEN_HEADER)
|
||||
if (params->flags & CRYPT_TCRYPT_SYSTEM_HEADER)
|
||||
dmd.size = 0;
|
||||
else if (params->flags & CRYPT_TCRYPT_HIDDEN_HEADER)
|
||||
dmd.size = hdr->d.hidden_volume_size / hdr->d.sector_size;
|
||||
else
|
||||
dmd.size = hdr->d.volume_size / hdr->d.sector_size;
|
||||
|
||||
/*
|
||||
* System encryption use the whole device mapping, there can
|
||||
* be active partitions.
|
||||
* FIXME: This will allow multiple mappings unexpectedly.
|
||||
*/
|
||||
if ((dmd.flags & CRYPT_ACTIVATE_SHARED) ||
|
||||
(params->flags & CRYPT_TCRYPT_SYSTEM_HEADER))
|
||||
if (dmd.flags & CRYPT_ACTIVATE_SHARED)
|
||||
device_check = DEV_SHARED;
|
||||
else
|
||||
device_check = DEV_EXCL;
|
||||
|
||||
if ((params->flags & CRYPT_TCRYPT_SYSTEM_HEADER) &&
|
||||
(part_path = crypt_get_partition_device(device_path(dmd.data_device),
|
||||
dmd.u.crypt.offset, dmd.size))) {
|
||||
if (!device_alloc(&part_device, part_path)) {
|
||||
log_verbose(cd, _("Activating TCRYPT system encryption for partition %s.\n"),
|
||||
part_path);
|
||||
dmd.data_device = part_device;
|
||||
dmd.u.crypt.offset = 0;
|
||||
}
|
||||
free(part_path);
|
||||
!crypt_dev_is_partition(device_path(dmd.data_device))) {
|
||||
part_path = crypt_get_partition_device(device_path(dmd.data_device),
|
||||
dmd.u.crypt.offset, dmd.size);
|
||||
if (part_path) {
|
||||
if (!device_alloc(&part_device, part_path)) {
|
||||
log_verbose(cd, _("Activating TCRYPT system encryption for partition %s.\n"),
|
||||
part_path);
|
||||
dmd.data_device = part_device;
|
||||
dmd.u.crypt.offset = 0;
|
||||
}
|
||||
free(part_path);
|
||||
} else
|
||||
/*
|
||||
* System encryption use the whole device mapping, there can
|
||||
* be active partitions.
|
||||
*/
|
||||
device_check = DEV_SHARED;
|
||||
}
|
||||
|
||||
r = device_block_adjust(cd, dmd.data_device, device_check,
|
||||
dmd.u.crypt.offset, &dmd.size, &dmd.flags);
|
||||
if (r)
|
||||
if (r) {
|
||||
device_free(part_device);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Frome here, key size for every cipher must be the same */
|
||||
dmd.u.crypt.vk = crypt_alloc_volume_key(algs->cipher[0].key_size, NULL);
|
||||
if (!dmd.u.crypt.vk)
|
||||
dmd.u.crypt.vk = crypt_alloc_volume_key(algs->cipher[0].key_size +
|
||||
algs->cipher[0].key_extra_size, NULL);
|
||||
if (!dmd.u.crypt.vk) {
|
||||
device_free(part_device);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
for (i = algs->chain_count; i > 0; i--) {
|
||||
if (i == 1) {
|
||||
@@ -752,8 +806,8 @@ int TCRYPT_activate(struct crypt_device *cd,
|
||||
break;
|
||||
}
|
||||
|
||||
if (r < 0 && !(dm_flags() & DM_PLAIN64_SUPPORTED)) {
|
||||
log_err(cd, _("Kernel doesn't support plain64 IV.\n"));
|
||||
if (r < 0 && !(dm_flags() & req_flags)) {
|
||||
log_err(cd, _("Kernel doesn't support TCRYPT compatible mapping.\n"));
|
||||
r = -ENOTSUP;
|
||||
}
|
||||
|
||||
@@ -907,8 +961,11 @@ uint64_t TCRYPT_get_data_offset(struct crypt_device *cd,
|
||||
goto hdr_offset;
|
||||
|
||||
/* Mapping through whole device, not partition! */
|
||||
if (params->flags & CRYPT_TCRYPT_SYSTEM_HEADER)
|
||||
if (params->flags & CRYPT_TCRYPT_SYSTEM_HEADER) {
|
||||
if (crypt_dev_is_partition(device_path(crypt_metadata_device(cd))))
|
||||
return 0;
|
||||
goto hdr_offset;
|
||||
}
|
||||
|
||||
if (params->mode && !strncmp(params->mode, "xts", 3)) {
|
||||
if (hdr->d.version < 3)
|
||||
@@ -938,15 +995,21 @@ hdr_offset:
|
||||
|
||||
uint64_t TCRYPT_get_iv_offset(struct crypt_device *cd,
|
||||
struct tcrypt_phdr *hdr,
|
||||
struct crypt_params_tcrypt *params
|
||||
)
|
||||
struct crypt_params_tcrypt *params)
|
||||
{
|
||||
if (params->mode && !strncmp(params->mode, "xts", 3))
|
||||
return TCRYPT_get_data_offset(cd, hdr, params);
|
||||
else if (params->mode && !strncmp(params->mode, "lrw", 3))
|
||||
return 0;
|
||||
uint64_t iv_offset;
|
||||
|
||||
return hdr->d.mk_offset / hdr->d.sector_size;
|
||||
if (params->mode && !strncmp(params->mode, "xts", 3))
|
||||
iv_offset = TCRYPT_get_data_offset(cd, hdr, params);
|
||||
else if (params->mode && !strncmp(params->mode, "lrw", 3))
|
||||
iv_offset = 0;
|
||||
else
|
||||
iv_offset = hdr->d.mk_offset / hdr->d.sector_size;
|
||||
|
||||
if (params->flags & CRYPT_TCRYPT_SYSTEM_HEADER)
|
||||
iv_offset += crypt_dev_partition_offset(device_path(crypt_metadata_device(cd)));
|
||||
|
||||
return iv_offset;
|
||||
}
|
||||
|
||||
int TCRYPT_get_volume_key(struct crypt_device *cd,
|
||||
@@ -983,11 +1046,13 @@ int TCRYPT_dump(struct crypt_device *cd,
|
||||
struct tcrypt_phdr *hdr,
|
||||
struct crypt_params_tcrypt *params)
|
||||
{
|
||||
log_std(cd, "TCRYPT header information for %s\n",
|
||||
log_std(cd, "%s header information for %s\n",
|
||||
hdr->d.magic[0] == 'T' ? "TCRYPT" : "VERACRYPT",
|
||||
device_path(crypt_metadata_device(cd)));
|
||||
if (hdr->d.version) {
|
||||
log_std(cd, "Version: \t%d\n", hdr->d.version);
|
||||
log_std(cd, "Driver req.:\t%d\n", hdr->d.version_tc);
|
||||
log_std(cd, "Driver req.:\t%x.%x\n", hdr->d.version_tc >> 8,
|
||||
hdr->d.version_tc & 0xFF);
|
||||
|
||||
log_std(cd, "Sector size:\t%" PRIu32 "\n", hdr->d.sector_size);
|
||||
log_std(cd, "MK offset:\t%" PRIu64 "\n", hdr->d.mk_offset);
|
||||
@@ -995,6 +1060,6 @@ int TCRYPT_dump(struct crypt_device *cd,
|
||||
}
|
||||
log_std(cd, "Cipher chain:\t%s\n", params->cipher);
|
||||
log_std(cd, "Cipher mode:\t%s\n", params->mode);
|
||||
log_std(cd, "MK bits: \t%d\n", params->key_size * 8);
|
||||
log_std(cd, "MK bits: \t%zu\n", params->key_size * 8);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* TCRYPT (TrueCrypt-compatible) header defitinion
|
||||
*
|
||||
* Copyright (C) 2012, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2012-2013, Milan Broz
|
||||
* Copyright (C) 2012-2014, Milan Broz
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -29,6 +29,7 @@
|
||||
#define TCRYPT_HDR_LEN 448
|
||||
#define TCRYPT_HDR_KEY_LEN 192
|
||||
#define TCRYPT_HDR_MAGIC "TRUE"
|
||||
#define VCRYPT_HDR_MAGIC "VERA"
|
||||
#define TCRYPT_HDR_MAGIC_LEN 4
|
||||
|
||||
#define TCRYPT_HDR_HIDDEN_OFFSET_OLD -1536
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* utils - miscellaneous device utilities for cryptsetup
|
||||
*
|
||||
* Copyright (C) 2004, Christophe Saout <christophe@saout.de>
|
||||
* Copyright (C) 2004, Jana Saout <jana@saout.de>
|
||||
* Copyright (C) 2004-2007, Clemens Fruhwirth <clemens@endorphin.org>
|
||||
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2009-2012, Milan Broz
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* libcryptsetup - cryptsetup library, cipher bechmark
|
||||
*
|
||||
* Copyright (C) 2012, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2012, Milan Broz
|
||||
* Copyright (C) 2012-2013, Milan Broz
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -21,8 +21,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
@@ -32,6 +31,12 @@
|
||||
*/
|
||||
#define CIPHER_BLOCK_BYTES 65536
|
||||
|
||||
/*
|
||||
* If the measured value is lower, encrypted buffer is probably too small
|
||||
* and calculated values are not reliable.
|
||||
*/
|
||||
#define CIPHER_TIME_MIN_MS 0.001
|
||||
|
||||
/*
|
||||
* The whole test depends on Linux kernel usermode crypto API for now.
|
||||
* (The same implementations are used in dm-crypt though.)
|
||||
@@ -47,19 +52,15 @@ struct cipher_perf {
|
||||
size_t buffer_size;
|
||||
};
|
||||
|
||||
static long time_ms(struct rusage *start, struct rusage *end)
|
||||
static int time_ms(struct timespec *start, struct timespec *end, double *ms)
|
||||
{
|
||||
long ms = 0;
|
||||
double start_ms, end_ms;
|
||||
|
||||
/* For kernel backend, we need to measure only tim in kernel.
|
||||
ms = (end->ru_utime.tv_sec - start->ru_utime.tv_sec) * 1000;
|
||||
ms += (end->ru_utime.tv_usec - start->ru_utime.tv_usec) / 1000;
|
||||
*/
|
||||
start_ms = start->tv_sec * 1000.0 + start->tv_nsec / (1000.0 * 1000);
|
||||
end_ms = end->tv_sec * 1000.0 + end->tv_nsec / (1000.0 * 1000);
|
||||
|
||||
ms += (end->ru_stime.tv_sec - start->ru_stime.tv_sec) * 1000;
|
||||
ms += (end->ru_stime.tv_usec - start->ru_stime.tv_usec) / 1000;
|
||||
|
||||
return ms;
|
||||
*ms = end_ms - start_ms;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cipher_perf_one(struct cipher_perf *cp, char *buf,
|
||||
@@ -98,26 +99,39 @@ static int cipher_perf_one(struct cipher_perf *cp, char *buf,
|
||||
|
||||
return r;
|
||||
}
|
||||
static long cipher_measure(struct cipher_perf *cp, char *buf,
|
||||
size_t buf_size, int encrypt)
|
||||
static int cipher_measure(struct cipher_perf *cp, char *buf,
|
||||
size_t buf_size, int encrypt, double *ms)
|
||||
{
|
||||
struct rusage rstart, rend;
|
||||
struct timespec start, end;
|
||||
int r;
|
||||
|
||||
if (getrusage(RUSAGE_SELF, &rstart) < 0)
|
||||
/*
|
||||
* Using getrusage would be better here but the precision
|
||||
* is not adequate, so better stick with CLOCK_MONOTONIC
|
||||
*/
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &start) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
r = cipher_perf_one(cp, buf, buf_size, encrypt);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (getrusage(RUSAGE_SELF, &rend) < 0)
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &end) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
return time_ms(&rstart, &rend);
|
||||
r = time_ms(&start, &end, ms);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (*ms < CIPHER_TIME_MIN_MS) {
|
||||
log_dbg("Measured cipher runtime (%1.6f) is too low.", *ms);
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static double speed_mbs(unsigned long bytes, unsigned long ms)
|
||||
static double speed_mbs(unsigned long bytes, double ms)
|
||||
{
|
||||
double speed = bytes, s = ms / 1000.;
|
||||
|
||||
@@ -127,32 +141,32 @@ static double speed_mbs(unsigned long bytes, unsigned long ms)
|
||||
static int cipher_perf(struct cipher_perf *cp,
|
||||
double *encryption_mbs, double *decryption_mbs)
|
||||
{
|
||||
long ms_enc, ms_dec, ms;
|
||||
int repeat_enc, repeat_dec;
|
||||
double ms_enc, ms_dec, ms;
|
||||
int r, repeat_enc, repeat_dec;
|
||||
void *buf = NULL;
|
||||
|
||||
if (posix_memalign(&buf, crypt_getpagesize(), cp->buffer_size))
|
||||
return -ENOMEM;
|
||||
|
||||
ms_enc = 0;
|
||||
ms_enc = 0.0;
|
||||
repeat_enc = 1;
|
||||
while (ms_enc < 1000) {
|
||||
ms = cipher_measure(cp, buf, cp->buffer_size, 1);
|
||||
if (ms < 0) {
|
||||
while (ms_enc < 1000.0) {
|
||||
r = cipher_measure(cp, buf, cp->buffer_size, 1, &ms);
|
||||
if (r < 0) {
|
||||
free(buf);
|
||||
return (int)ms;
|
||||
return r;
|
||||
}
|
||||
ms_enc += ms;
|
||||
repeat_enc++;
|
||||
}
|
||||
|
||||
ms_dec = 0;
|
||||
ms_dec = 0.0;
|
||||
repeat_dec = 1;
|
||||
while (ms_dec < 1000) {
|
||||
ms = cipher_measure(cp, buf, cp->buffer_size, 0);
|
||||
if (ms < 0) {
|
||||
while (ms_dec < 1000.0) {
|
||||
r = cipher_measure(cp, buf, cp->buffer_size, 0, &ms);
|
||||
if (r < 0) {
|
||||
free(buf);
|
||||
return (int)ms;
|
||||
return r;
|
||||
}
|
||||
ms_dec += ms;
|
||||
repeat_dec++;
|
||||
@@ -226,7 +240,7 @@ int crypt_benchmark_kdf(struct crypt_device *cd,
|
||||
size_t salt_size,
|
||||
uint64_t *iterations_sec)
|
||||
{
|
||||
int r;
|
||||
int r, key_length = 0;
|
||||
|
||||
if (!iterations_sec)
|
||||
return -EINVAL;
|
||||
@@ -235,14 +249,21 @@ int crypt_benchmark_kdf(struct crypt_device *cd,
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
// FIXME: this should be in KDF check API parameters later
|
||||
if (cd)
|
||||
key_length = crypt_get_volume_key_size(cd);
|
||||
|
||||
if (key_length == 0)
|
||||
key_length = DEFAULT_LUKS1_KEYBITS / 8;
|
||||
|
||||
if (!strncmp(kdf, "pbkdf2", 6))
|
||||
r = crypt_pbkdf_check(kdf, hash, password, password_size,
|
||||
salt, salt_size, iterations_sec);
|
||||
salt, salt_size, key_length, iterations_sec);
|
||||
else
|
||||
r = -EINVAL;
|
||||
|
||||
if (!r)
|
||||
log_dbg("KDF %s, hash %s: %" PRIu64 " iterations per second.",
|
||||
kdf, hash, *iterations_sec);
|
||||
log_dbg("KDF %s, hash %s: %" PRIu64 " iterations per second (%d-bits key).",
|
||||
kdf, hash, *iterations_sec, key_length * 8);
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -81,6 +81,18 @@ int crypt_parse_name_and_mode(const char *s, char *cipher, int *key_nums,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Replacement for memset(s, 0, n) on stack that can be optimized out
|
||||
* Also used in safe allocations for explicit memory wipe.
|
||||
*/
|
||||
void crypt_memzero(void *s, size_t n)
|
||||
{
|
||||
volatile uint8_t *p = (volatile uint8_t *)s;
|
||||
|
||||
while(n--)
|
||||
*p++ = 0;
|
||||
}
|
||||
|
||||
/* safe allocations */
|
||||
void *crypt_safe_alloc(size_t size)
|
||||
{
|
||||
@@ -94,7 +106,7 @@ void *crypt_safe_alloc(size_t size)
|
||||
return NULL;
|
||||
|
||||
alloc->size = size;
|
||||
memset(&alloc->data, 0, size);
|
||||
crypt_memzero(&alloc->data, size);
|
||||
|
||||
/* coverity[leaked_storage] */
|
||||
return &alloc->data;
|
||||
@@ -110,7 +122,7 @@ void crypt_safe_free(void *data)
|
||||
alloc = (struct safe_allocation *)
|
||||
((char *)data - offsetof(struct safe_allocation, data));
|
||||
|
||||
memset(data, 0, alloc->size);
|
||||
crypt_memzero(data, alloc->size);
|
||||
|
||||
alloc->size = 0x55aa55aa;
|
||||
free(alloc);
|
||||
@@ -157,7 +169,7 @@ static int untimed_read(int fd, char *pass, size_t maxlen)
|
||||
static int timed_read(int fd, char *pass, size_t maxlen, long timeout)
|
||||
{
|
||||
struct timeval t;
|
||||
fd_set fds;
|
||||
fd_set fds = {}; /* Just to avoid scan-build false report for FD_SET */
|
||||
int failed = -1;
|
||||
|
||||
FD_ZERO(&fds);
|
||||
@@ -176,16 +188,18 @@ static int interactive_pass(const char *prompt, char *pass, size_t maxlen,
|
||||
{
|
||||
struct termios orig, tmp;
|
||||
int failed = -1;
|
||||
int infd = STDIN_FILENO, outfd;
|
||||
int infd, outfd;
|
||||
|
||||
if (maxlen < 1)
|
||||
goto out_err;
|
||||
return failed;
|
||||
|
||||
/* Read and write to /dev/tty if available */
|
||||
if ((infd = outfd = open("/dev/tty", O_RDWR)) == -1) {
|
||||
infd = open("/dev/tty", O_RDWR);
|
||||
if (infd == -1) {
|
||||
infd = STDIN_FILENO;
|
||||
outfd = STDERR_FILENO;
|
||||
}
|
||||
} else
|
||||
outfd = infd;
|
||||
|
||||
if (tcgetattr(infd, &orig))
|
||||
goto out_err;
|
||||
@@ -320,7 +334,7 @@ int crypt_get_key(const char *prompt,
|
||||
struct crypt_device *cd)
|
||||
{
|
||||
int fd, regular_file, read_stdin, char_read, unlimited_read = 0;
|
||||
int r = -EINVAL;
|
||||
int r = -EINVAL, newline;
|
||||
char *pass = NULL;
|
||||
size_t buflen, i, file_read_size;
|
||||
struct stat st;
|
||||
@@ -394,7 +408,7 @@ int crypt_get_key(const char *prompt,
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
for(i = 0; i < keyfile_size_max; i++) {
|
||||
for(i = 0, newline = 0; i < keyfile_size_max; i++) {
|
||||
if(i == buflen) {
|
||||
buflen += 4096;
|
||||
pass = crypt_safe_realloc(pass, buflen);
|
||||
@@ -412,12 +426,17 @@ int crypt_get_key(const char *prompt,
|
||||
}
|
||||
|
||||
/* Stop on newline only if not requested read from keyfile */
|
||||
if(char_read == 0 || (!key_file && pass[i] == '\n'))
|
||||
if (char_read == 0)
|
||||
break;
|
||||
if (!key_file && pass[i] == '\n') {
|
||||
newline = 1;
|
||||
pass[i] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Fail if piped input dies reading nothing */
|
||||
if(!i && !regular_file) {
|
||||
if(!i && !regular_file && !newline) {
|
||||
log_dbg("Nothing read on input.");
|
||||
r = -EPIPE;
|
||||
goto out_err;
|
||||
@@ -471,68 +490,3 @@ ssize_t crypt_hex_to_bytes(const char *hex, char **result, int safe_alloc)
|
||||
*result = bytes;
|
||||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
* Device size string parsing, suffixes:
|
||||
* s|S - 512 bytes sectors
|
||||
* k |K |m |M |g |G |t |T - 1024 base
|
||||
* kiB|KiB|miB|MiB|giB|GiB|tiB|TiB - 1024 base
|
||||
* kb |KB |mM |MB |gB |GB |tB |TB - 1000 base
|
||||
*/
|
||||
int crypt_string_to_size(struct crypt_device *cd, const char *s, uint64_t *size)
|
||||
{
|
||||
char *endp = NULL;
|
||||
size_t len;
|
||||
uint64_t mult_base, mult, tmp;
|
||||
|
||||
*size = strtoull(s, &endp, 10);
|
||||
if (!isdigit(s[0]) ||
|
||||
(errno == ERANGE && *size == ULLONG_MAX) ||
|
||||
(errno != 0 && *size == 0))
|
||||
return -EINVAL;
|
||||
|
||||
if (!endp || !*endp)
|
||||
return 0;
|
||||
|
||||
len = strlen(endp);
|
||||
/* Allow "B" and "iB" suffixes */
|
||||
if (len > 3 ||
|
||||
(len == 3 && (endp[1] != 'i' || endp[2] != 'B')) ||
|
||||
(len == 2 && endp[1] != 'B'))
|
||||
return -EINVAL;
|
||||
|
||||
if (len == 1 || len == 3)
|
||||
mult_base = 1024;
|
||||
else
|
||||
mult_base = 1000;
|
||||
|
||||
mult = 1;
|
||||
switch (endp[0]) {
|
||||
case 's':
|
||||
case 'S': mult = 512;
|
||||
break;
|
||||
case 't':
|
||||
case 'T': mult *= mult_base;
|
||||
/* Fall through */
|
||||
case 'g':
|
||||
case 'G': mult *= mult_base;
|
||||
/* Fall through */
|
||||
case 'm':
|
||||
case 'M': mult *= mult_base;
|
||||
/* Fall through */
|
||||
case 'k':
|
||||
case 'K': mult *= mult_base;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tmp = *size * mult;
|
||||
if ((tmp / *size) != mult) {
|
||||
log_dbg("Device size overflow.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*size = tmp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -45,7 +45,8 @@ void *crypt_safe_alloc(size_t size);
|
||||
void crypt_safe_free(void *data);
|
||||
void *crypt_safe_realloc(void *data, size_t size);
|
||||
|
||||
void crypt_memzero(void *s, size_t n);
|
||||
|
||||
ssize_t crypt_hex_to_bytes(const char *hex, char **result, int safe_alloc);
|
||||
int crypt_string_to_size(struct crypt_device *cd, const char *s, uint64_t *size);
|
||||
|
||||
#endif /* _UTILS_CRYPT_H */
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
/*
|
||||
* device backend utilities
|
||||
*
|
||||
* Copyright (C) 2004, Christophe Saout <christophe@saout.de>
|
||||
* Copyright (C) 2004, Jana Saout <jana@saout.de>
|
||||
* Copyright (C) 2004-2007, Clemens Fruhwirth <clemens@endorphin.org>
|
||||
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2009-2012, Milan Broz
|
||||
* Copyright (C) 2009-2015, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2009-2015, Milan Broz
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -38,20 +38,106 @@ struct device {
|
||||
char *file_path;
|
||||
int loop_fd;
|
||||
|
||||
int o_direct:1;
|
||||
int init_done:1;
|
||||
};
|
||||
|
||||
static int device_ready(const char *device)
|
||||
static int device_block_size_fd(int fd, size_t *min_size)
|
||||
{
|
||||
int devfd, r = 0;
|
||||
struct stat st;
|
||||
int bsize = 0, r = -EINVAL;
|
||||
|
||||
if (fstat(fd, &st) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (S_ISREG(st.st_mode))
|
||||
r = (int)crypt_getpagesize();
|
||||
else if (ioctl(fd, BLKSSZGET, &bsize) >= 0)
|
||||
r = bsize;
|
||||
else
|
||||
r = -EINVAL;
|
||||
|
||||
if (r < 0 || !min_size)
|
||||
return r;
|
||||
|
||||
if (S_ISREG(st.st_mode)) {
|
||||
/* file can be empty as well */
|
||||
if (st.st_size > bsize)
|
||||
*min_size = bsize;
|
||||
else
|
||||
*min_size = st.st_size;
|
||||
} else {
|
||||
/* block device must have at least one block */
|
||||
*min_size = bsize;
|
||||
}
|
||||
|
||||
return bsize;
|
||||
}
|
||||
|
||||
static int device_read_test(int devfd)
|
||||
{
|
||||
char buffer[512];
|
||||
int blocksize, r = -EIO;
|
||||
size_t minsize = 0;
|
||||
|
||||
blocksize = device_block_size_fd(devfd, &minsize);
|
||||
|
||||
if (blocksize < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (minsize == 0)
|
||||
return 0;
|
||||
|
||||
if (minsize > sizeof(buffer))
|
||||
minsize = sizeof(buffer);
|
||||
|
||||
if (read_blockwise(devfd, blocksize, buffer, minsize) == (ssize_t)minsize)
|
||||
r = 0;
|
||||
|
||||
crypt_memzero(buffer, sizeof(buffer));
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* The direct-io is always preferred. The header is usually mapped to the same
|
||||
* device and can be accessed when the rest of device is mapped to data device.
|
||||
* Using dirct-io encsures that we do not mess with data in cache.
|
||||
* (But proper alignment should prevent this in the first place.)
|
||||
* The read test is needed to detect broken configurations (seen with remote
|
||||
* block devices) that allow open with direct-io but then fails on read.
|
||||
*/
|
||||
static int device_ready(struct device *device, int check_directio)
|
||||
{
|
||||
int devfd = -1, r = 0;
|
||||
struct stat st;
|
||||
|
||||
log_dbg("Trying to open and read device %s.", device);
|
||||
devfd = open(device, O_RDONLY);
|
||||
device->o_direct = 0;
|
||||
if (check_directio) {
|
||||
log_dbg("Trying to open and read device %s with direct-io.",
|
||||
device_path(device));
|
||||
devfd = open(device_path(device), O_RDONLY | O_DIRECT);
|
||||
if (devfd >= 0) {
|
||||
if (device_read_test(devfd) == 0) {
|
||||
device->o_direct = 1;
|
||||
} else {
|
||||
close(devfd);
|
||||
devfd = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (devfd < 0) {
|
||||
log_err(NULL, _("Device %s doesn't exist or access denied.\n"), device);
|
||||
log_dbg("Trying to open device %s without direct-io.",
|
||||
device_path(device));
|
||||
devfd = open(device_path(device), O_RDONLY);
|
||||
}
|
||||
|
||||
if (devfd < 0) {
|
||||
log_err(NULL, _("Device %s doesn't exist or access denied.\n"),
|
||||
device_path(device));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (fstat(devfd, &st) < 0)
|
||||
r = -EINVAL;
|
||||
else if (!S_ISBLK(st.st_mode))
|
||||
@@ -65,12 +151,14 @@ int device_open(struct device *device, int flags)
|
||||
{
|
||||
int devfd;
|
||||
|
||||
devfd = open(device_path(device), flags | O_DIRECT | O_SYNC);
|
||||
if (devfd < 0 && errno == EINVAL) {
|
||||
log_dbg("Trying to open device %s without direct-io.",
|
||||
device_path(device));
|
||||
devfd = open(device_path(device), flags | O_SYNC);
|
||||
}
|
||||
flags |= O_SYNC;
|
||||
if (device->o_direct)
|
||||
flags |= O_DIRECT;
|
||||
|
||||
devfd = open(device_path(device), flags);
|
||||
|
||||
if (devfd < 0)
|
||||
log_dbg("Cannot open device %s.", device_path(device));
|
||||
|
||||
return devfd;
|
||||
}
|
||||
@@ -90,24 +178,24 @@ int device_alloc(struct device **device, const char *path)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(dev, 0, sizeof(struct device));
|
||||
dev->path = strdup(path);
|
||||
if (!dev->path) {
|
||||
free(dev);
|
||||
return -ENOMEM;
|
||||
}
|
||||
dev->loop_fd = -1;
|
||||
|
||||
r = device_ready(path);
|
||||
r = device_ready(dev, 1);
|
||||
if (!r) {
|
||||
dev->init_done = 1;
|
||||
} else if (r == -ENOTBLK) {
|
||||
/* alloc loop later */
|
||||
} else if (r < 0) {
|
||||
free(dev->path);
|
||||
free(dev);
|
||||
return -ENOTBLK;
|
||||
}
|
||||
|
||||
dev->path = strdup(path);
|
||||
if (!dev->path) {
|
||||
free(dev);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
*device = dev;
|
||||
return 0;
|
||||
}
|
||||
@@ -208,27 +296,23 @@ out:
|
||||
|
||||
int device_block_size(struct device *device)
|
||||
{
|
||||
struct stat st;
|
||||
int fd, bsize = 0, r = -EINVAL;
|
||||
int fd, r = -EINVAL;
|
||||
|
||||
if (!device)
|
||||
return 0;
|
||||
|
||||
if (device->file_path)
|
||||
return (int)crypt_getpagesize();
|
||||
|
||||
fd = open(device->path, O_RDONLY);
|
||||
if(fd < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (fstat(fd, &st) < 0)
|
||||
goto out;
|
||||
r = device_block_size_fd(fd, NULL);
|
||||
|
||||
if (S_ISREG(st.st_mode)) {
|
||||
r = (int)crypt_getpagesize();
|
||||
goto out;
|
||||
}
|
||||
if (r <= 0)
|
||||
log_dbg("Cannot get block size for device %s.", device_path(device));
|
||||
|
||||
if (ioctl(fd, BLKSSZGET, &bsize) >= 0)
|
||||
r = bsize;
|
||||
out:
|
||||
close(fd);
|
||||
return r;
|
||||
}
|
||||
@@ -333,7 +417,7 @@ out:
|
||||
|
||||
static int device_internal_prepare(struct crypt_device *cd, struct device *device)
|
||||
{
|
||||
char *loop_device;
|
||||
char *loop_device, *file_path = NULL;
|
||||
int r, loop_fd, readonly = 0;
|
||||
|
||||
if (device->init_done)
|
||||
@@ -359,15 +443,19 @@ static int device_internal_prepare(struct crypt_device *cd, struct device *devic
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
r = device_ready(loop_device);
|
||||
file_path = device->path;
|
||||
device->path = loop_device;
|
||||
|
||||
r = device_ready(device, device->o_direct);
|
||||
if (r < 0) {
|
||||
device->path = file_path;
|
||||
crypt_loop_detach(loop_device);
|
||||
free(loop_device);
|
||||
return r;
|
||||
}
|
||||
|
||||
device->loop_fd = loop_fd;
|
||||
device->file_path = device->path;
|
||||
device->path = loop_device;
|
||||
device->file_path = file_path;
|
||||
device->init_done = 1;
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* devname - search for device name
|
||||
*
|
||||
* Copyright (C) 2004, Christophe Saout <christophe@saout.de>
|
||||
* Copyright (C) 2004, Jana Saout <jana@saout.de>
|
||||
* Copyright (C) 2004-2007, Clemens Fruhwirth <clemens@endorphin.org>
|
||||
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2009-2013, Milan Broz
|
||||
@@ -236,6 +236,24 @@ int crypt_dev_is_partition(const char *dev_path)
|
||||
return val ? 1 : 0;
|
||||
}
|
||||
|
||||
uint64_t crypt_dev_partition_offset(const char *dev_path)
|
||||
{
|
||||
uint64_t val;
|
||||
struct stat st;
|
||||
|
||||
if (!crypt_dev_is_partition(dev_path))
|
||||
return 0;
|
||||
|
||||
if (stat(dev_path, &st) < 0)
|
||||
return 0;
|
||||
|
||||
if (!_sysfs_get_uint64(major(st.st_rdev), minor(st.st_rdev),
|
||||
&val, "start"))
|
||||
return 0;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/* Try to find partition which match offset and size on top level device */
|
||||
char *crypt_get_partition_device(const char *dev_path, uint64_t offset, uint64_t size)
|
||||
{
|
||||
@@ -305,3 +323,42 @@ char *crypt_get_partition_device(const char *dev_path, uint64_t offset, uint64_t
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Try to find base device from partition */
|
||||
char *crypt_get_base_device(const char *dev_path)
|
||||
{
|
||||
char link[PATH_MAX], path[PATH_MAX], part_path[PATH_MAX], *devname;
|
||||
struct stat st;
|
||||
ssize_t len;
|
||||
|
||||
if (!crypt_dev_is_partition(dev_path))
|
||||
return NULL;
|
||||
|
||||
if (stat(dev_path, &st) < 0)
|
||||
return NULL;
|
||||
|
||||
if (snprintf(path, sizeof(path), "/sys/dev/block/%d:%d",
|
||||
major(st.st_rdev), minor(st.st_rdev)) < 0)
|
||||
return NULL;
|
||||
|
||||
len = readlink(path, link, sizeof(link) - 1);
|
||||
if (len < 0)
|
||||
return NULL;
|
||||
|
||||
/* Get top level disk name for sysfs search */
|
||||
link[len] = '\0';
|
||||
devname = strrchr(link, '/');
|
||||
if (!devname)
|
||||
return NULL;
|
||||
*devname = '\0';
|
||||
devname = strrchr(link, '/');
|
||||
if (!devname)
|
||||
return NULL;
|
||||
devname++;
|
||||
|
||||
if (dm_is_dm_kernel_name(devname))
|
||||
return NULL;
|
||||
|
||||
snprintf(part_path, sizeof(part_path), "/dev/%s", devname);
|
||||
return strdup(part_path);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
/*
|
||||
* libdevmapper - device-mapper backend for cryptsetup
|
||||
*
|
||||
* Copyright (C) 2004, Christophe Saout <christophe@saout.de>
|
||||
* Copyright (C) 2004, Jana Saout <jana@saout.de>
|
||||
* Copyright (C) 2004-2007, Clemens Fruhwirth <clemens@endorphin.org>
|
||||
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2009-2012, Milan Broz
|
||||
* Copyright (C) 2009-2015, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2009-2015, Milan Broz
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -39,6 +39,10 @@ struct device;
|
||||
#define DM_PLAIN64_SUPPORTED (1 << 3) /* plain64 IV */
|
||||
#define DM_DISCARDS_SUPPORTED (1 << 4) /* discards/TRIM option is supported */
|
||||
#define DM_VERITY_SUPPORTED (1 << 5) /* dm-verity target supported */
|
||||
#define DM_TCW_SUPPORTED (1 << 6) /* tcw (TCRYPT CBC with whitening) */
|
||||
#define DM_SAME_CPU_CRYPT_SUPPORTED (1 << 7) /* same_cpu_crypt */
|
||||
#define DM_SUBMIT_FROM_CRYPT_CPUS_SUPPORTED (1 << 8) /* submit_from_crypt_cpus */
|
||||
|
||||
uint32_t dm_flags(void);
|
||||
|
||||
#define DM_ACTIVE_DEVICE (1 << 0)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* FIPS mode utilities
|
||||
*
|
||||
* Copyright (C) 2011-2012, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2011-2015, Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -18,45 +18,29 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include "libcryptsetup.h"
|
||||
#include "nls.h"
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include "utils_fips.h"
|
||||
|
||||
#if !ENABLE_FIPS
|
||||
int crypt_fips_mode(void) { return 0; }
|
||||
void crypt_fips_libcryptsetup_check(struct crypt_device *cd) {}
|
||||
void crypt_fips_self_check(struct crypt_device *cd) {}
|
||||
#else
|
||||
#include <fipscheck.h>
|
||||
static int kernel_fips_mode(void)
|
||||
{
|
||||
int fd;
|
||||
char buf[1] = "";
|
||||
|
||||
if ((fd = open("/proc/sys/crypto/fips_enabled", O_RDONLY)) >= 0) {
|
||||
while (read(fd, buf, sizeof(buf)) < 0 && errno == EINTR);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
return (buf[0] == '1') ? 1 : 0;
|
||||
}
|
||||
|
||||
int crypt_fips_mode(void)
|
||||
{
|
||||
return FIPSCHECK_kernel_fips_mode();
|
||||
}
|
||||
|
||||
static void crypt_fips_verify(struct crypt_device *cd,
|
||||
const char *name, const char *function)
|
||||
{
|
||||
if (!crypt_fips_mode())
|
||||
return;
|
||||
|
||||
if (!FIPSCHECK_verify(name, function)) {
|
||||
crypt_log(cd, CRYPT_LOG_ERROR, _("FIPS checksum verification failed.\n"));
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
crypt_log(cd, CRYPT_LOG_VERBOSE, _("Running in FIPS mode.\n"));
|
||||
}
|
||||
|
||||
void crypt_fips_libcryptsetup_check(struct crypt_device *cd)
|
||||
{
|
||||
crypt_fips_verify(cd, LIBCRYPTSETUP_VERSION_FIPS, "crypt_init");
|
||||
}
|
||||
|
||||
void crypt_fips_self_check(struct crypt_device *cd)
|
||||
{
|
||||
crypt_fips_verify(cd, NULL, NULL);
|
||||
return kernel_fips_mode() && !access("/etc/system-fips", F_OK);
|
||||
}
|
||||
#endif /* ENABLE_FIPS */
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* FIPS mode utilities
|
||||
*
|
||||
* Copyright (C) 2011-2012, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2011-2015, Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -21,10 +21,6 @@
|
||||
#ifndef _UTILS_FIPS_H
|
||||
#define _UTILS_FIPS_H
|
||||
|
||||
struct crypt_device;
|
||||
|
||||
int crypt_fips_mode(void);
|
||||
void crypt_fips_libcryptsetup_check(struct crypt_device *cd);
|
||||
void crypt_fips_self_check(struct crypt_device *cd);
|
||||
|
||||
#endif /* _UTILS_FIPS_H */
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* loopback block device utilities
|
||||
*
|
||||
* Copyright (C) 2011-2012, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2009-2012, Milan Broz
|
||||
* Copyright (C) 2011-2015, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2009-2015, Milan Broz
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -42,6 +42,10 @@
|
||||
#define LOOP_CTL_GET_FREE 0x4C82
|
||||
#endif
|
||||
|
||||
#ifndef LOOP_SET_CAPACITY
|
||||
#define LOOP_SET_CAPACITY 0x4C07
|
||||
#endif
|
||||
|
||||
static char *crypt_loop_get_device_old(void)
|
||||
{
|
||||
char dev[20];
|
||||
@@ -157,6 +161,21 @@ int crypt_loop_detach(const char *loop)
|
||||
return r;
|
||||
}
|
||||
|
||||
int crypt_loop_resize(const char *loop)
|
||||
{
|
||||
int loop_fd = -1, r = 1;
|
||||
|
||||
loop_fd = open(loop, O_RDONLY);
|
||||
if (loop_fd < 0)
|
||||
return 1;
|
||||
|
||||
if (!ioctl(loop_fd, LOOP_SET_CAPACITY, 0))
|
||||
r = 0;
|
||||
|
||||
close(loop_fd);
|
||||
return r;
|
||||
}
|
||||
|
||||
static char *_ioctl_backing_file(const char *loop)
|
||||
{
|
||||
struct loop_info64 lo64 = {0};
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/*
|
||||
* loopback block device utilities
|
||||
*
|
||||
* Copyright (C) 2011-2012, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2011-2015, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2009-2015, Milan Broz
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -29,5 +30,6 @@ int crypt_loop_device(const char *loop);
|
||||
int crypt_loop_attach(const char *loop, const char *file, int offset,
|
||||
int autoclear, int *readonly);
|
||||
int crypt_loop_detach(const char *loop);
|
||||
int crypt_loop_resize(const char *loop);
|
||||
|
||||
#endif /* _UTILS_LOOP_H */
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
#define VERITY_SIGNATURE "verity\0\0"
|
||||
|
||||
/* http://code.google.com/p/cryptsetup/wiki/DMVerity#Verity_superblock_format */
|
||||
/* https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity#verity-superblock-format */
|
||||
struct verity_sb {
|
||||
uint8_t signature[8]; /* "verity\0\0" */
|
||||
uint32_t version; /* superblock version */
|
||||
@@ -63,11 +63,11 @@ int VERITY_read_sb(struct crypt_device *cd,
|
||||
ssize_t hdr_size = sizeof(struct verity_sb);
|
||||
int devfd = 0, sb_version;
|
||||
|
||||
log_dbg("Reading VERITY header of size %u on device %s, offset %" PRIu64 ".",
|
||||
log_dbg("Reading VERITY header of size %zu on device %s, offset %" PRIu64 ".",
|
||||
sizeof(struct verity_sb), device_path(device), sb_offset);
|
||||
|
||||
if (params->flags & CRYPT_VERITY_NO_HEADER) {
|
||||
log_err(cd, _("Verity device doesn't use on-disk header.\n"),
|
||||
log_err(cd, _("Verity device %s doesn't use on-disk header.\n"),
|
||||
device_path(device));
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -159,17 +159,17 @@ int VERITY_write_sb(struct crypt_device *cd,
|
||||
uuid_t uuid;
|
||||
int r, devfd = 0;
|
||||
|
||||
log_dbg("Updating VERITY header of size %u on device %s, offset %" PRIu64 ".",
|
||||
log_dbg("Updating VERITY header of size %zu on device %s, offset %" PRIu64 ".",
|
||||
sizeof(struct verity_sb), device_path(device), sb_offset);
|
||||
|
||||
if (!uuid_string || uuid_parse(uuid_string, uuid) == -1) {
|
||||
log_err(cd, _("Wrong VERITY UUID format provided.\n"),
|
||||
log_err(cd, _("Wrong VERITY UUID format provided on device %s.\n"),
|
||||
device_path(device));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (params->flags & CRYPT_VERITY_NO_HEADER) {
|
||||
log_err(cd, _("Verity device doesn't use on-disk header.\n"),
|
||||
log_err(cd, _("Verity device %s doesn't use on-disk header.\n"),
|
||||
device_path(device));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ struct volume_key *crypt_alloc_volume_key(unsigned keylength, const char *key)
|
||||
if (key)
|
||||
memcpy(&vk->key, key, keylength);
|
||||
else
|
||||
memset(&vk->key, 0, keylength);
|
||||
crypt_memzero(&vk->key, keylength);
|
||||
|
||||
return vk;
|
||||
}
|
||||
@@ -43,7 +43,7 @@ struct volume_key *crypt_alloc_volume_key(unsigned keylength, const char *key)
|
||||
void crypt_free_volume_key(struct volume_key *vk)
|
||||
{
|
||||
if (vk) {
|
||||
memset(vk->key, 0, vk->keylength);
|
||||
crypt_memzero(vk->key, vk->keylength);
|
||||
vk->keylength = 0;
|
||||
free(vk);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.TH CRYPTSETUP-REENCRYPT "8" "June 2012" "cryptsetup-reencrypt" "Maintenance Commands"
|
||||
.TH CRYPTSETUP-REENCRYPT "8" "January 2015" "cryptsetup-reencrypt" "Maintenance Commands"
|
||||
.SH NAME
|
||||
cryptsetup-reencrypt - tool for offline LUKS device re-encryption
|
||||
.SH SYNOPSIS
|
||||
@@ -19,8 +19,6 @@ or kernel failures during reencryption (you can lose you data in this case).
|
||||
|
||||
\fIALWAYS BE SURE YOU HAVE RELIABLE BACKUP BEFORE USING THIS TOOL.\fR
|
||||
.br
|
||||
\fITHIS TOOL IS EXPERIMENTAL.\fR
|
||||
|
||||
The reencryption can be temporarily suspended (by TERM signal or by
|
||||
using ctrl+c) but you need to retain temporary files named LUKS-<uuid>.[log|org|new].
|
||||
LUKS device is unavailable until reencryption is finished though.
|
||||
@@ -36,9 +34,15 @@ To start (or continue) re-encryption for <device> use:
|
||||
.PP
|
||||
\fIcryptsetup-reencrypt\fR <device>
|
||||
|
||||
\fB<options>\fR can be [\-\-block-size, \-\-cipher, \-\-hash, \-\-iter-time,
|
||||
\-\-use-random | \-\-use-urandom, \-\-key-file, \-\-key-slot, \-\-keyfile-offset,
|
||||
\-\-keyfile-size, \-\-tries, \-\-use-directio, \-\-use-fsync, \-\-write-log]
|
||||
\fB<options>\fR can be [\-\-batch-mode, \-\-block-size, \-\-cipher, \-\-debug,
|
||||
\-\-device-size, \-\-hash, \-\-iter-time, \-\-use-random | \-\-use-urandom,
|
||||
\-\-keep-key, \-\-key-size, \-\-key-file, \-\-key-slot, \-\-keyfile-offset,
|
||||
\-\-keyfile-size, \-\-tries, \-\-use-directio, \-\-use-fsync, \-\-verbose, \-\-write-log]
|
||||
|
||||
To encrypt data on (not yet encrypted) device, use \fI\-\-new\fR with combination
|
||||
with \fI\-\-reduce-device-size\fR.
|
||||
|
||||
To remove encryption from device, use \fI\-\-decrypt\fR.
|
||||
|
||||
For detailed description of encryption and key file options see \fIcryptsetup(8)\fR
|
||||
man page.
|
||||
@@ -56,7 +60,7 @@ Set the cipher specification string.
|
||||
.B "\-\-key-size, \-s \fI<bits>\fR"
|
||||
Set key size in bits. The argument has to be a multiple of 8.
|
||||
|
||||
The possible key-sizes are limited by the cipher and mode used.
|
||||
The possible key-sizes are limited by the cipher and mode used.
|
||||
|
||||
If you are increasing key size, there must be enough space in the LUKS header
|
||||
for enlarged keyslots (data offset must be large enough) or reencryption
|
||||
@@ -67,6 +71,9 @@ you can destructively shrink device with \-\-reduce-device-size option.
|
||||
.TP
|
||||
.B "\-\-hash, \-h \fI<hash-spec>\fR"
|
||||
Specifies the hash used in the LUKS key setup scheme and volume key digest.
|
||||
|
||||
\fBNOTE:\fR if this parameter is not specified, default hash algorithm is always used
|
||||
for new device header.
|
||||
.TP
|
||||
.B "\-\-iter-time, \-i \fI<milliseconds>\fR"
|
||||
The number of milliseconds to spend with PBKDF2 passphrase processing for the
|
||||
@@ -80,7 +87,7 @@ Define which kernel random number generator will be used to create the volume ke
|
||||
.B "\-\-key-file, \-d \fIname\fR"
|
||||
Read the passphrase from file.
|
||||
|
||||
WARNING: \-\-key-file option can be used only if there only one active keyslot,
|
||||
\fBWARNING:\fR \-\-key-file option can be used only if there only one active keyslot,
|
||||
or alternatively, also if \-\-key-slot option is specified (then all other keyslots
|
||||
will be disabled in new LUKS device).
|
||||
|
||||
@@ -90,7 +97,7 @@ passphrases.
|
||||
.B "\-\-key-slot, \-S <0-7>"
|
||||
Specify which key slot is used.
|
||||
|
||||
WARNING: All other keyslots will be disabled if this option is used.
|
||||
\fBWARNING:\fR All other keyslots will be disabled if this option is used.
|
||||
.TP
|
||||
.B "\-\-keyfile-offset \fIvalue\fR"
|
||||
Skip \fIvalue\fR bytes at the beginning of the key file.
|
||||
@@ -100,6 +107,12 @@ Read a maximum of \fIvalue\fR bytes from the key file.
|
||||
Default is to read the whole file up to the compiled-in
|
||||
maximum.
|
||||
.TP
|
||||
.B "\-\-keep-key"
|
||||
Do not change encryption key, just reencrypt the LUKS header and keyslots.
|
||||
|
||||
This option can be combined only with \fI\-\-hash\fR or \fI\-\-iter-time\fR
|
||||
options.
|
||||
.TP
|
||||
.B "\-\-tries, \-T"
|
||||
Number of retries for invalid passphrase entry.
|
||||
.TP
|
||||
@@ -114,14 +127,14 @@ Instead of real device size, use specified value.
|
||||
It means that only specified area (from the start of the device
|
||||
to the specified size) will be reencrypted.
|
||||
|
||||
WARNING: This is destructive operation.
|
||||
\fBWARNING:\fR This is destructive operation.
|
||||
|
||||
If no unit suffix is specified, the size is in bytes.
|
||||
|
||||
Unit suffix can be S for 512 byte sectors, K/M/G/T (or KiB,MiB,GiB,TiB)
|
||||
for units with 1024 base or KB/MB/GB/TB for 1000 base (SI scale).
|
||||
|
||||
WARNING: This is destructive operation.
|
||||
\fBWARNING:\fR This is destructive operation.
|
||||
.TP
|
||||
.B "\-\-reduce-device-size \fIsize[units]\fR"
|
||||
Enlarge data offset to specified value by shrinking device size.
|
||||
@@ -130,12 +143,12 @@ This means that last sectors on the original device will be lost,
|
||||
ciphertext data will be effectively shifted by specified
|
||||
number of sectors.
|
||||
|
||||
It can be usefull if you e.g. added some space to underlying
|
||||
It can be useful if you e.g. added some space to underlying
|
||||
partition (so last sectors contains no data).
|
||||
|
||||
For units suffix see \-\-device-size parameter description.
|
||||
|
||||
WARNING: This is destructive operation and cannot be reverted.
|
||||
\fBWARNING:\fR This is destructive operation and cannot be reverted.
|
||||
Use with extreme care - shrinked filesystems are usually unrecoverable.
|
||||
|
||||
You cannot shrink device more than by 64 MiB (131072 sectors).
|
||||
@@ -145,17 +158,23 @@ Create new header (encrypt not yet encrypted device).
|
||||
|
||||
This option must be used together with \-\-reduce-device-size.
|
||||
|
||||
WARNING: This is destructive operation and cannot be reverted.
|
||||
\fBWARNING:\fR This is destructive operation and cannot be reverted.
|
||||
.TP
|
||||
.B "\-\-decrypt"
|
||||
Remove encryption (decrypt already encrypted device and remove LUKS header).
|
||||
|
||||
\fBWARNING:\fR This is destructive operation and cannot be reverted.
|
||||
.TP
|
||||
.B "\-\-use-directio"
|
||||
Use direct-io (O_DIRECT) for all read/write data operations.
|
||||
Use direct-io (O_DIRECT) for all read/write data operations related
|
||||
to block device undergoing reencryption.
|
||||
|
||||
Usefull if direct-io operations perform better than normal buffered
|
||||
Useful if direct-io operations perform better than normal buffered
|
||||
operations (e.g. in virtual environments).
|
||||
.TP
|
||||
.B "\-\-use-fsync"
|
||||
Use fsync call after every written block.
|
||||
Use fsync call after every written block. This applies for reencryption
|
||||
log files as well.
|
||||
.TP
|
||||
.B "\-\-write-log"
|
||||
Update log file after every block write. This can slow down reencryption
|
||||
@@ -178,18 +197,24 @@ Reencrypt /dev/sdb1 (change volume key)
|
||||
cryptsetup-reencrypt /dev/sdb1
|
||||
.TP
|
||||
Reencrypt and also change cipher and cipher mode
|
||||
cryptsetup-reencrypt /dev/sdb1 -c aes-xts-plain64
|
||||
cryptsetup-reencrypt /dev/sdb1 \-c aes-xts-plain64
|
||||
.TP
|
||||
Add LUKS encryption to not yet encrypted device
|
||||
|
||||
First, be sure you have space added to disk.
|
||||
|
||||
Or alternatively shrink filesystem in advance.
|
||||
.br
|
||||
Here we need 4096 512-bytes sectors (enough for 2x128 bit key).
|
||||
|
||||
fdisk -u /dev/sdb # move sdb1 partition end + 4096 sectors
|
||||
fdisk \-u /dev/sdb # move sdb1 partition end + 4096 sectors
|
||||
(or use resize2fs or tool for your filesystem and shrink it)
|
||||
|
||||
cryptsetup-reencrypt /dev/sdb1 --new --reduce-device-size 4096
|
||||
cryptsetup-reencrypt /dev/sdb1 \-\-new \-\-reduce-device-size 4096S
|
||||
.TP
|
||||
Remove LUKS encryption completely
|
||||
|
||||
cryptsetup-reencrypt /dev/sdb1 \-\-decrypt
|
||||
|
||||
.SH REPORTING BUGS
|
||||
Report bugs, including ones in the documentation, on
|
||||
@@ -200,11 +225,11 @@ Please attach the output of the failed command with the
|
||||
.SH AUTHORS
|
||||
Cryptsetup-reencrypt was written by Milan Broz <gmazyland@gmail.com>.
|
||||
.SH COPYRIGHT
|
||||
Copyright \(co 2012 Milan Broz
|
||||
Copyright \(co 2012-2015 Milan Broz
|
||||
.br
|
||||
Copyright \(co 2012 Red Hat, Inc.
|
||||
Copyright \(co 2012-2013 Red Hat, Inc.
|
||||
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
.SH SEE ALSO
|
||||
The project website at \fBhttp://code.google.com/p/cryptsetup/\fR
|
||||
The project website at \fBhttps://gitlab.com/cryptsetup/cryptsetup\fR
|
||||
|
||||
229
man/cryptsetup.8
229
man/cryptsetup.8
@@ -1,4 +1,4 @@
|
||||
.TH CRYPTSETUP "8" "May 2012" "cryptsetup" "Maintenance Commands"
|
||||
.TH CRYPTSETUP "8" "December 2013" "cryptsetup" "Maintenance Commands"
|
||||
.SH NAME
|
||||
cryptsetup - manage plain dm-crypt and LUKS encrypted volumes
|
||||
.SH SYNOPSIS
|
||||
@@ -12,7 +12,7 @@ and can hence offer more features than plain dm-crypt. On the other
|
||||
hand, the header is visible and vulnerable to damage.
|
||||
|
||||
In addition, cryptsetup provides limited support for the use of
|
||||
historic loopaes volumes and for TruerCrypt compatible volumes.
|
||||
historic loopaes volumes and for TrueCrypt compatible volumes.
|
||||
|
||||
.SH PLAIN DM-CRYPT OR LUKS?
|
||||
.PP
|
||||
@@ -55,11 +55,11 @@ secure wiping by just overwriting header and key-slot area.
|
||||
|
||||
\fBPreviously used partitions:\fR If a partition was previously used,
|
||||
it is a very good idea to wipe filesystem signatures, data, etc. before
|
||||
creating a LUKS or plain dm-crypt container on it.
|
||||
For a quick removal of filesystem signatures, use "wipefs". Take care
|
||||
though that this may not remove everything. In particular md (RAID)
|
||||
signatures at the end of a device may survive. It also does not
|
||||
remove data. For a full wipe, overwrite the whole partition before
|
||||
creating a LUKS or plain dm-crypt container on it.
|
||||
For a quick removal of filesystem signatures, use "wipefs". Take care
|
||||
though that this may not remove everything. In particular md (RAID)
|
||||
signatures at the end of a device may survive. It also does not
|
||||
remove data. For a full wipe, overwrite the whole partition before
|
||||
container creation. If you do not know how to to that, the
|
||||
cryptsetup FAQ describes several options.
|
||||
|
||||
@@ -75,9 +75,9 @@ or \fItcrypt\fR.
|
||||
|
||||
For backward compatibility there are \fBopen\fR command aliases:
|
||||
|
||||
\fBcreate\fR (argument-order <name> <device>): open \-\-type plain
|
||||
\fBcreate\fR (argument-order <name> <device>): open \-\-type plain
|
||||
.br
|
||||
\fBplainOpen\fR: open \-\-type plain
|
||||
\fBplainOpen\fR: open \-\-type plain
|
||||
.br
|
||||
\fBluksOpen\fR: open \-\-type luks
|
||||
.br
|
||||
@@ -86,7 +86,7 @@ For backward compatibility there are \fBopen\fR command aliases:
|
||||
\fBtcryptOpen\fR: open \-\-type tcrypt
|
||||
|
||||
\fB<options>\fR are type specific and are described below
|
||||
for individual device types. For \fBcreate\fR, the order of the <name>
|
||||
for individual device types. For \fBcreate\fR, the order of the <name>
|
||||
and <device> options is inverted for historical reasons, all other
|
||||
aliases use the standard \fB<device> <name>\fR order.
|
||||
.PP
|
||||
@@ -131,7 +131,7 @@ Opens (creates a mapping with) <name> backed by device <device>.
|
||||
\-\-key-file, \-\-keyfile-offset, \-\-key-size, \-\-offset, \-\-skip, \-\-size,
|
||||
\-\-readonly, \-\-shared, \-\-allow-discards]
|
||||
|
||||
Example: 'cryptsetup open --type plain /dev/sda10 e1' maps the raw
|
||||
Example: 'cryptsetup open \-\-type plain /dev/sda10 e1' maps the raw
|
||||
encrypted device /dev/sda10 to the mapped (decrypted) device
|
||||
/dev/mapper/e1, which can then be mounted, fsck-ed or have a
|
||||
filesystem created on it.
|
||||
@@ -160,12 +160,20 @@ Key operations that do not specify a slot affect the first slot
|
||||
that matches the supplied passphrase or the first empty slot if
|
||||
a new passphrase is added.
|
||||
|
||||
The \fB<device>\fR parameter can be also specified by a LUKS UUID in the
|
||||
format UUID=<uuid>. Translation to real device name uses symlinks
|
||||
in /dev/disk/by-uuid directory.
|
||||
|
||||
To specify a detached header, the \fB\-\-header\fR parameter can be used
|
||||
in all LUKS commands and always takes precedence over positional \fB<device>\fR
|
||||
parameter.
|
||||
|
||||
The following are valid LUKS actions:
|
||||
|
||||
\fIluksFormat\fR <device> [<key file>]
|
||||
.IP
|
||||
Initializes a LUKS partition and sets the initial passphrase
|
||||
(for key-slot 0),
|
||||
(for key-slot 0),
|
||||
either via prompting or via <key file>. Note that
|
||||
if the second argument is present, then the passphrase
|
||||
is taken from the file given there, without the need
|
||||
@@ -176,8 +184,8 @@ from stdin and the safety-question being skipped.
|
||||
|
||||
You can only call luksFormat on a LUKS device that is not mapped.
|
||||
|
||||
\fB<options>\fR can be [\-\-hash, \-\-cipher, \-\-verify\-passphrase,
|
||||
\-\-key\-size, \-\-key\-slot,
|
||||
\fB<options>\fR can be [\-\-hash, \-\-cipher, \-\-verify\-passphrase,
|
||||
\-\-key\-size, \-\-key\-slot,
|
||||
\-\-key\-file (takes precedence over optional second argument),
|
||||
\-\-keyfile\-offset, \-\-keyfile\-size, \-\-use\-random | \-\-use\-urandom,
|
||||
\-\-uuid, \-\-master\-key\-file, \-\-iter\-time, \-\-header,
|
||||
@@ -196,9 +204,6 @@ successful verification of the supplied passphrase.
|
||||
If the passphrase is not supplied via \-\-key-file, the command
|
||||
prompts for it interactively.
|
||||
|
||||
The <device> parameter can be also specified by LUKS UUID in the
|
||||
format UUID=<uuid>, which uses the symlinks in /dev/disk/by-uuid.
|
||||
|
||||
\fB<options>\fR can be [\-\-key\-file, \-\-keyfile\-offset,
|
||||
\-\-keyfile\-size, \-\-readonly, \-\-test\-passphrase,
|
||||
\-\-allow\-discards, \-\-header, \-\-key-slot, \-\-master\-key\-file].
|
||||
@@ -235,7 +240,7 @@ or read from the file given as positional argument.
|
||||
\fB<options>\fR can be [\-\-key\-file, \-\-keyfile\-offset,
|
||||
\-\-keyfile\-size, \-\-new\-keyfile\-offset,
|
||||
\-\-new\-keyfile\-size, \-\-key\-slot, \-\-master\-key\-file,
|
||||
\-\-iter\-time, \-\-force\-password].
|
||||
\-\-iter\-time, \-\-force\-password, \-\-header].
|
||||
.PP
|
||||
\fIluksRemoveKey\fR <device> [<key file with passphrase to be removed>]
|
||||
.IP
|
||||
@@ -244,11 +249,11 @@ passphrase to be removed can be specified interactively,
|
||||
as positional argument or via \-\-key-file.
|
||||
|
||||
\fB<options>\fR can be [\-\-key\-file, \-\-keyfile\-offset,
|
||||
\-\-keyfile\-size]
|
||||
\-\-keyfile\-size, \-\-header]
|
||||
|
||||
\fBWARNING:\fR If you read the passphrase from stdin
|
||||
(without further argument or with '-' as argument
|
||||
to \-\-key\-file), batch-mode (-q) will be implicitely
|
||||
(without further argument or with '-' as argument
|
||||
to \-\-key\-file), batch-mode (\-q) will be implicitely
|
||||
switched on and no warning will be given when you remove the
|
||||
last remaining passphrase from a LUKS container. Removing
|
||||
the last passphrase makes the LUKS container permanently
|
||||
@@ -277,7 +282,7 @@ inaccessible.
|
||||
|
||||
\fB<options>\fR can be [\-\-key\-file, \-\-keyfile\-offset,
|
||||
\-\-keyfile\-size, \-\-new\-keyfile\-offset,
|
||||
\-\-new\-keyfile\-size, \-\-key\-slot, \-\-force\-password].
|
||||
\-\-new\-keyfile\-size, \-\-key\-slot, \-\-force\-password, \-\-header].
|
||||
.PP
|
||||
\fIluksKillSlot\fR <device> <key slot number>
|
||||
.IP
|
||||
@@ -287,17 +292,26 @@ This command can remove the last remaining key-slot, but requires
|
||||
an interactive confirmation when doing so. Removing the last
|
||||
passphrase makes a LUKS container permanently inaccessible.
|
||||
|
||||
\fB<options>\fR can be [\-\-key\-file, \-\-keyfile\-offset,
|
||||
\-\-keyfile\-size].
|
||||
\fB<options>\fR can be [\-\-key\-file, \-\-keyfile\-offset,
|
||||
\-\-keyfile\-size, \-\-header].
|
||||
|
||||
\fBWARNING:\fR If you read the passphrase from stdin
|
||||
(without further argument or with '-' as argument
|
||||
to \-\-key-file), batch-mode (-q) will be implicitely
|
||||
to \-\-key-file), batch-mode (\-q) will be implicitely
|
||||
switched on and no warning will be given when you remove the
|
||||
last remaining passphrase from a LUKS container. Removing
|
||||
the last passphrase makes the LUKS container permanently
|
||||
inaccessible.
|
||||
.PP
|
||||
\fIerase\fR <device>
|
||||
.br
|
||||
\fIluksErase\fR <device>
|
||||
.IP
|
||||
Erase all keyslots and make the LUKS container permanently inaccessible.
|
||||
You do not need to provide any password for this operation.
|
||||
|
||||
\fBWARNING:\fR This operation is irreversible.
|
||||
.PP
|
||||
\fIluksUUID\fR <device>
|
||||
.IP
|
||||
Print the UUID of a LUKS device.
|
||||
@@ -322,10 +336,10 @@ that if the master key is compromised, the whole device has to be
|
||||
erased to prevent further access. Use this option carefully.
|
||||
|
||||
In order to dump the master key, a passphrase has to be supplied,
|
||||
either interactively or via \-\-key\-file.
|
||||
either interactively or via \-\-key\-file.
|
||||
|
||||
\fB<options>\fR can be [\-\-dump\-master\-key, \-\-key\-file,
|
||||
\-\-keyfile\-offset, \-\-keyfile\-size].
|
||||
\-\-keyfile\-offset, \-\-keyfile\-size, \-\-header].
|
||||
|
||||
\fBWARNING:\fR If \-\-dump\-master\-key is used with \-\-key\-file
|
||||
and the argument to \-\-key\-file is '-', no validation question
|
||||
@@ -375,9 +389,17 @@ Opens the loop-AES <device> and sets up a mapping <name>.
|
||||
If the key file is encrypted with GnuPG, then you have to use
|
||||
\-\-key\-file=\- and decrypt it before use, e.g. like this:
|
||||
.br
|
||||
gpg \-\-decrypt <keyfile> | cryptsetup loopaesOpen \-\-key\-file=\-
|
||||
gpg \-\-decrypt <keyfile> | cryptsetup loopaesOpen \-\-key\-file=\-
|
||||
<device> <name>
|
||||
|
||||
\fBWARNING:\fR The loop-AES extension cannot use direct input of key file
|
||||
on real terminal because the keys are separated by end-of-line and only part
|
||||
of the multi-key file would be read.
|
||||
.br
|
||||
If you need it in script, just use the pipe redirection:
|
||||
.br
|
||||
echo $keyfile | cryptsetup loopaesOpen \-\-key\-file=\- <device> <name>
|
||||
|
||||
Use \fB\-\-keyfile\-size\fR to specify the proper key length if needed.
|
||||
|
||||
Use \fB\-\-offset\fR to specify device offset. Note that the units
|
||||
@@ -397,8 +419,9 @@ size).
|
||||
.PP
|
||||
See also section 7 of the FAQ and \fBhttp://loop-aes.sourceforge.net\fR
|
||||
for more information regarding loop-AES.
|
||||
.SH TCRYPT (TrueCrypt-compatible) EXTENSION
|
||||
cryptsetup supports mapping of TrueCrypt or tcplay encrypted partition
|
||||
.SH TCRYPT (TrueCrypt-compatible and VeraCrypt) EXTENSION
|
||||
cryptsetup supports mapping of TrueCrypt, tcplay or VeraCrypt
|
||||
(with \fB\-\-veracrypt\fR option) encrypted partition
|
||||
using a native Linux kernel API.
|
||||
Header formatting and TCRYPT header change is not supported, cryptsetup
|
||||
never changes TCRYPT header on-device.
|
||||
@@ -416,6 +439,11 @@ Cryptsetup should recognize all header variants, except legacy cipher chains
|
||||
using LRW encryption mode with 64 bits encryption block (namely Blowfish
|
||||
in LRW mode is not recognized, this is limitation of kernel crypto API).
|
||||
|
||||
To recognize VeraCrypt device use \fB\-\-veracrypt\fR option.
|
||||
VeraCrypt is just extension of TrueCrypt header with increased
|
||||
iteration count so unlocking can take quite a lot of time (in comparison
|
||||
with TCRYPT device).
|
||||
|
||||
\fBNOTE:\fR Activation with \fBtcryptOpen\fR is supported only for cipher chains
|
||||
using LRW or XTS encryption modes.
|
||||
|
||||
@@ -423,12 +451,26 @@ The \fBtcryptDump\fR command should work for all recognized TCRYPT devices
|
||||
and doesn't require superuser privilege.
|
||||
|
||||
To map system device (device with boot loader where the whole encrypted
|
||||
system resides) use \fB\-\-tcrypt\-system\fR option. Use the whole
|
||||
device not the system partition as the device parameter.
|
||||
system resides) use \fB\-\-tcrypt\-system\fR option.
|
||||
You can use partition device as the parameter (parameter must be real partition
|
||||
device, not image in file), then only this partition is mapped.
|
||||
|
||||
If you have whole TCRYPT device as a file image and you want to map multiple
|
||||
partition encrypted with system encryption, please create loopback mapping
|
||||
with partitions first (\fBlosetup \-P\fR, see \fPlosetup(8)\fR man page for more info),
|
||||
and use loop partition as the device parameter.
|
||||
|
||||
If you use whole base device as parameter, one device for the whole system
|
||||
encryption is mapped. This mode is available only for backward compatibility
|
||||
with older cryptsetup versions which mapped TCRYPT system encryption
|
||||
using whole device.
|
||||
|
||||
To use hidden header (and map hidden device, if available),
|
||||
use \fB\-\-tcrypt\-hidden\fR option.
|
||||
|
||||
To explicitly use backup (secondary) header, use \fB\-\-tcrypt\-backup\fR
|
||||
option.
|
||||
|
||||
\fBNOTE:\fR There is no protection for a hidden volume if
|
||||
the outer volume is mounted. The reason is that if there
|
||||
were any protection, it would require some metadata describing
|
||||
@@ -440,21 +482,28 @@ become detectable.
|
||||
.br
|
||||
\fItcryptOpen\fR <device> <name> (\fBold syntax\fR)
|
||||
.IP
|
||||
Opens the TCRYPT (a TrueCrypt-compatible) <device> and sets up
|
||||
Opens the TCRYPT (a TrueCrypt-compatible) <device> and sets up
|
||||
a mapping <name>.
|
||||
|
||||
\fB<options>\fR can be [\-\-key\-file, \-\-tcrypt\-hidden,
|
||||
\-\-tcrypt\-system, \-\-readonly, \-\-test\-passphrase].
|
||||
\fB<options>\fR can be [\-\-key\-file, \-\-tcrypt\-hidden,
|
||||
\-\-tcrypt\-system, \-\-tcrypt\-backup, \-\-readonly, \-\-test\-passphrase,
|
||||
\-\-allow-discards].
|
||||
|
||||
The keyfile parameter allows combination of file content with the
|
||||
passphrase and can be repeated. Note that using keyfiles is compatible
|
||||
with TCRYPT and is different from LUKS keyfile logic.
|
||||
|
||||
\fBWARNING:\fR Option \fB\-\-allow\-discards\fR cannot be combined with
|
||||
option \fB\-\-tcrypt\-hidden\fR. For normal mapping it can cause
|
||||
\fBdestruction of hidden volume\fR (hidden volume appears as unused space
|
||||
for outer volume so this space can be discarded).
|
||||
|
||||
.PP
|
||||
\fItcryptDump\fR <device>
|
||||
.IP
|
||||
Dump the header information of a TCRYPT device.
|
||||
|
||||
If the \-\-dump\-master\-key option is used, the TCRYPT device master key
|
||||
If the \-\-dump\-master\-key option is used, the TCRYPT device master key
|
||||
is dumped instead of TCRYPT header info. Beware that the master key
|
||||
(or concatenated master keys if cipher chain is used)
|
||||
can be used to decrypt the data stored in the TCRYPT container without
|
||||
@@ -462,8 +511,8 @@ a passphrase.
|
||||
This means that if the master key is compromised, the whole device has
|
||||
to be erased to prevent further access. Use this option carefully.
|
||||
|
||||
\fB<options>\fR can be [\-\-dump\-master\-key, \-\-key\-file,
|
||||
\-\-tcrypt\-hidden, \-\-tcrypt\-system].
|
||||
\fB<options>\fR can be [\-\-dump\-master\-key, \-\-key\-file,
|
||||
\-\-tcrypt\-hidden, \-\-tcrypt\-system, \-\-tcrypt\-backup].
|
||||
|
||||
The keyfile parameter allows combination of file content with the
|
||||
passphrase and can be repeated.
|
||||
@@ -516,14 +565,16 @@ Run in debug mode with full diagnostic logs. Debug output
|
||||
lines are always prefixed by '#'.
|
||||
.TP
|
||||
.B "\-\-hash, \-h \fI<hash\-spec>\fR"
|
||||
Specifies the passphrase hash for \fIopen\fR (for plain and loopaes device types).
|
||||
Specifies the passphrase hash for \fIopen\fR (for plain and
|
||||
loopaes device types).
|
||||
|
||||
Specifies the hash used in the LUKS key setup scheme and volume key digest
|
||||
for \fIluksFormat\fR.
|
||||
for \fIluksFormat\fR. The specified hash is used as hash-parameter
|
||||
for PBKDF2 and for the AF splitter.
|
||||
|
||||
The specified hash name is passed to the compiled-in crypto backend.
|
||||
Different backends may support different hashes.
|
||||
For \fIluksFormat\fR, the hash
|
||||
For \fIluksFormat\fR, the hash
|
||||
algorithm must provide at least 160 bits of output, which
|
||||
excludes, e.g., MD5. Do not use a non-crypto hash like
|
||||
\fB"crc32"\fR as this breaks security.
|
||||
@@ -542,6 +593,11 @@ The current default in the distributed sources is
|
||||
"aes-cbc-essiv:sha256" for plain dm-crypt and
|
||||
"aes-xts-plain64" for LUKS.
|
||||
|
||||
If a hash is part of the cipher spefification, then it is
|
||||
used as part of the IV generation. For example, ESSIV
|
||||
needs a hash function, while "plain64" does not and
|
||||
hence none is specified.
|
||||
|
||||
For XTS mode you can optionally set a key size of
|
||||
512 bits with the \-s option. Key size for XTS
|
||||
mode is twice that for other modes for the same
|
||||
@@ -613,14 +669,14 @@ then the new header decrypts the data encrypted with the
|
||||
header the master key was taken from.
|
||||
|
||||
\fBWARNING:\fR If you create your own master key, you
|
||||
need to make sure to do it right. Otherwise you can end
|
||||
need to make sure to do it right. Otherwise you can end
|
||||
up with a low-entropy or otherwise partially predictable
|
||||
master key which will compromise security.
|
||||
|
||||
For \fIluksAddKey\fR this allows adding a new passphrase
|
||||
without having to know an exiting one.
|
||||
|
||||
For \fIopen\fR this allows to open the LUKS device
|
||||
For \fIopen\fR this allows one to open the LUKS device
|
||||
without giving a passphrase.
|
||||
.TP
|
||||
.B "\-\-dump\-master\-key"
|
||||
@@ -680,17 +736,14 @@ This option is only relevant for the \fIopen\fR action with plain
|
||||
or loopaes device types.
|
||||
.TP
|
||||
.B "\-\-skip, \-p <number of 512 byte sectors>"
|
||||
How many sectors of the encrypted data to skip at the beginning.
|
||||
Start offset used in IV calculation in 512-byte sectors
|
||||
(how many sectors of the encrypted data to skip at the beginning).
|
||||
This option is only relevant for the \fIopen\fR action with plain
|
||||
or loopaes device types.
|
||||
|
||||
This is different from the \-\-offset options with respect to
|
||||
the sector numbers used in IV calculation.
|
||||
Using \-\-offset will shift the IV calculation by the same negative amount.
|
||||
Hence, if \-\-offset \fIn\fR, sector \fIn\fR will get a sector
|
||||
number of \fI0\fR for the IV calculation.
|
||||
Using \-\-skip causes sector \fIn\fR to also be the first sector
|
||||
of the mapped device, but with its number for IV generation is \fIn\fR.
|
||||
Hence, if \-\-offset \fIn\fR, and \-\-skip \fIs\fR, sector \fIn\fR
|
||||
(the first sector of encrypted device) will get a sector number
|
||||
of \fIs\fR for the IV calculation.
|
||||
.TP
|
||||
.B "\-\-readonly, \-r"
|
||||
set up a read-only mapping.
|
||||
@@ -698,7 +751,7 @@ set up a read-only mapping.
|
||||
.B "\-\-shared"
|
||||
Creates an additional mapping for one common
|
||||
ciphertext device. Arbitrary mappings are supported.
|
||||
This option is only relevant for the
|
||||
This option is only relevant for the
|
||||
\fIopen \-\-type plain\fR action. Use \-\-offset, \-\-size and \-\-skip to
|
||||
specify the mapped area.
|
||||
.TP
|
||||
@@ -720,7 +773,7 @@ via terminal. It is relevant every time a passphrase is asked,
|
||||
for example for \fIopen\fR, \fIluksFormat\fR or \fIluksAddKey\fR.
|
||||
It has no effect if used in conjunction with \-\-key-file.
|
||||
.br
|
||||
This option is useful when the system
|
||||
This option is useful when the system
|
||||
should not stall if the user does not input a passphrase,
|
||||
e.g. during boot. The default is a value of 0 seconds,
|
||||
which means to wait forever.
|
||||
@@ -761,11 +814,33 @@ because it can make filesystem-level operations visible on
|
||||
the physical device. For example, information leaking
|
||||
filesystem type, used space, etc. may be extractable from
|
||||
the physical device if the discarded blocks can be located
|
||||
later. If in doubt, do no use it.
|
||||
later. If in doubt, do not use it.
|
||||
|
||||
A kernel version of 3.1 or later is needed. For earlier kernels
|
||||
this option is ignored.
|
||||
.TP
|
||||
.B "\-\-perf\-same_cpu_crypt\fR"
|
||||
Perform encryption using the same cpu that IO was submitted on.
|
||||
The default is to use an unbound workqueue so that encryption work
|
||||
is automatically balanced between available CPUs.
|
||||
This option is only relevant for \fIopen\fR action.
|
||||
|
||||
\fBNOTE:\fR This option is available only for low-level dm-crypt
|
||||
performance tuning, use only if you need a change to default dm-crypt
|
||||
behaviour. Needs kernel 4.0 or later.
|
||||
.TP
|
||||
.B "\-\-perf\-submit_from_crypt_cpus\fR"
|
||||
Disable offloading writes to a separate thread after encryption.
|
||||
There are some situations where offloading write bios from the
|
||||
encryption threads to a single thread degrades performance
|
||||
significantly. The default is to offload write bios to the same
|
||||
thread.
|
||||
This option is only relevant for \fIopen\fR action.
|
||||
|
||||
\fBNOTE:\fR This option is available only for low-level dm-crypt
|
||||
performance tuning, use only if you need a change to default dm-crypt
|
||||
behaviour. Needs kernel 4.0 or later.
|
||||
.TP
|
||||
.B "\-\-test\-passphrase\fR"
|
||||
Do not activate device, just verify passphrase.
|
||||
This option is only relevant for \fIopen\fR action (the device
|
||||
@@ -773,10 +848,10 @@ mapping name is not mandatory if this option is used).
|
||||
.TP
|
||||
.B "\-\-header\fR <device or file storing the LUKS header>"
|
||||
Use a detached (separated) metadata device or file where the
|
||||
LUKS header is stored. This options allows to store ciphertext
|
||||
LUKS header is stored. This options allows one to store ciphertext
|
||||
and LUKS header on different devices.
|
||||
|
||||
This option is only relevant for LUKS devices and can be
|
||||
This option is only relevant for LUKS devices and can be
|
||||
used with the \fIluksFormat\fR, \fIopen\fR, \fIluksSuspend\fR,
|
||||
\fIluksResume\fR, \fIstatus\fR and \fIresize\fR commands.
|
||||
|
||||
@@ -804,7 +879,7 @@ This option applies only to \fIluksFormat\fR, \fIluksAddKey\fR and
|
||||
password quality checking support.
|
||||
|
||||
For more info about password quality check, see manual page
|
||||
for \fBpwquality.conf(5)\fR.
|
||||
for \fBpwquality.conf(5)\fR and \fBpasswdqc.conf(5)\fR.
|
||||
.TP
|
||||
.B "\-\-version"
|
||||
Show the program version.
|
||||
@@ -829,18 +904,18 @@ low-entropy passphrases are easy to attack in plain mode.
|
||||
first newline, i.e. '\\n'.
|
||||
The input without the newline character is processed with
|
||||
the default hash or the hash specified with \-\-hash.
|
||||
The hash result will be truncated to the key size
|
||||
The hash result will be truncated to the key size
|
||||
of the used cipher, or the size specified with \-s.
|
||||
|
||||
\fBFrom stdin\fR: Reading will continue until a newline (or until
|
||||
the maximum input size is reached), with the trailing newline
|
||||
stripped. The maximum input size is defined by the same
|
||||
compiled-in default as for the maximum key file size and can
|
||||
compiled-in default as for the maximum key file size and can
|
||||
be overwritten using \-\-keyfile-size option.
|
||||
|
||||
The data read will be hashed with the default hash
|
||||
or the hash specified with \-\-hash.
|
||||
The has result will be truncated to the key size
|
||||
The hash result will be truncated to the key size
|
||||
of the used cipher, or the size specified with \-s.
|
||||
|
||||
Note that if \-\-key-file=- is used for reading the key
|
||||
@@ -854,11 +929,19 @@ directly specifying a binary key.
|
||||
No warning will be given if the amount of data read from stdin is
|
||||
less than the key size.
|
||||
|
||||
\fBFrom a key file\fR: It will be truncated to the
|
||||
\fBFrom a key file\fR: It will be truncated to the
|
||||
key size of the used cipher or the size given by \-s
|
||||
and directly used as binary key.
|
||||
if the key file is shorter than the key, cryptsetup
|
||||
|
||||
\fBWARNING\fR: The \-\-hash argument is being ignored.
|
||||
The \-\-hash option is usable only for stdin input in plain mode.
|
||||
|
||||
If the key file is shorter than the key, cryptsetup
|
||||
will quit with an error.
|
||||
The maximum input size is defined by the same
|
||||
compiled-in default as for the maximum key file size and can
|
||||
be overwritten using \-\-keyfile-size option.
|
||||
|
||||
|
||||
.SH NOTES ON PASSPHRASE PROCESSING FOR LUKS
|
||||
LUKS uses PBKDF2 to protect against dictionary attacks
|
||||
@@ -896,8 +979,8 @@ passphrase used on a device with a slow CPU, as this will
|
||||
result in a low iteration count. On a slow device it may
|
||||
be advisable to increase the iteration time using the
|
||||
\-\-iter\-time option in order to obtain a higher
|
||||
iteration count. This does slow down all later luksOpen
|
||||
operations accordingly.
|
||||
iteration count. This does slow down all later luksOpen
|
||||
operations accordingly.
|
||||
.SH INCOHERENT BEHAVIOR FOR INVALID PASSPHRASES/KEYS
|
||||
LUKS checks for a valid passphrase when an encrypted partition
|
||||
is unlocked. The behavior of plain dm-crypt is different.
|
||||
@@ -938,7 +1021,7 @@ options. Using /dev/random on a system without enough entropy sources
|
||||
can cause \fPluksFormat\fR to block until the requested amount of
|
||||
random data is gathered. In a low-entropy situation (embedded system),
|
||||
this can take a very long time and potentially forever. At the same
|
||||
time, using /dev/urandom in a low-entropy situation will
|
||||
time, using /dev/urandom in a low-entropy situation will
|
||||
produce low-quality keys. This is a serious problem, but solving
|
||||
it is out of scope for a mere man-page.
|
||||
See \fPurandom(4)\fR for more information.
|
||||
@@ -969,7 +1052,7 @@ or in the 'Issues' section on LUKS website.
|
||||
Please attach the output of the failed command with the
|
||||
\-\-debug option added.
|
||||
.SH AUTHORS
|
||||
cryptsetup originally written by Christophe Saout <christophe@saout.de>
|
||||
cryptsetup originally written by Jana Saout <jana@saout.de>
|
||||
.br
|
||||
The LUKS extensions and original man page were written by
|
||||
Clemens Fruhwirth <clemens@endorphin.org>.
|
||||
@@ -978,26 +1061,26 @@ Man page extensions by Milan Broz <gmazyland@gmail.com>.
|
||||
.br
|
||||
Man page rewrite and extension by Arno Wagner <arno@wagner.name>.
|
||||
.SH COPYRIGHT
|
||||
Copyright \(co 2004 Christophe Saout
|
||||
Copyright \(co 2004 Jana Saout
|
||||
.br
|
||||
Copyright \(co 2004-2006 Clemens Fruhwirth
|
||||
.br
|
||||
Copyright \(co 2009-2012 Red Hat, Inc.
|
||||
Copyright \(co 2009-2015 Red Hat, Inc.
|
||||
.br
|
||||
Copyright \(co 2009-2013 Milan Broz
|
||||
Copyright \(co 2009-2015 Milan Broz
|
||||
.br
|
||||
Copyright \(co 2012-2013 Arno Wagner
|
||||
Copyright \(co 2012-2014 Arno Wagner
|
||||
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
.SH SEE ALSO
|
||||
The LUKS website at \fBhttp://code.google.com/p/cryptsetup/\fR
|
||||
The LUKS website at \fBhttps://gitlab.com/cryptsetup/cryptsetup/\fR
|
||||
|
||||
The cryptsetup FAQ, contained in the distribution package and
|
||||
online at
|
||||
\fBhttp://code.google.com/p/cryptsetup/wiki/FrequentlyAskedQuestions\fR
|
||||
\fBhttps://gitlab.com/cryptsetup/cryptsetup/wikis/FrequentlyAskedQuestions\fR
|
||||
|
||||
The cryptsetup mailing list and list archive, see FAQ entry 1.6.
|
||||
|
||||
The LUKS on-disk format specification available at
|
||||
\fBhttp://code.google.com/p/cryptsetup/wiki/Specification\fR
|
||||
\fBhttps://gitlab.com/cryptsetup/cryptsetup/wikis/Specification\fR
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.TH VERITYSETUP "8" "June 2012" "veritysetup" "Maintenance Commands"
|
||||
.TH VERITYSETUP "8" "December 2013" "veritysetup" "Maintenance Commands"
|
||||
.SH NAME
|
||||
veritysetup - manage dm-verity (block level verification) volumes
|
||||
.SH SYNOPSIS
|
||||
@@ -130,12 +130,14 @@ The first implementation of veritysetup was written by Chrome OS authors.
|
||||
This version is based on verification code written by Mikulas Patocka <mpatocka@redhat.com>
|
||||
and rewritten for libcryptsetup by Milan Broz <gmazyland@gmail.com>.
|
||||
.SH COPYRIGHT
|
||||
Copyright \(co 2012 Red Hat, Inc.
|
||||
Copyright \(co 2012-2013 Red Hat, Inc.
|
||||
.br
|
||||
Copyright \(co 2012-2014 Milan Broz
|
||||
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
.SH SEE ALSO
|
||||
The project website at \fBhttp://code.google.com/p/cryptsetup/\fR
|
||||
The project website at \fBhttps://gitlab.com/cryptsetup/cryptsetup\fR
|
||||
|
||||
The verity on-disk format specification available at
|
||||
\fBhttp://code.google.com/p/cryptsetup/wiki/DMVerity\fR
|
||||
\fBhttps://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity\fR
|
||||
|
||||
17
misc/11-dm-crypt.rules
Normal file
17
misc/11-dm-crypt.rules
Normal file
@@ -0,0 +1,17 @@
|
||||
# Old udev rules historically used in device-mapper.
|
||||
# No need to install these until you have some weird configuration.
|
||||
# (Code internally set the same flags.)
|
||||
|
||||
ACTION!="add|change", GOTO="crypt_end"
|
||||
ENV{DM_UDEV_RULES_VSN}!="?*", GOTO="crypt_end"
|
||||
|
||||
ENV{DM_UUID}=="CRYPT-TEMP-?*", GOTO="crypt_disable"
|
||||
ENV{DM_UUID}!="?*", ENV{DM_NAME}=="temporary-cryptsetup-?*", GOTO="crypt_disable"
|
||||
GOTO="crypt_end"
|
||||
|
||||
LABEL="crypt_disable"
|
||||
ENV{DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG}="1"
|
||||
ENV{DM_UDEV_DISABLE_DISK_RULES_FLAG}="1"
|
||||
ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="1"
|
||||
|
||||
LABEL="crypt_end"
|
||||
@@ -2,13 +2,28 @@ Example of simple dracut module for reencryption of system
|
||||
LUKS drive on-the-fly.
|
||||
|
||||
Install in /usr/[share|lib]/dracut/modules.d/90reencrypt, then
|
||||
rebuild intramfs "with dracut -f -a reencrypt".
|
||||
build special intramfs "with dracut -a reencrypt -o crypt".
|
||||
Reencrypt module doesn't work (has a conflict) with crypt module as
|
||||
of now. After successfull reencryption reboot using original initramfs.
|
||||
|
||||
Dracut then recognize argument rd_REENCRYPT=name:size,
|
||||
e.g. rd_REENCRYPT=sda2:52G means only 52G of device
|
||||
Dracut then recognize argument rd.luks.reencrypt=name:size,
|
||||
e.g. rd.luks.reencrypt=sda2:52G means only 52G of device
|
||||
will be reencrypted (default is whole device).
|
||||
(Name is kernel name of device.)
|
||||
|
||||
Also, you may specify keyslot which you want to use for reencryption,
|
||||
rd.luks.reencrypt_keyslot=<keyslot_number>. Bear in mind that if you
|
||||
use this option, all other keyslots will be deactivated.
|
||||
|
||||
Another argument, rd.luks.reencrypt_key=/dev/sda:/path/to/keyfile
|
||||
can be used to read password for specific keyslot from device containing
|
||||
filesystem with a keyfile (file with a password). If you omit reencrypt_key
|
||||
argument, reencryption would work only in case a LUKS container has
|
||||
exactly one keyslot activated.
|
||||
|
||||
Arguments rd.luks.reencrypt_keyslot and rd.luks.reencrypt_key are not
|
||||
mandatory.
|
||||
|
||||
Note that reencryption context is stored in ramdisk, any
|
||||
fail can mean complete lost of data!
|
||||
|
||||
|
||||
@@ -7,16 +7,23 @@ check() {
|
||||
|
||||
depends() {
|
||||
echo dm rootfs-block
|
||||
return 0
|
||||
}
|
||||
|
||||
installkernel() {
|
||||
instmods dm_crypt =crypto
|
||||
# requires hostonly='' override so that loop module is pulled in initramfs
|
||||
# even if not loaded in actual kernel. dracut bug?
|
||||
hostonly='' instmods dm_crypt =crypto loop
|
||||
}
|
||||
|
||||
install() {
|
||||
if dracut_module_included crypt; then
|
||||
derror "'reencrypt' can't be installed together with 'crypt'."
|
||||
derror "Add '-o crypt' option to install reencrypt module."
|
||||
return 1
|
||||
fi
|
||||
|
||||
dracut_install cryptsetup-reencrypt
|
||||
|
||||
inst_hook cmdline 30 "$moddir/parse-reencrypt.sh"
|
||||
inst_simple "$moddir"/reencrypt.sh /sbin/reencrypt
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,19 @@
|
||||
#!/bin/sh
|
||||
|
||||
REENC=$(getargs rd_REENCRYPT=)
|
||||
REENC=$(getargs rd.luks.reencrypt=)
|
||||
REENC_DEV=$(echo $REENC | sed 's/:.*//')
|
||||
REENC_SIZE=$(echo $REENC | sed -n 's/.*://p')
|
||||
|
||||
REENC_KEY=$(getargs rd_REENCRYPT_KEY=)
|
||||
REENC_KEY=$(getargs rd.luks.reencrypt_key=)
|
||||
if [ -z "$REENC_KEY" ] ; then
|
||||
REENC_KEY=none
|
||||
fi
|
||||
|
||||
REENC_SLOT=$(getargs rd.luks.reencrypt_keyslot=)
|
||||
if [ -z "$REENC_SLOT" ] ; then
|
||||
REENC_SLOT=any
|
||||
fi
|
||||
|
||||
if [ -n "$REENC_DEV" ] ; then
|
||||
{
|
||||
printf 'SUBSYSTEM!="block", GOTO="reenc_end"\n'
|
||||
@@ -16,7 +21,7 @@ if [ -n "$REENC_DEV" ] ; then
|
||||
printf 'KERNEL!="%s", GOTO="reenc_end"\n' $REENC_DEV
|
||||
printf 'ENV{ID_FS_TYPE}=="crypto_LUKS", RUN+="/sbin/initqueue \
|
||||
--unique --onetime --name crypt-reencrypt-%%k \
|
||||
/sbin/reencrypt $env{DEVNAME} %s"\n' "$REENC_KEY $REENC_SIZE"
|
||||
/sbin/reencrypt $env{DEVNAME} %s"\n' "$REENC_KEY $REENC_SLOT $REENC_SIZE"
|
||||
printf 'LABEL="reenc_end"\n'
|
||||
} > /etc/udev/rules.d/69-reencryption.rules
|
||||
fi
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# $1=$device [$2=keyfile|none [$3=size]]
|
||||
# $1=$device [$2=keyfile|none [$3=keyslot|any [$4=size]]]
|
||||
#
|
||||
|
||||
[ -d /sys/module/dm_crypt ] || modprobe dm_crypt
|
||||
|
||||
[ -d /sys/module/loop ] || modprobe loop
|
||||
|
||||
[ -f /tmp/reencrypted ] && exit 0
|
||||
|
||||
. /lib/dracut-lib.sh
|
||||
@@ -17,8 +19,12 @@ else
|
||||
fi
|
||||
|
||||
PARAMS="$device -T 1 --use-fsync -B 32"
|
||||
if [ -n "$3" ]; then
|
||||
PARAMS="$PARAMS --device-size $3"
|
||||
if [ "$3" != "any" ]; then
|
||||
PARAMS="$PARAMS -S $3"
|
||||
fi
|
||||
|
||||
if [ -n "$4" ]; then
|
||||
PARAMS="$PARAMS --device-size $4"
|
||||
fi
|
||||
|
||||
reenc_readkey() {
|
||||
@@ -34,25 +40,40 @@ reenc_readkey() {
|
||||
|
||||
reenc_run() {
|
||||
local cwd=$(pwd)
|
||||
local _prompt="LUKS password for REENCRYPTING $device"
|
||||
cd /tmp
|
||||
if [ "$1" = "none" ] ; then
|
||||
if [ "$2" != "any" ]; then
|
||||
_prompt="$_prompt, using keyslot $2"
|
||||
fi
|
||||
/bin/plymouth ask-for-password \
|
||||
--prompt "LUKS password for REENCRYPTING $device" \
|
||||
--prompt "$_prompt" \
|
||||
--command="/sbin/cryptsetup-reencrypt $PARAMS"
|
||||
else
|
||||
info "REENCRYPT using key $1"
|
||||
reenc_readkey "$1" | /sbin/cryptsetup-reencrypt -d - $PARAMS
|
||||
fi
|
||||
_ret=$?
|
||||
cd $cwd
|
||||
}
|
||||
|
||||
info "REENCRYPT $device requested"
|
||||
# flock against other interactive activities
|
||||
{ flock -s 9;
|
||||
reenc_run $2
|
||||
} 9>/.console.lock
|
||||
reenc_run $2 $3
|
||||
} 9>/.console_lock
|
||||
|
||||
# do not ask again
|
||||
>> /tmp/reencrypted
|
||||
if [ $_ret -eq 0 ]; then
|
||||
# do not ask again
|
||||
>> /tmp/reencrypted
|
||||
warn "Reencryption of device $device has finished successfully. Use previous"
|
||||
warn "initramfs image (without reencrypt module) to boot the system. When"
|
||||
warn "you leave the emergency shell, the system will reboot."
|
||||
|
||||
exit 0
|
||||
emergency_shell -n "(reboot)"
|
||||
[ -x /usr/bin/systemctl ] && /usr/bin/systemctl reboot
|
||||
[ -x /sbin/shutdown ] && /sbin/shutdown -r now
|
||||
fi
|
||||
|
||||
# panic the kernel otherwise
|
||||
exit 1
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
cs
|
||||
da
|
||||
de
|
||||
es
|
||||
fi
|
||||
fr
|
||||
id
|
||||
it
|
||||
nl
|
||||
pl
|
||||
sr
|
||||
sv
|
||||
uk
|
||||
vi
|
||||
zh_CN
|
||||
|
||||
1770
po/zh_CN.po
Normal file
1770
po/zh_CN.po
Normal file
File diff suppressed because it is too large
Load Diff
@@ -10,7 +10,7 @@ pyexec_LTLIBRARIES = pycryptsetup.la
|
||||
pycryptsetup_la_SOURCES = pycryptsetup.c
|
||||
pycryptsetup_la_CPPFLAGS = $(AM_CPPFLAGS) $(PYTHON_CPPFLAGS) -fno-strict-aliasing
|
||||
pycryptsetup_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
|
||||
pycryptsetup_la_LIBADD = $(top_builddir)/lib/libcryptsetup.la -lpython$(PYTHON_VERSION)
|
||||
pycryptsetup_la_LIBADD = $(top_builddir)/lib/libcryptsetup.la $(PYTHON_LIBS)
|
||||
else
|
||||
all:
|
||||
endif
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#
|
||||
# Python bindings to libcryptsetup test
|
||||
#
|
||||
# Copyright (C) 2011, Red Hat, Inc. All rights reserved.
|
||||
# Copyright (C) 2011-2014, Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
@@ -18,6 +18,8 @@
|
||||
# License along with this file; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
@@ -31,11 +33,11 @@ DEVICE = "pycryptsetup_test_dev"
|
||||
|
||||
def log(level, txt):
|
||||
if level == pycryptsetup.CRYPT_LOG_ERROR:
|
||||
print txt,
|
||||
print(txt,end="")
|
||||
return
|
||||
|
||||
def askyes(txt):
|
||||
print "Question:", txt
|
||||
print("Question:", txt)
|
||||
return 1
|
||||
|
||||
def askpassword(txt):
|
||||
@@ -43,17 +45,17 @@ def askpassword(txt):
|
||||
|
||||
def print_status(c):
|
||||
r = c.status()
|
||||
print "status :",
|
||||
print("status :",end="")
|
||||
if r == pycryptsetup.CRYPT_ACTIVE:
|
||||
print "ACTIVE"
|
||||
print("ACTIVE")
|
||||
elif r == pycryptsetup.CRYPT_INACTIVE:
|
||||
print "INACTIVE"
|
||||
print("INACTIVE")
|
||||
else:
|
||||
print "ERROR"
|
||||
print("ERROR")
|
||||
return
|
||||
|
||||
if os.geteuid() != 0:
|
||||
print "WARNING: You must be root to run this test, test skipped."
|
||||
print("WARNING: You must be root to run this test, test skipped.")
|
||||
sys.exit(0)
|
||||
|
||||
os.system("dd if=/dev/zero of=" + IMG + " bs=1M count=32 >/dev/null 2>&1")
|
||||
@@ -69,36 +71,36 @@ c = pycryptsetup.CryptSetup(
|
||||
c.debugLevel(pycryptsetup.CRYPT_DEBUG_NONE);
|
||||
c.iterationTime(1)
|
||||
r = c.isLuks()
|
||||
print "isLuks :", r
|
||||
print("isLuks :", r)
|
||||
c.askyes(message = "Is there anybody out there?")
|
||||
c.log(priority = pycryptsetup.CRYPT_LOG_ERROR, message = "Nobody there...\n")
|
||||
c.luksFormat(cipher = "aes", cipherMode= "xts-plain64", keysize = 512)
|
||||
print "isLuks :", c.isLuks()
|
||||
print "luksUUID:", c.luksUUID()
|
||||
print "addKeyVK:", c.addKeyByVolumeKey(newPassphrase = PASSWORD, slot = 2)
|
||||
print "addKeyP :", c.addKeyByPassphrase(passphrase = PASSWORD,
|
||||
newPassphrase = PASSWORD2, slot = 3)
|
||||
print "removeP :", c.removePassphrase(passphrase = PASSWORD2)
|
||||
print "addKeyP :", c.addKeyByPassphrase(PASSWORD, PASSWORD2)
|
||||
print("isLuks :", c.isLuks())
|
||||
print("luksUUID:", c.luksUUID())
|
||||
print("addKeyVK:", c.addKeyByVolumeKey(newPassphrase = PASSWORD, slot = 2))
|
||||
print("addKeyP :", c.addKeyByPassphrase(passphrase = PASSWORD,
|
||||
newPassphrase = PASSWORD2, slot = 3))
|
||||
print("removeP :", c.removePassphrase(passphrase = PASSWORD2))
|
||||
print("addKeyP :", c.addKeyByPassphrase(PASSWORD, PASSWORD2))
|
||||
# original api required wrong passphrase parameter here
|
||||
# print "killSlot:", c.killSlot(passphrase = "xxx", slot = 0)
|
||||
print "killSlot:", c.killSlot(slot = 0)
|
||||
print "activate:", c.activate(name = DEVICE, passphrase = PASSWORD)
|
||||
print "suspend :", c.suspend()
|
||||
print("killSlot:", c.killSlot(slot = 0))
|
||||
print("activate:", c.activate(name = DEVICE, passphrase = PASSWORD))
|
||||
print("suspend :", c.suspend())
|
||||
# os.system("dmsetup info -c " + DEVICE)
|
||||
print "resume :", c.resume(passphrase = PASSWORD)
|
||||
print("resume :", c.resume(passphrase = PASSWORD))
|
||||
print_status(c)
|
||||
info = c.info()
|
||||
print "cipher :", info["cipher"]
|
||||
print "cmode :", info["cipher_mode"]
|
||||
print "keysize :", info["keysize"]
|
||||
print "dir :", info["dir"]
|
||||
print "device :", info["device"]
|
||||
print "offset :", info["offset"]
|
||||
print "name :", info["name"]
|
||||
print "uuid :", info["uuid"]
|
||||
print("cipher :", info["cipher"])
|
||||
print("cmode :", info["cipher_mode"])
|
||||
print("keysize :", info["keysize"])
|
||||
print("dir :", info["dir"])
|
||||
print("device :", info["device"])
|
||||
print("offset :", info["offset"])
|
||||
print("name :", info["name"])
|
||||
print("uuid :", info["uuid"])
|
||||
# os.system("cryptsetup luksDump " + info["device"])
|
||||
print "deact. :", c.deactivate()
|
||||
print("deact. :", c.deactivate())
|
||||
|
||||
del c
|
||||
|
||||
@@ -109,7 +111,7 @@ c = pycryptsetup.CryptSetup(
|
||||
logFunc = log,
|
||||
passwordDialog = askpassword)
|
||||
|
||||
print "activate:", c.activate(name = DEVICE, passphrase = PASSWORD)
|
||||
print("activate:", c.activate(name = DEVICE, passphrase = PASSWORD))
|
||||
|
||||
c2 = pycryptsetup.CryptSetup(
|
||||
name = DEVICE,
|
||||
@@ -118,13 +120,13 @@ c2 = pycryptsetup.CryptSetup(
|
||||
passwordDialog = askpassword)
|
||||
|
||||
info = c2.info()
|
||||
print "cipher :", info["cipher"]
|
||||
print "cmode :", info["cipher_mode"]
|
||||
print "keysize :", info["keysize"]
|
||||
print("cipher :", info["cipher"])
|
||||
print("cmode :", info["cipher_mode"])
|
||||
print("keysize :", info["keysize"])
|
||||
|
||||
print "deact. :", c.deactivate()
|
||||
print("deact. :", c.deactivate())
|
||||
r = c2.deactivate()
|
||||
print "deact. :", r
|
||||
print("deact. :", r)
|
||||
del c
|
||||
del c2
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Python bindings to libcryptsetup
|
||||
*
|
||||
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2009-2014, Red Hat, Inc. All rights reserved.
|
||||
* Written by Martin Sivak
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or
|
||||
@@ -25,6 +25,29 @@
|
||||
|
||||
#include "libcryptsetup.h"
|
||||
|
||||
/* Python API use char* where const char* should be used... */
|
||||
#define CONST_CAST(x) (x)(uintptr_t)
|
||||
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
#define MOD_ERROR_VAL
|
||||
#define MOD_SUCCESS_VAL(val)
|
||||
#define MOD_INIT(name) void init##name(void)
|
||||
#define MOD_DEF(ob, name, doc, methods) \
|
||||
ob = Py_InitModule3(name, methods, doc);
|
||||
#else
|
||||
#define PyInt_AsLong PyLong_AsLong
|
||||
#define PyInt_Check PyLong_Check
|
||||
#define MOD_ERROR_VAL NULL
|
||||
#define MOD_SUCCESS_VAL(val) val
|
||||
#define MOD_INIT(name) PyMODINIT_FUNC PyInit_##name(void)
|
||||
#define MOD_DEF(ob, name, doc, methods) \
|
||||
static struct PyModuleDef moduledef = { \
|
||||
PyModuleDef_HEAD_INIT, name, doc, -1, methods, }; \
|
||||
ob = PyModule_Create(&moduledef);
|
||||
#endif
|
||||
|
||||
MOD_INIT(pycryptsetup);
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
|
||||
@@ -128,7 +151,7 @@ static void CryptSetup_dealloc(CryptSetupObject* self)
|
||||
crypt_free(self->device);
|
||||
|
||||
/* free self */
|
||||
self->ob_type->tp_free((PyObject*)self);
|
||||
Py_TYPE(self)->tp_free((PyObject*)self);
|
||||
}
|
||||
|
||||
static PyObject *CryptSetup_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||
@@ -155,17 +178,19 @@ static PyObject *PyObjectResult(int is)
|
||||
return result;
|
||||
}
|
||||
|
||||
#define CryptSetup_HELP "CryptSetup object\n\n\
|
||||
static char
|
||||
CryptSetup_HELP[] =
|
||||
"CryptSetup object\n\n\
|
||||
constructor takes one to five arguments:\n\
|
||||
__init__(device, name, yesDialog, passwordDialog, logFunc)\n\n\
|
||||
yesDialog - python function with func(text) signature, \n\
|
||||
which asks the user question text and returns 1\n\
|
||||
of the answer was positive or 0 if not\n\
|
||||
logFunc - python function with func(level, text) signature to log stuff somewhere"
|
||||
logFunc - python function with func(level, text) signature to log stuff somewhere";
|
||||
|
||||
static int CryptSetup_init(CryptSetupObject* self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
static char *kwlist[] = {"device", "name", "yesDialog", "passwordDialog", "logFunc", NULL};
|
||||
static const char *kwlist[] = {"device", "name", "yesDialog", "passwordDialog", "logFunc", NULL};
|
||||
PyObject *yesDialogCB = NULL,
|
||||
*passwordDialogCB = NULL,
|
||||
*cmdLineLogCB = NULL,
|
||||
@@ -173,7 +198,7 @@ static int CryptSetup_init(CryptSetupObject* self, PyObject *args, PyObject *kwd
|
||||
char *device = NULL, *deviceName = NULL;
|
||||
int r;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|zzOOO", kwlist, &device, &deviceName,
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|zzOOO", CONST_CAST(char**)kwlist, &device, &deviceName,
|
||||
&yesDialogCB, &passwordDialogCB, &cmdLineLogCB))
|
||||
return -1;
|
||||
|
||||
@@ -229,16 +254,18 @@ static int CryptSetup_init(CryptSetupObject* self, PyObject *args, PyObject *kwd
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define CryptSetup_activate_HELP "Activate LUKS device\n\n\
|
||||
activate(name)"
|
||||
static char
|
||||
CryptSetup_activate_HELP[] =
|
||||
"Activate LUKS device\n\n\
|
||||
activate(name)";
|
||||
|
||||
static PyObject *CryptSetup_activate(CryptSetupObject* self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
static char *kwlist[] = {"name", "passphrase", NULL};
|
||||
static const char *kwlist[] = {"name", "passphrase", NULL};
|
||||
char *name = NULL, *passphrase = NULL;
|
||||
int is;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|s", kwlist, &name, &passphrase))
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|s", CONST_CAST(char**)kwlist, &name, &passphrase))
|
||||
return NULL;
|
||||
|
||||
// FIXME: allow keyfile and \0 in passphrase
|
||||
@@ -253,8 +280,10 @@ static PyObject *CryptSetup_activate(CryptSetupObject* self, PyObject *args, PyO
|
||||
return PyObjectResult(is);
|
||||
}
|
||||
|
||||
#define CryptSetup_deactivate_HELP "Dectivate LUKS device\n\n\
|
||||
deactivate()"
|
||||
static char
|
||||
CryptSetup_deactivate_HELP[] =
|
||||
"Dectivate LUKS device\n\n\
|
||||
deactivate()";
|
||||
|
||||
static PyObject *CryptSetup_deactivate(CryptSetupObject* self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
@@ -268,15 +297,17 @@ static PyObject *CryptSetup_deactivate(CryptSetupObject* self, PyObject *args, P
|
||||
return PyObjectResult(is);
|
||||
}
|
||||
|
||||
#define CryptSetup_askyes_HELP "Asks a question using the configured dialog CB\n\n\
|
||||
int askyes(message)"
|
||||
static char
|
||||
CryptSetup_askyes_HELP[] =
|
||||
"Asks a question using the configured dialog CB\n\n\
|
||||
int askyes(message)";
|
||||
|
||||
static PyObject *CryptSetup_askyes(CryptSetupObject* self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
static char *kwlist[] = {"message", NULL};
|
||||
static const char *kwlist[] = {"message", NULL};
|
||||
PyObject *message = NULL, *result, *arglist;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &message))
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", CONST_CAST(char**)kwlist, &message))
|
||||
return NULL;
|
||||
|
||||
Py_INCREF(message);
|
||||
@@ -294,15 +325,17 @@ static PyObject *CryptSetup_askyes(CryptSetupObject* self, PyObject *args, PyObj
|
||||
return result;
|
||||
}
|
||||
|
||||
#define CryptSetup_log_HELP "Logs a string using the configured log CB\n\n\
|
||||
log(int level, message)"
|
||||
static char
|
||||
CryptSetup_log_HELP[] =
|
||||
"Logs a string using the configured log CB\n\n\
|
||||
log(int level, message)";
|
||||
|
||||
static PyObject *CryptSetup_log(CryptSetupObject* self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
static char *kwlist[] = {"priority", "message", NULL};
|
||||
static const char *kwlist[] = {"priority", "message", NULL};
|
||||
PyObject *message = NULL, *priority = NULL, *result, *arglist;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist, &message, &priority))
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO", CONST_CAST(char**)kwlist, &message, &priority))
|
||||
return NULL;
|
||||
|
||||
Py_INCREF(message);
|
||||
@@ -322,8 +355,10 @@ static PyObject *CryptSetup_log(CryptSetupObject* self, PyObject *args, PyObject
|
||||
return result;
|
||||
}
|
||||
|
||||
#define CryptSetup_luksUUID_HELP "Get UUID of the LUKS device\n\n\
|
||||
luksUUID()"
|
||||
static char
|
||||
CryptSetup_luksUUID_HELP[] =
|
||||
"Get UUID of the LUKS device\n\n\
|
||||
luksUUID()";
|
||||
|
||||
static PyObject *CryptSetup_luksUUID(CryptSetupObject* self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
@@ -336,17 +371,21 @@ static PyObject *CryptSetup_luksUUID(CryptSetupObject* self, PyObject *args, PyO
|
||||
return result;
|
||||
}
|
||||
|
||||
#define CryptSetup_isLuks_HELP "Is the device LUKS?\n\n\
|
||||
isLuks()"
|
||||
static char
|
||||
CryptSetup_isLuks_HELP[] =
|
||||
"Is the device LUKS?\n\n\
|
||||
isLuks()";
|
||||
|
||||
static PyObject *CryptSetup_isLuks(CryptSetupObject* self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
return PyObjectResult(crypt_load(self->device, CRYPT_LUKS1, NULL));
|
||||
}
|
||||
|
||||
#define CryptSetup_Info_HELP "Returns dictionary with info about opened device\nKeys:\n\
|
||||
static char
|
||||
CryptSetup_Info_HELP[] =
|
||||
"Returns dictionary with info about opened device\nKeys:\n\
|
||||
dir\n name\n uuid\n cipher\n cipher_mode\n keysize\n device\n\
|
||||
offset\n size\n skip\n mode\n"
|
||||
offset\n size\n skip\n mode\n";
|
||||
|
||||
static PyObject *CryptSetup_Info(CryptSetupObject* self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
@@ -371,20 +410,22 @@ static PyObject *CryptSetup_Info(CryptSetupObject* self, PyObject *args, PyObjec
|
||||
return result;
|
||||
}
|
||||
|
||||
#define CryptSetup_luksFormat_HELP "Format device to enable LUKS\n\n\
|
||||
static char
|
||||
CryptSetup_luksFormat_HELP[] =
|
||||
"Format device to enable LUKS\n\n\
|
||||
luksFormat(cipher = 'aes', cipherMode = 'cbc-essiv:sha256', keysize = 256)\n\n\
|
||||
cipher - cipher specification, e.g. aes, serpent\n\
|
||||
cipherMode - cipher mode specification, e.g. cbc-essiv:sha256, xts-plain64\n\
|
||||
keysize - key size in bits"
|
||||
keysize - key size in bits";
|
||||
|
||||
static PyObject *CryptSetup_luksFormat(CryptSetupObject* self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
static char *kwlist[] = {"cipher", "cipherMode", "keysize", NULL};
|
||||
static const char *kwlist[] = {"cipher", "cipherMode", "keysize", NULL};
|
||||
char *cipher_mode = NULL, *cipher = NULL;
|
||||
int keysize = 256;
|
||||
PyObject *keysize_object = NULL;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|zzO", kwlist,
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|zzO", CONST_CAST(char**)kwlist,
|
||||
&cipher, &cipher_mode, &keysize_object))
|
||||
return NULL;
|
||||
|
||||
@@ -408,20 +449,22 @@ static PyObject *CryptSetup_luksFormat(CryptSetupObject* self, PyObject *args, P
|
||||
NULL, NULL, keysize / 8, NULL));
|
||||
}
|
||||
|
||||
#define CryptSetup_addKeyByPassphrase_HELP "Initialize keyslot using passphrase\n\n\
|
||||
static char
|
||||
CryptSetup_addKeyByPassphrase_HELP[] =
|
||||
"Initialize keyslot using passphrase\n\n\
|
||||
addKeyByPassphrase(passphrase, newPassphrase, slot)\n\n\
|
||||
passphrase - string or none to ask the user\n\
|
||||
newPassphrase - passphrase to add\n\
|
||||
slot - which slot to use (optional)"
|
||||
slot - which slot to use (optional)";
|
||||
|
||||
static PyObject *CryptSetup_addKeyByPassphrase(CryptSetupObject* self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
static char *kwlist[] = {"passphrase", "newPassphrase", "slot", NULL};
|
||||
static const char *kwlist[] = {"passphrase", "newPassphrase", "slot", NULL};
|
||||
char *passphrase = NULL, *newpassphrase = NULL;
|
||||
size_t passphrase_len = 0, newpassphrase_len = 0;
|
||||
int slot = CRYPT_ANY_SLOT;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss|i", kwlist, &passphrase, &newpassphrase, &slot))
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss|i", CONST_CAST(char**)kwlist, &passphrase, &newpassphrase, &slot))
|
||||
return NULL;
|
||||
|
||||
if(passphrase)
|
||||
@@ -435,19 +478,21 @@ static PyObject *CryptSetup_addKeyByPassphrase(CryptSetupObject* self, PyObject
|
||||
newpassphrase, newpassphrase_len));
|
||||
}
|
||||
|
||||
#define CryptSetup_addKeyByVolumeKey_HELP "Initialize keyslot using cached volume key\n\n\
|
||||
static char
|
||||
CryptSetup_addKeyByVolumeKey_HELP[] =
|
||||
"Initialize keyslot using cached volume key\n\n\
|
||||
addKeyByVolumeKey(passphrase, newPassphrase, slot)\n\n\
|
||||
newPassphrase - passphrase to add\n\
|
||||
slot - which slot to use (optional)"
|
||||
slot - which slot to use (optional)";
|
||||
|
||||
static PyObject *CryptSetup_addKeyByVolumeKey(CryptSetupObject* self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
static char *kwlist[] = {"newPassphrase", "slot", NULL};
|
||||
static const char *kwlist[] = {"newPassphrase", "slot", NULL};
|
||||
char *newpassphrase = NULL;
|
||||
size_t newpassphrase_len = 0;
|
||||
int slot = CRYPT_ANY_SLOT;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|i", kwlist, &newpassphrase, &slot))
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|i", CONST_CAST(char**)kwlist, &newpassphrase, &slot))
|
||||
return NULL;
|
||||
|
||||
if (newpassphrase)
|
||||
@@ -457,18 +502,20 @@ static PyObject *CryptSetup_addKeyByVolumeKey(CryptSetupObject* self, PyObject *
|
||||
NULL, 0, newpassphrase, newpassphrase_len));
|
||||
}
|
||||
|
||||
#define CryptSetup_removePassphrase_HELP "Destroy keyslot using passphrase\n\n\
|
||||
static char
|
||||
CryptSetup_removePassphrase_HELP[] =
|
||||
"Destroy keyslot using passphrase\n\n\
|
||||
removePassphrase(passphrase)\n\n\
|
||||
passphrase - string or none to ask the user"
|
||||
passphrase - string or none to ask the user";
|
||||
|
||||
static PyObject *CryptSetup_removePassphrase(CryptSetupObject* self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
static char *kwlist[] = {"passphrase", NULL};
|
||||
static const char *kwlist[] = {"passphrase", NULL};
|
||||
char *passphrase = NULL;
|
||||
size_t passphrase_len = 0;
|
||||
int is;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &passphrase))
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", CONST_CAST(char**)kwlist, &passphrase))
|
||||
return NULL;
|
||||
|
||||
if (passphrase)
|
||||
@@ -482,16 +529,18 @@ static PyObject *CryptSetup_removePassphrase(CryptSetupObject* self, PyObject *a
|
||||
return PyObjectResult(crypt_keyslot_destroy(self->device, is));
|
||||
}
|
||||
|
||||
#define CryptSetup_killSlot_HELP "Destroy keyslot\n\n\
|
||||
static char
|
||||
CryptSetup_killSlot_HELP[] =
|
||||
"Destroy keyslot\n\n\
|
||||
killSlot(slot)\n\n\
|
||||
slot - the slot to remove"
|
||||
slot - the slot to remove";
|
||||
|
||||
static PyObject *CryptSetup_killSlot(CryptSetupObject* self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
static char *kwlist[] = {"slot", NULL};
|
||||
static const char *kwlist[] = {"slot", NULL};
|
||||
int slot = CRYPT_ANY_SLOT;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &slot))
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", CONST_CAST(char**)kwlist, &slot))
|
||||
return NULL;
|
||||
|
||||
switch (crypt_keyslot_status(self->device, slot)) {
|
||||
@@ -511,8 +560,10 @@ static PyObject *CryptSetup_killSlot(CryptSetupObject* self, PyObject *args, PyO
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define CryptSetup_Status_HELP "Status of LUKS device\n\n\
|
||||
luksStatus()"
|
||||
static char
|
||||
CryptSetup_Status_HELP[] =
|
||||
"Status of LUKS device\n\n\
|
||||
luksStatus()";
|
||||
|
||||
static PyObject *CryptSetup_Status(CryptSetupObject* self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
@@ -524,13 +575,15 @@ static PyObject *CryptSetup_Status(CryptSetupObject* self, PyObject *args, PyObj
|
||||
return PyObjectResult(crypt_status(self->device, self->activated_as));
|
||||
}
|
||||
|
||||
#define CryptSetup_Resume_HELP "Resume LUKS device\n\n\
|
||||
static char
|
||||
CryptSetup_Resume_HELP[] =
|
||||
"Resume LUKS device\n\n\
|
||||
luksOpen(passphrase)\n\n\
|
||||
passphrase - string or none to ask the user"
|
||||
passphrase - string or none to ask the user";
|
||||
|
||||
static PyObject *CryptSetup_Resume(CryptSetupObject* self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
static char *kwlist[] = {"passphrase", NULL};
|
||||
static const char *kwlist[] = {"passphrase", NULL};
|
||||
char* passphrase = NULL;
|
||||
size_t passphrase_len = 0;
|
||||
|
||||
@@ -539,7 +592,7 @@ static PyObject *CryptSetup_Resume(CryptSetupObject* self, PyObject *args, PyObj
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (! PyArg_ParseTupleAndKeywords(args, kwds, "|s", kwlist, &passphrase))
|
||||
if (! PyArg_ParseTupleAndKeywords(args, kwds, "|s", CONST_CAST(char**)kwlist, &passphrase))
|
||||
return NULL;
|
||||
|
||||
if (passphrase)
|
||||
@@ -549,8 +602,10 @@ static PyObject *CryptSetup_Resume(CryptSetupObject* self, PyObject *args, PyObj
|
||||
CRYPT_ANY_SLOT, passphrase, passphrase_len));
|
||||
}
|
||||
|
||||
#define CryptSetup_Suspend_HELP "Suspend LUKS device\n\n\
|
||||
luksSupsend()"
|
||||
static char
|
||||
CryptSetup_Suspend_HELP[] =
|
||||
"Suspend LUKS device\n\n\
|
||||
luksSupsend()";
|
||||
|
||||
static PyObject *CryptSetup_Suspend(CryptSetupObject* self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
@@ -562,16 +617,18 @@ static PyObject *CryptSetup_Suspend(CryptSetupObject* self, PyObject *args, PyOb
|
||||
return PyObjectResult(crypt_suspend(self->device, self->activated_as));
|
||||
}
|
||||
|
||||
#define CryptSetup_debugLevel_HELP "Set debug level\n\n\
|
||||
static char
|
||||
CryptSetup_debugLevel_HELP[] =
|
||||
"Set debug level\n\n\
|
||||
debugLevel(level)\n\n\
|
||||
level - debug level"
|
||||
level - debug level";
|
||||
|
||||
static PyObject *CryptSetup_debugLevel(CryptSetupObject* self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
static char *kwlist[] = {"level", NULL};
|
||||
static const char *kwlist[] = {"level", NULL};
|
||||
int level = 0;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &level))
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", CONST_CAST(char**)kwlist, &level))
|
||||
return NULL;
|
||||
|
||||
crypt_set_debug_level(level);
|
||||
@@ -579,16 +636,18 @@ static PyObject *CryptSetup_debugLevel(CryptSetupObject* self, PyObject *args, P
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
#define CryptSetup_iterationTime_HELP "Set iteration time\n\n\
|
||||
static char
|
||||
CryptSetup_iterationTime_HELP[] =
|
||||
"Set iteration time\n\n\
|
||||
iterationTime(time_ms)\n\n\
|
||||
time_ms - time in miliseconds"
|
||||
time_ms - time in miliseconds";
|
||||
|
||||
static PyObject *CryptSetup_iterationTime(CryptSetupObject* self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
static char *kwlist[] = {"time_ms", NULL};
|
||||
static const char *kwlist[] = {"time_ms", NULL};
|
||||
uint64_t time_ms = 0;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "K", kwlist, &time_ms))
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "K", CONST_CAST(char**)kwlist, &time_ms))
|
||||
return NULL;
|
||||
|
||||
crypt_set_iteration_time(self->device, time_ms);
|
||||
@@ -597,9 +656,9 @@ static PyObject *CryptSetup_iterationTime(CryptSetupObject* self, PyObject *args
|
||||
}
|
||||
|
||||
static PyMemberDef CryptSetup_members[] = {
|
||||
{"yesDialogCB", T_OBJECT_EX, offsetof(CryptSetupObject, yesDialogCB), 0, "confirmation dialog callback"},
|
||||
{"cmdLineLogCB", T_OBJECT_EX, offsetof(CryptSetupObject, cmdLineLogCB), 0, "logging callback"},
|
||||
{"passwordDialogCB", T_OBJECT_EX, offsetof(CryptSetupObject, passwordDialogCB), 0, "password dialog callback"},
|
||||
{CONST_CAST(char*)"yesDialogCB", T_OBJECT_EX, offsetof(CryptSetupObject, yesDialogCB), 0, CONST_CAST(char*)"confirmation dialog callback"},
|
||||
{CONST_CAST(char*)"cmdLineLogCB", T_OBJECT_EX, offsetof(CryptSetupObject, cmdLineLogCB), 0, CONST_CAST(char*)"logging callback"},
|
||||
{CONST_CAST(char*)"passwordDialogCB", T_OBJECT_EX, offsetof(CryptSetupObject, passwordDialogCB), 0, CONST_CAST(char*)"password dialog callback"},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
@@ -615,7 +674,7 @@ static PyMethodDef CryptSetup_methods[] = {
|
||||
/* cryptsetup info entrypoints */
|
||||
{"luksUUID", (PyCFunction)CryptSetup_luksUUID, METH_NOARGS, CryptSetup_luksUUID_HELP},
|
||||
{"isLuks", (PyCFunction)CryptSetup_isLuks, METH_NOARGS, CryptSetup_isLuks_HELP},
|
||||
{"info", (PyCFunction)CryptSetup_Info, METH_NOARGS, CryptSetup_Info_HELP},
|
||||
{"info", (PyCFunction)CryptSetup_Info, METH_NOARGS, CryptSetup_Info_HELP},
|
||||
{"status", (PyCFunction)CryptSetup_Status, METH_NOARGS, CryptSetup_Status_HELP},
|
||||
|
||||
/* cryptsetup mgmt entrypoints */
|
||||
@@ -637,8 +696,7 @@ static PyMethodDef CryptSetup_methods[] = {
|
||||
};
|
||||
|
||||
static PyTypeObject CryptSetupType = {
|
||||
PyObject_HEAD_INIT(NULL)
|
||||
0, /*ob_size*/
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"pycryptsetup.CryptSetup", /*tp_name*/
|
||||
sizeof(CryptSetupObject), /*tp_basicsize*/
|
||||
0, /*tp_itemsize*/
|
||||
@@ -682,15 +740,14 @@ static PyMethodDef pycryptsetup_methods[] = {
|
||||
{NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
PyMODINIT_FUNC initpycryptsetup(void);
|
||||
PyMODINIT_FUNC initpycryptsetup(void)
|
||||
MOD_INIT(pycryptsetup)
|
||||
{
|
||||
PyObject *m;
|
||||
|
||||
if (PyType_Ready(&CryptSetupType) < 0)
|
||||
return;
|
||||
return MOD_ERROR_VAL;
|
||||
|
||||
m = Py_InitModule3("pycryptsetup", pycryptsetup_methods, "CryptSetup pythonized API.");
|
||||
MOD_DEF(m, "pycryptsetup", "CryptSetup pythonized API.", pycryptsetup_methods);
|
||||
Py_INCREF(&CryptSetupType);
|
||||
|
||||
PyModule_AddObject(m, "CryptSetup", (PyObject *)&CryptSetupType);
|
||||
@@ -710,4 +767,6 @@ PyMODINIT_FUNC initpycryptsetup(void)
|
||||
PyModule_AddIntConstant(m, "CRYPT_INACTIVE", CRYPT_INACTIVE);
|
||||
PyModule_AddIntConstant(m, "CRYPT_ACTIVE", CRYPT_ACTIVE);
|
||||
PyModule_AddIntConstant(m, "CRYPT_BUSY", CRYPT_BUSY);
|
||||
|
||||
return MOD_SUCCESS_VAL(m);
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ AM_CPPFLAGS = -include config.h \
|
||||
cryptsetup_SOURCES = \
|
||||
$(top_builddir)/lib/utils_crypt.c \
|
||||
$(top_builddir)/lib/utils_loop.c \
|
||||
$(top_builddir)/lib/utils_fips.c \
|
||||
utils_tools.c \
|
||||
utils_password.c \
|
||||
cryptsetup.c \
|
||||
@@ -21,8 +20,8 @@ cryptsetup_SOURCES = \
|
||||
cryptsetup_LDADD = \
|
||||
$(top_builddir)/lib/libcryptsetup.la \
|
||||
@POPT_LIBS@ \
|
||||
@FIPSCHECK_LIBS@ \
|
||||
@PWQUALITY_LIBS@
|
||||
@PWQUALITY_LIBS@ \
|
||||
@PASSWDQC_LIBS@
|
||||
|
||||
cryptsetup_CFLAGS = $(AM_CFLAGS) -Wall
|
||||
|
||||
|
||||
408
src/cryptsetup.c
408
src/cryptsetup.c
@@ -1,10 +1,10 @@
|
||||
/*
|
||||
* cryptsetup - setup cryptographic volumes for dm-crypt
|
||||
*
|
||||
* Copyright (C) 2004, Christophe Saout <christophe@saout.de>
|
||||
* Copyright (C) 2004, Jana Saout <jana@saout.de>
|
||||
* Copyright (C) 2004-2007, Clemens Fruhwirth <clemens@endorphin.org>
|
||||
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2009-2013, Milan Broz
|
||||
* Copyright (C) 2009-2015, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2009-2015, Milan Broz
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -57,14 +57,26 @@ static int opt_urandom = 0;
|
||||
static int opt_dump_master_key = 0;
|
||||
static int opt_shared = 0;
|
||||
static int opt_allow_discards = 0;
|
||||
static int opt_perf_same_cpu_crypt = 0;
|
||||
static int opt_perf_submit_from_crypt_cpus = 0;
|
||||
static int opt_test_passphrase = 0;
|
||||
static int opt_tcrypt_hidden = 0;
|
||||
static int opt_tcrypt_system = 0;
|
||||
static int opt_tcrypt_backup = 0;
|
||||
static int opt_veracrypt = 0;
|
||||
|
||||
static const char **action_argv;
|
||||
static int action_argc;
|
||||
static const char *null_action_argv[] = {NULL, NULL};
|
||||
|
||||
static const char *uuid_or_device_header(const char **data_device)
|
||||
{
|
||||
if (data_device)
|
||||
*data_device = opt_header_device ? action_argv[0] : NULL;
|
||||
|
||||
return uuid_or_device(opt_header_device ?: action_argv[0]);
|
||||
}
|
||||
|
||||
static int _verify_passphrase(int def)
|
||||
{
|
||||
/* Batch mode switch off verify - if not overrided by -y */
|
||||
@@ -83,6 +95,21 @@ static int _verify_passphrase(int def)
|
||||
return def;
|
||||
}
|
||||
|
||||
static void _set_activation_flags(uint32_t *flags)
|
||||
{
|
||||
if (opt_readonly)
|
||||
*flags |= CRYPT_ACTIVATE_READONLY;
|
||||
|
||||
if (opt_allow_discards)
|
||||
*flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS;
|
||||
|
||||
if (opt_perf_same_cpu_crypt)
|
||||
*flags |= CRYPT_ACTIVATE_SAME_CPU_CRYPT;
|
||||
|
||||
if (opt_perf_submit_from_crypt_cpus)
|
||||
*flags |= CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS;
|
||||
}
|
||||
|
||||
static int action_open_plain(void)
|
||||
{
|
||||
struct crypt_device *cd = NULL;
|
||||
@@ -94,22 +121,11 @@ static int action_open_plain(void)
|
||||
.size = opt_size,
|
||||
};
|
||||
char *password = NULL;
|
||||
size_t passwordLen;
|
||||
size_t passwordLen, key_size_max;
|
||||
size_t key_size = (opt_key_size ?: DEFAULT_PLAIN_KEYBITS) / 8;
|
||||
uint32_t activate_flags = 0;
|
||||
int r;
|
||||
|
||||
if (params.hash && !strcmp(params.hash, "plain"))
|
||||
params.hash = NULL;
|
||||
|
||||
/* FIXME: temporary hack */
|
||||
if (opt_key_file && strcmp(opt_key_file, "-"))
|
||||
params.hash = NULL;
|
||||
|
||||
if ((opt_keyfile_offset || opt_keyfile_size) && opt_key_file)
|
||||
log_std(_("Ignoring keyfile offset and size options, keyfile read "
|
||||
"size is always the same as encryption key size.\n"));
|
||||
|
||||
r = crypt_parse_name_and_mode(opt_cipher ?: DEFAULT_CIPHER(PLAIN),
|
||||
cipher, NULL, cipher_mode);
|
||||
if (r < 0) {
|
||||
@@ -117,6 +133,21 @@ static int action_open_plain(void)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* FIXME: temporary hack, no hashing for keyfiles in plain mode */
|
||||
if (opt_key_file && !tools_is_stdin(opt_key_file)) {
|
||||
params.hash = NULL;
|
||||
if (!opt_batch_mode && opt_hash)
|
||||
log_std(_("WARNING: The --hash parameter is being ignored "
|
||||
"in plain mode with keyfile specified.\n"));
|
||||
}
|
||||
|
||||
if (params.hash && !strcmp(params.hash, "plain"))
|
||||
params.hash = NULL;
|
||||
|
||||
if (!opt_batch_mode && !params.hash && opt_key_file && !tools_is_stdin(opt_key_file) && opt_keyfile_size)
|
||||
log_std(_("WARNING: The --keyfile-size option is being ignored, "
|
||||
"the read size is the same as the encryption key size.\n"));
|
||||
|
||||
if ((r = crypt_init(&cd, action_argv[0])))
|
||||
goto out;
|
||||
|
||||
@@ -132,28 +163,28 @@ static int action_open_plain(void)
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
if (opt_readonly)
|
||||
activate_flags |= CRYPT_ACTIVATE_READONLY;
|
||||
|
||||
if (opt_shared)
|
||||
activate_flags |= CRYPT_ACTIVATE_SHARED;
|
||||
|
||||
if (opt_allow_discards)
|
||||
activate_flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS;
|
||||
_set_activation_flags(&activate_flags);
|
||||
|
||||
if (opt_key_file)
|
||||
/* With hashing, read the whole keyfile */
|
||||
if (!tools_is_stdin(opt_key_file)) {
|
||||
/* If no hash, key is read directly, read size is always key_size
|
||||
* (possible opt_keyfile_size is ignored.
|
||||
* If hash is specified, opt_keyfile_size is applied.
|
||||
* The opt_keyfile_offset is applied always.
|
||||
*/
|
||||
key_size_max = params.hash ? (size_t)opt_keyfile_size : key_size;
|
||||
r = crypt_activate_by_keyfile_offset(cd, action_argv[1],
|
||||
CRYPT_ANY_SLOT, opt_key_file,
|
||||
params.hash ? 0 : key_size, 0,
|
||||
activate_flags);
|
||||
else {
|
||||
CRYPT_ANY_SLOT, opt_key_file, key_size_max,
|
||||
opt_keyfile_offset, activate_flags);
|
||||
} else {
|
||||
key_size_max = (opt_key_file && !params.hash) ? key_size : (size_t)opt_keyfile_size;
|
||||
r = tools_get_key(_("Enter passphrase: "),
|
||||
&password, &passwordLen,
|
||||
opt_keyfile_offset, opt_keyfile_size,
|
||||
NULL, opt_timeout,
|
||||
_verify_passphrase(0), 0,
|
||||
cd);
|
||||
opt_keyfile_offset, key_size_max,
|
||||
opt_key_file, opt_timeout,
|
||||
_verify_passphrase(0), 0, cd);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
@@ -184,11 +215,7 @@ static int action_open_loopaes(void)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (opt_readonly)
|
||||
activate_flags |= CRYPT_ACTIVATE_READONLY;
|
||||
|
||||
if (opt_allow_discards)
|
||||
activate_flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS;
|
||||
_set_activation_flags(&activate_flags);
|
||||
|
||||
if ((r = crypt_init(&cd, action_argv[0])))
|
||||
goto out;
|
||||
@@ -201,23 +228,68 @@ static int action_open_loopaes(void)
|
||||
|
||||
r = crypt_activate_by_keyfile_offset(cd, action_argv[1], CRYPT_ANY_SLOT,
|
||||
opt_key_file, opt_keyfile_size,
|
||||
opt_keyfile_size, activate_flags);
|
||||
opt_keyfile_offset, activate_flags);
|
||||
out:
|
||||
crypt_free(cd);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int tcrypt_load(struct crypt_device *cd, struct crypt_params_tcrypt *params)
|
||||
{
|
||||
int r, tries = opt_tries, eperm = 0;
|
||||
|
||||
do {
|
||||
/* TCRYPT header is encrypted, get passphrase now */
|
||||
r = tools_get_key(_("Enter passphrase: "),
|
||||
CONST_CAST(char**)¶ms->passphrase,
|
||||
¶ms->passphrase_size, 0, 0, NULL, opt_timeout,
|
||||
_verify_passphrase(0), 0, cd);
|
||||
if (r < 0)
|
||||
continue;
|
||||
|
||||
if (opt_tcrypt_hidden)
|
||||
params->flags |= CRYPT_TCRYPT_HIDDEN_HEADER;
|
||||
|
||||
if (opt_tcrypt_system)
|
||||
params->flags |= CRYPT_TCRYPT_SYSTEM_HEADER;
|
||||
|
||||
if (opt_tcrypt_backup)
|
||||
params->flags |= CRYPT_TCRYPT_BACKUP_HEADER;
|
||||
|
||||
r = crypt_load(cd, CRYPT_TCRYPT, params);
|
||||
|
||||
if (r == -EPERM) {
|
||||
log_err(_("No device header detected with this passphrase.\n"));
|
||||
eperm = 1;
|
||||
}
|
||||
|
||||
if (r < 0) {
|
||||
crypt_safe_free(CONST_CAST(char*)params->passphrase);
|
||||
params->passphrase = NULL;
|
||||
params->passphrase_size = 0;
|
||||
}
|
||||
check_signal(&r);
|
||||
} while (r == -EPERM && (--tries > 0));
|
||||
|
||||
/* Report wrong passphrase if at least one try failed */
|
||||
if (eperm && r == -EPIPE)
|
||||
r = -EPERM;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int action_open_tcrypt(void)
|
||||
{
|
||||
struct crypt_device *cd = NULL;
|
||||
struct crypt_params_tcrypt params = {
|
||||
.keyfiles = opt_keyfiles,
|
||||
.keyfiles_count = opt_keyfiles_count,
|
||||
.flags = CRYPT_TCRYPT_LEGACY_MODES,
|
||||
.flags = CRYPT_TCRYPT_LEGACY_MODES |
|
||||
(opt_veracrypt ? CRYPT_TCRYPT_VERA_MODES : 0),
|
||||
};
|
||||
const char *activated_name;
|
||||
uint32_t flags = 0;
|
||||
uint32_t activate_flags = 0;
|
||||
int r;
|
||||
|
||||
activated_name = opt_test_passphrase ? NULL : action_argv[1];
|
||||
@@ -225,33 +297,15 @@ static int action_open_tcrypt(void)
|
||||
if ((r = crypt_init(&cd, action_argv[0])))
|
||||
goto out;
|
||||
|
||||
/* TCRYPT header is encrypted, get passphrase now */
|
||||
r = tools_get_key(_("Enter passphrase: "),
|
||||
CONST_CAST(char**)¶ms.passphrase,
|
||||
¶ms.passphrase_size, 0, 0, NULL, opt_timeout,
|
||||
_verify_passphrase(0), 0, cd);
|
||||
r = tcrypt_load(cd, ¶ms);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
if (opt_tcrypt_hidden)
|
||||
params.flags |= CRYPT_TCRYPT_HIDDEN_HEADER;
|
||||
|
||||
if (opt_tcrypt_system)
|
||||
params.flags |= CRYPT_TCRYPT_SYSTEM_HEADER;
|
||||
|
||||
r = crypt_load(cd, CRYPT_TCRYPT, ¶ms);
|
||||
check_signal(&r);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
if (opt_readonly)
|
||||
flags |= CRYPT_ACTIVATE_READONLY;
|
||||
_set_activation_flags(&activate_flags);
|
||||
|
||||
if (activated_name)
|
||||
r = crypt_activate_by_volume_key(cd, activated_name, NULL, 0, flags);
|
||||
r = crypt_activate_by_volume_key(cd, activated_name, NULL, 0, activate_flags);
|
||||
out:
|
||||
if (r == -EPERM)
|
||||
log_err(_("No device header detected with this passphrase.\n"));
|
||||
crypt_free(cd);
|
||||
crypt_safe_free(CONST_CAST(char*)params.passphrase);
|
||||
return r;
|
||||
@@ -305,29 +359,15 @@ static int action_tcryptDump(void)
|
||||
struct crypt_params_tcrypt params = {
|
||||
.keyfiles = opt_keyfiles,
|
||||
.keyfiles_count = opt_keyfiles_count,
|
||||
.flags = CRYPT_TCRYPT_LEGACY_MODES,
|
||||
.flags = CRYPT_TCRYPT_LEGACY_MODES |
|
||||
(opt_veracrypt ? CRYPT_TCRYPT_VERA_MODES : 0),
|
||||
};
|
||||
int r;
|
||||
|
||||
if ((r = crypt_init(&cd, action_argv[0])))
|
||||
goto out;
|
||||
|
||||
/* TCRYPT header is encrypted, get passphrase now */
|
||||
r = tools_get_key(_("Enter passphrase: "),
|
||||
CONST_CAST(char**)¶ms.passphrase,
|
||||
¶ms.passphrase_size, 0, 0, NULL, opt_timeout,
|
||||
_verify_passphrase(0), 0, cd);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
if (opt_tcrypt_hidden)
|
||||
params.flags |= CRYPT_TCRYPT_HIDDEN_HEADER;
|
||||
|
||||
if (opt_tcrypt_system)
|
||||
params.flags |= CRYPT_TCRYPT_SYSTEM_HEADER;
|
||||
|
||||
r = crypt_load(cd, CRYPT_TCRYPT, ¶ms);
|
||||
check_signal(&r);
|
||||
r = tcrypt_load(cd, ¶ms);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
@@ -336,8 +376,6 @@ static int action_tcryptDump(void)
|
||||
else
|
||||
r = crypt_dump(cd);
|
||||
out:
|
||||
if (r == -EPERM)
|
||||
log_err(_("No device header detected with this passphrase.\n"));
|
||||
crypt_free(cd);
|
||||
crypt_safe_free(CONST_CAST(char*)params.passphrase);
|
||||
return r;
|
||||
@@ -404,10 +442,10 @@ static int action_status(void)
|
||||
ci == CRYPT_BUSY ? " and is in use" : "");
|
||||
|
||||
r = crypt_init_by_name_and_header(&cd, action_argv[0], opt_header_device);
|
||||
if (r < 0 || !crypt_get_type(cd))
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
log_std(" type: %s\n", crypt_get_type(cd));
|
||||
log_std(" type: %s\n", crypt_get_type(cd) ?: "n/a");
|
||||
|
||||
r = crypt_get_active_device(cd, action_argv[0], &cad);
|
||||
if (r < 0)
|
||||
@@ -428,8 +466,13 @@ static int action_status(void)
|
||||
log_std(" skipped: %" PRIu64 " sectors\n", cad.iv_offset);
|
||||
log_std(" mode: %s\n", cad.flags & CRYPT_ACTIVATE_READONLY ?
|
||||
"readonly" : "read/write");
|
||||
if (cad.flags & CRYPT_ACTIVATE_ALLOW_DISCARDS)
|
||||
log_std(" flags: discards\n");
|
||||
if (cad.flags & (CRYPT_ACTIVATE_ALLOW_DISCARDS|
|
||||
CRYPT_ACTIVATE_ALLOW_DISCARDS|
|
||||
CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS))
|
||||
log_std(" flags: %s%s%s\n",
|
||||
(cad.flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) ? "discards " : "",
|
||||
(cad.flags & CRYPT_ACTIVATE_SAME_CPU_CRYPT) ? "same_cpu_crypt " : "",
|
||||
(cad.flags & CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS) ? "submit_from_crypt_cpus" : "");
|
||||
}
|
||||
out:
|
||||
crypt_free(cd);
|
||||
@@ -448,8 +491,31 @@ static int action_benchmark_kdf(const char *hash)
|
||||
if (r < 0)
|
||||
log_std("PBKDF2-%-9s N/A\n", hash);
|
||||
else
|
||||
log_std("PBKDF2-%-9s %7" PRIu64 " iterations per second\n",
|
||||
hash, kdf_iters);
|
||||
log_std("PBKDF2-%-9s %7" PRIu64 " iterations per second for %d-bit key\n",
|
||||
hash, kdf_iters, DEFAULT_LUKS1_KEYBITS);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int benchmark_cipher_loop(const char *cipher, const char *cipher_mode,
|
||||
size_t volume_key_size, size_t iv_size,
|
||||
double *encryption_mbs, double *decryption_mbs)
|
||||
{
|
||||
int r, buffer_size = 1024 * 1024;
|
||||
|
||||
do {
|
||||
r = crypt_benchmark(NULL, cipher, cipher_mode,
|
||||
volume_key_size, iv_size, buffer_size,
|
||||
encryption_mbs, decryption_mbs);
|
||||
if (r == -ERANGE) {
|
||||
if (buffer_size < 1024 * 1024 * 65)
|
||||
buffer_size *= 2;
|
||||
else {
|
||||
log_err(_("Result of benchmark is not reliable.\n"));
|
||||
r = -ENOENT;
|
||||
}
|
||||
}
|
||||
} while (r == -ERANGE);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -482,7 +548,6 @@ static int action_benchmark(void)
|
||||
double enc_mbr = 0, dec_mbr = 0;
|
||||
int key_size = (opt_key_size ?: DEFAULT_PLAIN_KEYBITS);
|
||||
int iv_size = 16, skipped = 0;
|
||||
int buffer_size = 1024 * 1024;
|
||||
char *c;
|
||||
int i, r;
|
||||
|
||||
@@ -504,9 +569,12 @@ static int action_benchmark(void)
|
||||
strstr(cipher, "cast5"))
|
||||
iv_size = 8;
|
||||
|
||||
r = crypt_benchmark(NULL, cipher, cipher_mode,
|
||||
key_size / 8, iv_size, buffer_size,
|
||||
&enc_mbr, &dec_mbr);
|
||||
if (!strcmp(cipher_mode, "ecb"))
|
||||
iv_size = 0;
|
||||
|
||||
r = benchmark_cipher_loop(cipher, cipher_mode,
|
||||
key_size / 8, iv_size,
|
||||
&enc_mbr, &dec_mbr);
|
||||
if (!r) {
|
||||
log_std(N_("# Algorithm | Key | Encryption | Decryption\n"));
|
||||
log_std("%8s-%s %4db %6.1f MiB/s %6.1f MiB/s\n",
|
||||
@@ -521,9 +589,9 @@ static int action_benchmark(void)
|
||||
break;
|
||||
}
|
||||
for (i = 0; bciphers[i].cipher; i++) {
|
||||
r = crypt_benchmark(NULL, bciphers[i].cipher, bciphers[i].mode,
|
||||
r = benchmark_cipher_loop(bciphers[i].cipher, bciphers[i].mode,
|
||||
bciphers[i].key_size, bciphers[i].iv_size,
|
||||
buffer_size, &enc_mbr, &dec_mbr);
|
||||
&enc_mbr, &dec_mbr);
|
||||
check_signal(&r);
|
||||
if (r == -ENOTSUP || r == -EINTR)
|
||||
break;
|
||||
@@ -535,10 +603,10 @@ static int action_benchmark(void)
|
||||
snprintf(cipher, MAX_CIPHER_LEN, "%s-%s",
|
||||
bciphers[i].cipher, bciphers[i].mode);
|
||||
if (!r)
|
||||
log_std("%12s %4db %6.1f MiB/s %6.1f MiB/s\n",
|
||||
log_std("%12s %4zub %6.1f MiB/s %6.1f MiB/s\n",
|
||||
cipher, bciphers[i].key_size*8, enc_mbr, dec_mbr);
|
||||
else
|
||||
log_std("%12s %4db %13s %13s\n", cipher,
|
||||
log_std("%12s %4zub %13s %13s\n", cipher,
|
||||
bciphers[i].key_size*8, _("N/A"), _("N/A"));
|
||||
}
|
||||
if (skipped && skipped == i)
|
||||
@@ -640,6 +708,10 @@ static int action_luksFormat(void)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Never call pwquality if using null cipher */
|
||||
if (tools_is_cipher_null(cipher))
|
||||
opt_force_password = 1;
|
||||
|
||||
if ((r = crypt_init(&cd, header_device))) {
|
||||
if (opt_header_device)
|
||||
log_err(_("Cannot use %s as on-disk header.\n"), header_device);
|
||||
@@ -691,16 +763,10 @@ static int action_open_luks(void)
|
||||
struct crypt_device *cd = NULL;
|
||||
const char *data_device, *header_device, *activated_name;
|
||||
char *key = NULL;
|
||||
uint32_t flags = 0;
|
||||
uint32_t activate_flags = 0;
|
||||
int r, keysize;
|
||||
|
||||
if (opt_header_device) {
|
||||
header_device = uuid_or_device(opt_header_device);
|
||||
data_device = action_argv[0];
|
||||
} else {
|
||||
header_device = uuid_or_device(action_argv[0]);
|
||||
data_device = NULL;
|
||||
}
|
||||
header_device = uuid_or_device_header(&data_device);
|
||||
|
||||
activated_name = opt_test_passphrase ? NULL : action_argv[1];
|
||||
|
||||
@@ -727,11 +793,7 @@ static int action_open_luks(void)
|
||||
if (opt_iteration_time)
|
||||
crypt_set_iteration_time(cd, opt_iteration_time);
|
||||
|
||||
if (opt_readonly)
|
||||
flags |= CRYPT_ACTIVATE_READONLY;
|
||||
|
||||
if (opt_allow_discards)
|
||||
flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS;
|
||||
_set_activation_flags(&activate_flags);
|
||||
|
||||
if (opt_master_key_file) {
|
||||
keysize = crypt_get_volume_key_size(cd);
|
||||
@@ -739,15 +801,15 @@ static int action_open_luks(void)
|
||||
if (r < 0)
|
||||
goto out;
|
||||
r = crypt_activate_by_volume_key(cd, activated_name,
|
||||
key, keysize, flags);
|
||||
key, keysize, activate_flags);
|
||||
} else if (opt_key_file) {
|
||||
crypt_set_password_retry(cd, 1);
|
||||
r = crypt_activate_by_keyfile_offset(cd, activated_name,
|
||||
opt_key_slot, opt_key_file, opt_keyfile_size,
|
||||
opt_keyfile_offset, flags);
|
||||
opt_keyfile_offset, activate_flags);
|
||||
} else
|
||||
r = crypt_activate_by_passphrase(cd, activated_name,
|
||||
opt_key_slot, NULL, 0, flags);
|
||||
opt_key_slot, NULL, 0, activate_flags);
|
||||
out:
|
||||
crypt_safe_free(key);
|
||||
crypt_free(cd);
|
||||
@@ -804,7 +866,7 @@ static int action_luksKillSlot(void)
|
||||
struct crypt_device *cd = NULL;
|
||||
int r;
|
||||
|
||||
if ((r = crypt_init(&cd, uuid_or_device(action_argv[0]))))
|
||||
if ((r = crypt_init(&cd, uuid_or_device_header(NULL))))
|
||||
goto out;
|
||||
|
||||
crypt_set_confirm_callback(cd, yesDialog, NULL);
|
||||
@@ -847,7 +909,7 @@ static int action_luksRemoveKey(void)
|
||||
size_t passwordLen;
|
||||
int r;
|
||||
|
||||
if ((r = crypt_init(&cd, uuid_or_device(action_argv[0]))))
|
||||
if ((r = crypt_init(&cd, uuid_or_device_header(NULL))))
|
||||
goto out;
|
||||
|
||||
crypt_set_confirm_callback(cd, yesDialog, NULL);
|
||||
@@ -898,7 +960,7 @@ static int action_luksAddKey(void)
|
||||
size_t password_size = 0, password_new_size = 0;
|
||||
struct crypt_device *cd = NULL;
|
||||
|
||||
if ((r = crypt_init(&cd, uuid_or_device(action_argv[0]))))
|
||||
if ((r = crypt_init(&cd, uuid_or_device_header(NULL))))
|
||||
goto out;
|
||||
|
||||
crypt_set_confirm_callback(cd, yesDialog, NULL);
|
||||
@@ -906,6 +968,10 @@ static int action_luksAddKey(void)
|
||||
if ((r = crypt_load(cd, CRYPT_LUKS1, NULL)))
|
||||
goto out;
|
||||
|
||||
/* Never call pwquality if using null cipher */
|
||||
if (tools_is_cipher_null(crypt_get_cipher(cd)))
|
||||
opt_force_password = 1;
|
||||
|
||||
keysize = crypt_get_volume_key_size(cd);
|
||||
/* FIXME: lib cannot properly set verification for new/old passphrase */
|
||||
crypt_set_password_verify(cd, _verify_passphrase(0));
|
||||
@@ -917,16 +983,31 @@ static int action_luksAddKey(void)
|
||||
r = _read_mk(opt_master_key_file, &key, keysize);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
//FIXME: process keyfile arg
|
||||
r = crypt_keyslot_add_by_volume_key(cd, opt_key_slot,
|
||||
key, keysize, NULL, 0);
|
||||
} else if (opt_key_file || opt_new_key_file) {
|
||||
|
||||
r = crypt_volume_key_verify(cd, key, keysize);
|
||||
check_signal(&r);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
r = tools_get_key(_("Enter new passphrase for key slot: "),
|
||||
&password_new, &password_new_size,
|
||||
opt_new_keyfile_offset, opt_new_keyfile_size,
|
||||
opt_new_key_file, opt_timeout,
|
||||
_verify_passphrase(1), 1, cd);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
r = crypt_keyslot_add_by_volume_key(cd, opt_key_slot, key, keysize,
|
||||
password_new, password_new_size);
|
||||
} else if (opt_key_file && !tools_is_stdin(opt_key_file) &&
|
||||
opt_new_key_file && !tools_is_stdin(opt_new_key_file)) {
|
||||
r = crypt_keyslot_add_by_keyfile_offset(cd, opt_key_slot,
|
||||
opt_key_file, opt_keyfile_size, opt_keyfile_offset,
|
||||
opt_new_key_file, opt_new_keyfile_size, opt_new_keyfile_offset);
|
||||
} else {
|
||||
r = tools_get_key(_("Enter any existing passphrase: "),
|
||||
&password, &password_size, 0, 0, NULL,
|
||||
&password, &password_size,
|
||||
opt_keyfile_offset, opt_keyfile_size, opt_key_file,
|
||||
opt_timeout, _verify_passphrase(0), 0, cd);
|
||||
|
||||
if (r < 0)
|
||||
@@ -940,8 +1021,9 @@ static int action_luksAddKey(void)
|
||||
goto out;
|
||||
|
||||
r = tools_get_key(_("Enter new passphrase for key slot: "),
|
||||
&password_new, &password_new_size, 0, 0, NULL,
|
||||
opt_timeout, _verify_passphrase(0), 1, cd);
|
||||
&password_new, &password_new_size,
|
||||
opt_new_keyfile_offset, opt_new_keyfile_size, opt_new_key_file,
|
||||
opt_timeout, _verify_passphrase(1), opt_new_key_file ? 0 : 1, cd);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
@@ -965,12 +1047,16 @@ static int action_luksChangeKey(void)
|
||||
size_t password_size = 0, password_new_size = 0;
|
||||
int r;
|
||||
|
||||
if ((r = crypt_init(&cd, uuid_or_device(action_argv[0]))))
|
||||
if ((r = crypt_init(&cd, uuid_or_device_header(NULL))))
|
||||
goto out;
|
||||
|
||||
if ((r = crypt_load(cd, CRYPT_LUKS1, NULL)))
|
||||
goto out;
|
||||
|
||||
/* Never call pwquality if using null cipher */
|
||||
if (tools_is_cipher_null(crypt_get_cipher(cd)))
|
||||
opt_force_password = 1;
|
||||
|
||||
if (opt_iteration_time)
|
||||
crypt_set_iteration_time(cd, opt_iteration_time);
|
||||
|
||||
@@ -992,7 +1078,7 @@ static int action_luksChangeKey(void)
|
||||
&password_new, &password_new_size,
|
||||
opt_new_keyfile_offset, opt_new_keyfile_size,
|
||||
opt_new_key_file,
|
||||
opt_timeout, _verify_passphrase(0), 1, cd);
|
||||
opt_timeout, _verify_passphrase(1), 1, cd);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
@@ -1016,7 +1102,7 @@ static int action_isLuks(void)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if ((r = crypt_init(&cd, action_argv[0])))
|
||||
if ((r = crypt_init(&cd, uuid_or_device_header(NULL))))
|
||||
goto out;
|
||||
|
||||
crypt_set_log_callback(cd, quiet_log, NULL);
|
||||
@@ -1032,7 +1118,7 @@ static int action_luksUUID(void)
|
||||
const char *existing_uuid = NULL;
|
||||
int r;
|
||||
|
||||
if ((r = crypt_init(&cd, action_argv[0])))
|
||||
if ((r = crypt_init(&cd, uuid_or_device_header(NULL))))
|
||||
goto out;
|
||||
|
||||
crypt_set_confirm_callback(cd, yesDialog, NULL);
|
||||
@@ -1111,7 +1197,7 @@ static int action_luksDump(void)
|
||||
struct crypt_device *cd = NULL;
|
||||
int r;
|
||||
|
||||
if ((r = crypt_init(&cd, uuid_or_device(action_argv[0]))))
|
||||
if ((r = crypt_init(&cd, uuid_or_device_header(NULL))))
|
||||
goto out;
|
||||
|
||||
if ((r = crypt_load(cd, CRYPT_LUKS1, NULL)))
|
||||
@@ -1131,7 +1217,7 @@ static int action_luksSuspend(void)
|
||||
struct crypt_device *cd = NULL;
|
||||
int r;
|
||||
|
||||
r = crypt_init_by_name_and_header(&cd, action_argv[0], opt_header_device);
|
||||
r = crypt_init_by_name_and_header(&cd, action_argv[0], uuid_or_device(opt_header_device));
|
||||
if (!r)
|
||||
r = crypt_suspend(cd, action_argv[0]);
|
||||
|
||||
@@ -1144,7 +1230,7 @@ static int action_luksResume(void)
|
||||
struct crypt_device *cd = NULL;
|
||||
int r;
|
||||
|
||||
if ((r = crypt_init_by_name_and_header(&cd, action_argv[0], opt_header_device)))
|
||||
if ((r = crypt_init_by_name_and_header(&cd, action_argv[0], uuid_or_device(opt_header_device))))
|
||||
goto out;
|
||||
|
||||
crypt_set_timeout(cd, opt_timeout);
|
||||
@@ -1172,7 +1258,7 @@ static int action_luksBackup(void)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((r = crypt_init(&cd, uuid_or_device(action_argv[0]))))
|
||||
if ((r = crypt_init(&cd, uuid_or_device_header(NULL))))
|
||||
goto out;
|
||||
|
||||
crypt_set_confirm_callback(cd, yesDialog, NULL);
|
||||
@@ -1193,7 +1279,7 @@ static int action_luksRestore(void)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((r = crypt_init(&cd, action_argv[0])))
|
||||
if ((r = crypt_init(&cd, uuid_or_device_header(NULL))))
|
||||
goto out;
|
||||
|
||||
crypt_set_confirm_callback(cd, yesDialog, NULL);
|
||||
@@ -1233,6 +1319,47 @@ args:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int action_luksErase(void)
|
||||
{
|
||||
struct crypt_device *cd = NULL;
|
||||
crypt_keyslot_info ki;
|
||||
char *msg = NULL;
|
||||
int i, r;
|
||||
|
||||
if ((r = crypt_init(&cd, uuid_or_device_header(NULL))))
|
||||
goto out;
|
||||
|
||||
crypt_set_confirm_callback(cd, yesDialog, NULL);
|
||||
|
||||
if ((r = crypt_load(cd, CRYPT_LUKS1, NULL)))
|
||||
goto out;
|
||||
|
||||
if(asprintf(&msg, _("This operation will erase all keyslots on device %s.\n"
|
||||
"Device will become unusable after this operation."),
|
||||
uuid_or_device_header(NULL)) == -1) {
|
||||
r = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!yesDialog(msg, NULL)) {
|
||||
r = -EPERM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < crypt_keyslot_max(CRYPT_LUKS1); i++) {
|
||||
ki = crypt_keyslot_status(cd, i);
|
||||
if (ki == CRYPT_SLOT_ACTIVE || ki == CRYPT_SLOT_ACTIVE_LAST) {
|
||||
r = crypt_keyslot_destroy(cd, i);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
out:
|
||||
free(msg);
|
||||
crypt_free(cd);
|
||||
return r;
|
||||
}
|
||||
|
||||
static struct action_type {
|
||||
const char *type;
|
||||
int (*handler)(void);
|
||||
@@ -1247,6 +1374,7 @@ static struct action_type {
|
||||
{ "status", action_status, 1, 0, N_("<name>"), N_("show device status") },
|
||||
{ "benchmark", action_benchmark, 0, 0, N_("<name>"), N_("benchmark cipher") },
|
||||
{ "repair", action_luksRepair, 1, 1, N_("<device>"), N_("try to repair on-disk metadata") },
|
||||
{ "erase", action_luksErase , 1, 1, N_("<device>"), N_("erase all keyslots (remove encryption key)") },
|
||||
{ "luksFormat", action_luksFormat, 1, 1, N_("<device> [<new key file>]"), N_("formats a LUKS device") },
|
||||
{ "luksAddKey", action_luksAddKey, 1, 1, N_("<device> [<new key file>]"), N_("add key to LUKS device") },
|
||||
{ "luksRemoveKey",action_luksRemoveKey,1, 1, N_("<device> [<key file>]"), N_("removes supplied key or key file from LUKS device") },
|
||||
@@ -1390,8 +1518,12 @@ int main(int argc, const char **argv)
|
||||
{ "test-passphrase", '\0', POPT_ARG_NONE, &opt_test_passphrase, 0, N_("Do not activate device, just check passphrase."), NULL },
|
||||
{ "tcrypt-hidden", '\0', POPT_ARG_NONE, &opt_tcrypt_hidden, 0, N_("Use hidden header (hidden TCRYPT device)."), NULL },
|
||||
{ "tcrypt-system", '\0', POPT_ARG_NONE, &opt_tcrypt_system, 0, N_("Device is system TCRYPT drive (with bootloader)."), NULL },
|
||||
{ "tcrypt-backup", '\0', POPT_ARG_NONE, &opt_tcrypt_backup, 0, N_("Use backup (secondary) TCRYPT header."), NULL },
|
||||
{ "veracrypt", '\0', POPT_ARG_NONE, &opt_veracrypt, 0, N_("Scan also for VeraCrypt compatible device."), NULL },
|
||||
{ "type", 'M', POPT_ARG_STRING, &opt_type, 0, N_("Type of device metadata: luks, plain, loopaes, tcrypt."), NULL },
|
||||
{ "force-password", '\0', POPT_ARG_NONE, &opt_force_password, 0, N_("Disable password quality check (if enabled)."), NULL },
|
||||
{ "perf-same_cpu_crypt",'\0', POPT_ARG_NONE, &opt_perf_same_cpu_crypt, 0, N_("Use dm-crypt same_cpu_crypt performance compatibility option."), NULL },
|
||||
{ "perf-submit_from_crypt_cpus",'\0', POPT_ARG_NONE, &opt_perf_submit_from_crypt_cpus,0,N_("Use dm-crypt submit_from_crypt_cpus performance compatibility option."), NULL },
|
||||
POPT_TABLEEND
|
||||
};
|
||||
poptContext popt_context;
|
||||
@@ -1405,8 +1537,6 @@ int main(int argc, const char **argv)
|
||||
bindtextdomain(PACKAGE, LOCALEDIR);
|
||||
textdomain(PACKAGE);
|
||||
|
||||
crypt_fips_self_check(NULL);
|
||||
|
||||
popt_context = poptGetContext(PACKAGE, argc, argv, popt_options, 0);
|
||||
poptSetOtherOptionHelp(popt_context,
|
||||
_("[OPTION...] <action> <action-specific>"));
|
||||
@@ -1448,6 +1578,7 @@ int main(int argc, const char **argv)
|
||||
if (r < -1)
|
||||
usage(popt_context, EXIT_FAILURE, poptStrerror(r),
|
||||
poptBadOption(popt_context, POPT_BADOPTION_NOALIAS));
|
||||
|
||||
if (opt_version_mode) {
|
||||
log_std("%s %s\n", PACKAGE_NAME, PACKAGE_VERSION);
|
||||
poptFreeContext(popt_context);
|
||||
@@ -1490,12 +1621,17 @@ int main(int argc, const char **argv)
|
||||
} else if (!strcmp(aname, "tcryptOpen")) {
|
||||
aname = "open";
|
||||
opt_type = "tcrypt";
|
||||
} else if (!strcmp(aname, "tcryptDump")) {
|
||||
opt_type = "tcrypt";
|
||||
} else if (!strcmp(aname, "remove") ||
|
||||
!strcmp(aname, "plainClose") ||
|
||||
!strcmp(aname, "luksClose") ||
|
||||
!strcmp(aname, "loopaesClose") ||
|
||||
!strcmp(aname, "tcryptClose")) {
|
||||
aname = "close";
|
||||
} else if (!strcmp(aname, "luksErase")) {
|
||||
aname = "erase";
|
||||
opt_type = "luks";
|
||||
}
|
||||
|
||||
for(action = action_types; action->type; action++)
|
||||
@@ -1591,10 +1727,20 @@ int main(int argc, const char **argv)
|
||||
_("Option --offset is supported only for open of plain and loopaes devices.\n"),
|
||||
poptGetInvocationName(popt_context));
|
||||
|
||||
if ((opt_tcrypt_hidden || opt_tcrypt_system) && strcmp(aname, "tcryptDump") &&
|
||||
if ((opt_tcrypt_hidden || opt_tcrypt_system || opt_tcrypt_backup) && strcmp(aname, "tcryptDump") &&
|
||||
(strcmp(aname, "open") || strcmp(opt_type, "tcrypt")))
|
||||
usage(popt_context, EXIT_FAILURE,
|
||||
_("Option --tcrypt-hidden or --tcrypt-system is supported only for TCRYPT device.\n"),
|
||||
_("Option --tcrypt-hidden, --tcrypt-system or --tcrypt-backup is supported only for TCRYPT device.\n"),
|
||||
poptGetInvocationName(popt_context));
|
||||
|
||||
if (opt_tcrypt_hidden && opt_allow_discards)
|
||||
usage(popt_context, EXIT_FAILURE,
|
||||
_("Option --tcrypt-hidden cannot be combined with --allow-discards.\n"),
|
||||
poptGetInvocationName(popt_context));
|
||||
|
||||
if (opt_veracrypt && strcmp(opt_type, "tcrypt"))
|
||||
usage(popt_context, EXIT_FAILURE,
|
||||
_("Option --veracrypt is supported only for TCRYPT device type.\n"),
|
||||
poptGetInvocationName(popt_context));
|
||||
|
||||
if (opt_debug) {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
/*
|
||||
* cryptsetup - setup cryptographic volumes for dm-crypt
|
||||
*
|
||||
* Copyright (C) 2004, Christophe Saout <christophe@saout.de>
|
||||
* Copyright (C) 2004, Jana Saout <jana@saout.de>
|
||||
* Copyright (C) 2004-2007, Clemens Fruhwirth <clemens@endorphin.org>
|
||||
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2009-2013, Milan Broz
|
||||
* Copyright (C) 2009-2014, Milan Broz
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -57,7 +57,7 @@ extern int opt_force_password;
|
||||
|
||||
/* Common tools */
|
||||
void clogger(struct crypt_device *cd, int level, const char *file, int line,
|
||||
const char *format, ...);
|
||||
const char *format, ...) __attribute__ ((format (printf, 5, 6)));
|
||||
void tool_log(int level, const char *msg, void *usrptr __attribute__((unused)));
|
||||
void quiet_log(int level, const char *msg, void *usrptr);
|
||||
|
||||
@@ -81,6 +81,9 @@ int tools_get_key(const char *prompt,
|
||||
const char *key_file,
|
||||
int timeout, int verify, int pwquality,
|
||||
struct crypt_device *cd);
|
||||
int tools_is_stdin(const char *key_file);
|
||||
int tools_string_to_size(struct crypt_device *cd, const char *s, uint64_t *size);
|
||||
int tools_is_cipher_null(const char *cipher);
|
||||
|
||||
/* Log */
|
||||
#define log_dbg(x...) clogger(NULL, CRYPT_LOG_DEBUG, __FILE__, __LINE__, x)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* cryptsetup-reencrypt - crypt utility for offline re-encryption
|
||||
*
|
||||
* Copyright (C) 2012, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2012-2013, Milan Broz All rights reserved.
|
||||
* Copyright (C) 2012-2015, Milan Broz All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -47,6 +47,8 @@ static int opt_tries = 3;
|
||||
static int opt_key_slot = CRYPT_ANY_SLOT;
|
||||
static int opt_key_size = 0;
|
||||
static int opt_new = 0;
|
||||
static int opt_keep_key = 0;
|
||||
static int opt_decrypt = 0;
|
||||
|
||||
static const char *opt_reduce_size_str = NULL;
|
||||
static uint64_t opt_reduce_size = 0;
|
||||
@@ -61,12 +63,14 @@ struct reenc_ctx {
|
||||
char *device;
|
||||
char *device_uuid;
|
||||
uint64_t device_size; /* overrided by parameter */
|
||||
uint64_t device_size_real;
|
||||
uint64_t device_size_new_real;
|
||||
uint64_t device_size_org_real;
|
||||
uint64_t device_offset;
|
||||
uint64_t device_shift;
|
||||
|
||||
int in_progress:1;
|
||||
enum { FORWARD = 0, BACKWARD = 1 } reencrypt_direction;
|
||||
enum { REENCRYPT = 0, ENCRYPT = 1, DECRYPT = 2 } reencrypt_mode;
|
||||
|
||||
char header_file_org[PATH_MAX];
|
||||
char header_file_new[PATH_MAX];
|
||||
@@ -75,7 +79,7 @@ struct reenc_ctx {
|
||||
char crypt_path_org[PATH_MAX];
|
||||
char crypt_path_new[PATH_MAX];
|
||||
int log_fd;
|
||||
char *log_buf;
|
||||
char log_buf[SECTOR_SIZE];
|
||||
|
||||
struct {
|
||||
char *password;
|
||||
@@ -122,6 +126,12 @@ static int alignment(int fd)
|
||||
return alignment;
|
||||
}
|
||||
|
||||
static size_t pagesize(void)
|
||||
{
|
||||
long r = sysconf(_SC_PAGESIZE);
|
||||
return r < 0 ? 4096 : (size_t)r;
|
||||
}
|
||||
|
||||
/* Depends on the first two fields of LUKS1 header format, magic and version */
|
||||
static int device_check(struct reenc_ctx *rc, header_magic set_magic)
|
||||
{
|
||||
@@ -129,6 +139,7 @@ static int device_check(struct reenc_ctx *rc, header_magic set_magic)
|
||||
int r, devfd;
|
||||
ssize_t s;
|
||||
uint16_t version;
|
||||
size_t buf_size = pagesize();
|
||||
|
||||
devfd = open(rc->device, O_RDWR | O_EXCL | O_DIRECT);
|
||||
if (devfd == -1) {
|
||||
@@ -146,14 +157,14 @@ static int device_check(struct reenc_ctx *rc, header_magic set_magic)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (posix_memalign((void *)&buf, alignment(devfd), SECTOR_SIZE)) {
|
||||
if (posix_memalign((void *)&buf, alignment(devfd), buf_size)) {
|
||||
log_err(_("Allocation of aligned memory failed.\n"));
|
||||
r = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
s = read(devfd, buf, SECTOR_SIZE);
|
||||
if (s < 0 || s != SECTOR_SIZE) {
|
||||
s = read(devfd, buf, buf_size);
|
||||
if (s < 0 || s != (ssize_t)buf_size) {
|
||||
log_err(_("Cannot read device %s.\n"), rc->device);
|
||||
r = -EIO;
|
||||
goto out;
|
||||
@@ -184,8 +195,8 @@ static int device_check(struct reenc_ctx *rc, header_magic set_magic)
|
||||
if (!r) {
|
||||
if (lseek(devfd, 0, SEEK_SET) == -1)
|
||||
goto out;
|
||||
s = write(devfd, buf, SECTOR_SIZE);
|
||||
if (s < 0 || s != SECTOR_SIZE) {
|
||||
s = write(devfd, buf, buf_size);
|
||||
if (s < 0 || s != (ssize_t)buf_size) {
|
||||
log_err(_("Cannot write device %s.\n"), rc->device);
|
||||
r = -EIO;
|
||||
}
|
||||
@@ -193,7 +204,7 @@ static int device_check(struct reenc_ctx *rc, header_magic set_magic)
|
||||
log_dbg("LUKS signature check failed for %s.", rc->device);
|
||||
out:
|
||||
if (buf)
|
||||
memset(buf, 0, SECTOR_SIZE);
|
||||
memset(buf, 0, buf_size);
|
||||
free(buf);
|
||||
close(devfd);
|
||||
return r;
|
||||
@@ -257,9 +268,9 @@ static int write_log(struct reenc_ctx *rc)
|
||||
|
||||
memset(rc->log_buf, 0, SECTOR_SIZE);
|
||||
snprintf(rc->log_buf, SECTOR_SIZE, "# LUKS reencryption log, DO NOT EDIT OR DELETE.\n"
|
||||
"version = %d\nUUID = %s\ndirection = %d\n"
|
||||
"version = %d\nUUID = %s\ndirection = %d\nmode = %d\n"
|
||||
"offset = %" PRIu64 "\nshift = %" PRIu64 "\n# EOF\n",
|
||||
1, rc->device_uuid, rc->reencrypt_direction,
|
||||
2, rc->device_uuid, rc->reencrypt_direction, rc->reencrypt_mode,
|
||||
rc->device_offset, rc->device_shift);
|
||||
|
||||
if (lseek(rc->log_fd, 0, SEEK_SET) == -1)
|
||||
@@ -285,7 +296,7 @@ static int parse_line_log(struct reenc_ctx *rc, const char *line)
|
||||
return 0;
|
||||
|
||||
if (sscanf(line, "version = %d", &i) == 1) {
|
||||
if (i != 1) {
|
||||
if (i < 1 || i > 2) {
|
||||
log_dbg("Log: Unexpected version = %i", i);
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -303,6 +314,13 @@ static int parse_line_log(struct reenc_ctx *rc, const char *line)
|
||||
} else if (sscanf(line, "shift = %" PRIu64, &u64) == 1) {
|
||||
log_dbg("Log: shift = %" PRIu64, u64);
|
||||
rc->device_shift = u64;
|
||||
} else if (sscanf(line, "mode = %d", &i) == 1) { /* added in v2 */
|
||||
log_dbg("Log: mode = %i", i);
|
||||
rc->reencrypt_mode = i;
|
||||
if (rc->reencrypt_mode != REENCRYPT &&
|
||||
rc->reencrypt_mode != ENCRYPT &&
|
||||
rc->reencrypt_mode != DECRYPT)
|
||||
return -EINVAL;
|
||||
} else
|
||||
return -EINVAL;
|
||||
|
||||
@@ -343,13 +361,11 @@ static void close_log(struct reenc_ctx *rc)
|
||||
log_dbg("Closing LUKS reencryption log file %s.", rc->log_file);
|
||||
if (rc->log_fd != -1)
|
||||
close(rc->log_fd);
|
||||
free(rc->log_buf);
|
||||
rc->log_buf = NULL;
|
||||
}
|
||||
|
||||
static int open_log(struct reenc_ctx *rc)
|
||||
{
|
||||
int flags = opt_directio ? O_DIRECT : 0;
|
||||
int flags = opt_fsync ? O_SYNC : 0;
|
||||
|
||||
rc->log_fd = open(rc->log_file, O_RDWR|O_EXCL|O_CREAT|flags, S_IRUSR|S_IWUSR);
|
||||
if (rc->log_fd != -1) {
|
||||
@@ -363,12 +379,6 @@ static int open_log(struct reenc_ctx *rc)
|
||||
if (rc->log_fd == -1)
|
||||
return -EINVAL;
|
||||
|
||||
if (posix_memalign((void *)&rc->log_buf, alignment(rc->log_fd), SECTOR_SIZE)) {
|
||||
log_err(_("Allocation of aligned memory failed.\n"));
|
||||
close_log(rc);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (!rc->in_progress && write_log(rc) < 0) {
|
||||
close_log(rc);
|
||||
return -EIO;
|
||||
@@ -381,10 +391,31 @@ static int open_log(struct reenc_ctx *rc)
|
||||
static int activate_luks_headers(struct reenc_ctx *rc)
|
||||
{
|
||||
struct crypt_device *cd = NULL, *cd_new = NULL;
|
||||
const char *pwd_old, *pwd_new, pwd_empty[] = "";
|
||||
size_t pwd_old_len, pwd_new_len;
|
||||
int r;
|
||||
|
||||
log_dbg("Activating LUKS devices from headers.");
|
||||
|
||||
/* Never use real password for empty header processing */
|
||||
if (rc->reencrypt_mode == REENCRYPT) {
|
||||
pwd_old = rc->p[rc->keyslot].password;
|
||||
pwd_old_len = rc->p[rc->keyslot].passwordLen;
|
||||
pwd_new = pwd_old;
|
||||
pwd_new_len = pwd_old_len;
|
||||
} else if (rc->reencrypt_mode == DECRYPT) {
|
||||
pwd_old = rc->p[rc->keyslot].password;
|
||||
pwd_old_len = rc->p[rc->keyslot].passwordLen;
|
||||
pwd_new = pwd_empty;
|
||||
pwd_new_len = 0;
|
||||
} else if (rc->reencrypt_mode == ENCRYPT) {
|
||||
pwd_old = pwd_empty;
|
||||
pwd_old_len = 0;
|
||||
pwd_new = rc->p[rc->keyslot].password;
|
||||
pwd_new_len = rc->p[rc->keyslot].passwordLen;
|
||||
} else
|
||||
return -EINVAL;
|
||||
|
||||
if ((r = crypt_init(&cd, rc->header_file_org)) ||
|
||||
(r = crypt_load(cd, CRYPT_LUKS1, NULL)) ||
|
||||
(r = crypt_set_data_device(cd, rc->device)))
|
||||
@@ -392,7 +423,7 @@ static int activate_luks_headers(struct reenc_ctx *rc)
|
||||
|
||||
log_verbose(_("Activating temporary device using old LUKS header.\n"));
|
||||
if ((r = crypt_activate_by_passphrase(cd, rc->header_file_org,
|
||||
opt_key_slot, rc->p[rc->keyslot].password, rc->p[rc->keyslot].passwordLen,
|
||||
opt_key_slot, pwd_old, pwd_old_len,
|
||||
CRYPT_ACTIVATE_READONLY|CRYPT_ACTIVATE_PRIVATE)) < 0)
|
||||
goto out;
|
||||
|
||||
@@ -403,7 +434,7 @@ static int activate_luks_headers(struct reenc_ctx *rc)
|
||||
|
||||
log_verbose(_("Activating temporary device using new LUKS header.\n"));
|
||||
if ((r = crypt_activate_by_passphrase(cd_new, rc->header_file_new,
|
||||
opt_key_slot, rc->p[rc->keyslot].password, rc->p[rc->keyslot].passwordLen,
|
||||
opt_key_slot, pwd_new, pwd_new_len,
|
||||
CRYPT_ACTIVATE_SHARED|CRYPT_ACTIVATE_PRIVATE)) < 0)
|
||||
goto out;
|
||||
r = 0;
|
||||
@@ -417,7 +448,8 @@ out:
|
||||
|
||||
static int create_new_header(struct reenc_ctx *rc, const char *cipher,
|
||||
const char *cipher_mode, const char *uuid,
|
||||
int key_size, struct crypt_params_luks1 *params)
|
||||
const char *key, int key_size,
|
||||
struct crypt_params_luks1 *params)
|
||||
{
|
||||
struct crypt_device *cd_new = NULL;
|
||||
int i, r;
|
||||
@@ -434,7 +466,7 @@ static int create_new_header(struct reenc_ctx *rc, const char *cipher,
|
||||
crypt_set_iteration_time(cd_new, opt_iteration_time);
|
||||
|
||||
if ((r = crypt_format(cd_new, CRYPT_LUKS1, cipher, cipher_mode,
|
||||
uuid, NULL, key_size, params)))
|
||||
uuid, key, key_size, params)))
|
||||
goto out;
|
||||
log_verbose(_("New LUKS header for device %s created.\n"), rc->device);
|
||||
|
||||
@@ -457,6 +489,8 @@ static int backup_luks_headers(struct reenc_ctx *rc)
|
||||
struct crypt_device *cd = NULL;
|
||||
struct crypt_params_luks1 params = {0};
|
||||
char cipher [MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN];
|
||||
char *old_key = NULL;
|
||||
size_t old_key_size;
|
||||
int r;
|
||||
|
||||
log_dbg("Creating LUKS header backup for device %s.", rc->device);
|
||||
@@ -470,6 +504,10 @@ static int backup_luks_headers(struct reenc_ctx *rc)
|
||||
goto out;
|
||||
log_verbose(_("LUKS header backup of device %s created.\n"), rc->device);
|
||||
|
||||
/* For decrypt, new header will be fake one, so we are done here. */
|
||||
if (rc->reencrypt_mode == DECRYPT)
|
||||
goto out;
|
||||
|
||||
if ((r = create_empty_header(rc->header_file_new, rc->header_file_org,
|
||||
crypt_get_data_offset(cd))))
|
||||
goto out;
|
||||
@@ -487,14 +525,30 @@ static int backup_luks_headers(struct reenc_ctx *rc)
|
||||
}
|
||||
}
|
||||
|
||||
if (opt_keep_key) {
|
||||
log_dbg("Keeping key from old header.");
|
||||
old_key_size = crypt_get_volume_key_size(cd);
|
||||
old_key = crypt_safe_alloc(old_key_size);
|
||||
if (!old_key) {
|
||||
r = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
r = crypt_volume_key_get(cd, CRYPT_ANY_SLOT, old_key, &old_key_size,
|
||||
rc->p[rc->keyslot].password, rc->p[rc->keyslot].passwordLen);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
r = create_new_header(rc,
|
||||
opt_cipher ? cipher : crypt_get_cipher(cd),
|
||||
opt_cipher ? cipher_mode : crypt_get_cipher_mode(cd),
|
||||
crypt_get_uuid(cd),
|
||||
old_key,
|
||||
opt_key_size ? opt_key_size / 8 : crypt_get_volume_key_size(cd),
|
||||
¶ms);
|
||||
out:
|
||||
crypt_free(cd);
|
||||
crypt_safe_free(old_key);
|
||||
if (r)
|
||||
log_err(_("Creation of LUKS backup headers failed.\n"));
|
||||
return r;
|
||||
@@ -506,10 +560,13 @@ static int backup_fake_header(struct reenc_ctx *rc)
|
||||
struct crypt_device *cd_new = NULL;
|
||||
struct crypt_params_luks1 params = {0};
|
||||
char cipher [MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN];
|
||||
|
||||
const char *header_file_fake;
|
||||
int r;
|
||||
|
||||
log_dbg("Creating fake (cipher_null) header for original device.");
|
||||
log_dbg("Creating fake (cipher_null) header for %s device.",
|
||||
(rc->reencrypt_mode == DECRYPT) ? "new" : "original");
|
||||
|
||||
header_file_fake = (rc->reencrypt_mode == DECRYPT) ? rc->header_file_new : rc->header_file_org;
|
||||
|
||||
if (!opt_key_size)
|
||||
opt_key_size = DEFAULT_LUKS1_KEYBITS;
|
||||
@@ -522,7 +579,7 @@ static int backup_fake_header(struct reenc_ctx *rc)
|
||||
}
|
||||
}
|
||||
|
||||
r = create_empty_header(rc->header_file_org, NULL, 0);
|
||||
r = create_empty_header(header_file_fake, NULL, MAX_BCK_SECTORS);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -530,7 +587,7 @@ static int backup_fake_header(struct reenc_ctx *rc)
|
||||
params.data_alignment = 0;
|
||||
params.data_device = rc->device;
|
||||
|
||||
r = crypt_init(&cd_new, rc->header_file_org);
|
||||
r = crypt_init(&cd_new, header_file_fake);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -539,11 +596,15 @@ static int backup_fake_header(struct reenc_ctx *rc)
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
r = crypt_keyslot_add_by_volume_key(cd_new, 0, NULL, 0,
|
||||
rc->p[0].password, rc->p[0].passwordLen);
|
||||
r = crypt_keyslot_add_by_volume_key(cd_new, rc->keyslot, NULL, 0,
|
||||
rc->p[rc->keyslot].password, rc->p[rc->keyslot].passwordLen);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
/* The real header is backup header created in backup_luks_headers() */
|
||||
if (rc->reencrypt_mode == DECRYPT)
|
||||
goto out;
|
||||
|
||||
r = create_empty_header(rc->header_file_new, rc->header_file_org, 0);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
@@ -552,7 +613,7 @@ static int backup_fake_header(struct reenc_ctx *rc)
|
||||
r = create_new_header(rc,
|
||||
opt_cipher ? cipher : DEFAULT_LUKS1_CIPHER,
|
||||
opt_cipher ? cipher_mode : DEFAULT_LUKS1_MODE,
|
||||
NULL,
|
||||
NULL, NULL,
|
||||
(opt_key_size ? opt_key_size : DEFAULT_LUKS1_KEYBITS) / 8,
|
||||
¶ms);
|
||||
out:
|
||||
@@ -633,6 +694,29 @@ static void print_progress(struct reenc_ctx *rc, uint64_t bytes, int final)
|
||||
final ? "\n" :"");
|
||||
}
|
||||
|
||||
static ssize_t read_buf(int fd, void *buf, size_t count)
|
||||
{
|
||||
size_t read_size = 0;
|
||||
ssize_t s;
|
||||
|
||||
do {
|
||||
/* This expects that partial read is aligned in buffer */
|
||||
s = read(fd, buf, count - read_size);
|
||||
if (s == -1 && errno != EINTR)
|
||||
return s;
|
||||
if (s == 0)
|
||||
return (ssize_t)read_size;
|
||||
if (s > 0) {
|
||||
if (s != (ssize_t)count)
|
||||
log_dbg("Partial read %zd / %zu.", s, count);
|
||||
read_size += (size_t)s;
|
||||
buf = (uint8_t*)buf + s;
|
||||
}
|
||||
} while (read_size != count);
|
||||
|
||||
return (ssize_t)count;
|
||||
}
|
||||
|
||||
static int copy_data_forward(struct reenc_ctx *rc, int fd_old, int fd_new,
|
||||
size_t block_size, void *buf, uint64_t *bytes)
|
||||
{
|
||||
@@ -652,11 +736,11 @@ static int copy_data_forward(struct reenc_ctx *rc, int fd_old, int fd_new,
|
||||
return -EIO;
|
||||
|
||||
while (!quit && rc->device_offset < rc->device_size) {
|
||||
s1 = read(fd_old, buf, block_size);
|
||||
s1 = read_buf(fd_old, buf, block_size);
|
||||
if (s1 < 0 || ((size_t)s1 != block_size &&
|
||||
(rc->device_offset + s1) != rc->device_size)) {
|
||||
log_dbg("Read error, expecting %d, got %d.",
|
||||
(int)block_size, (int)s1);
|
||||
log_dbg("Read error, expecting %zu, got %zd.",
|
||||
block_size, s1);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@@ -666,8 +750,8 @@ static int copy_data_forward(struct reenc_ctx *rc, int fd_old, int fd_new,
|
||||
|
||||
s2 = write(fd_new, buf, s1);
|
||||
if (s2 < 0) {
|
||||
log_dbg("Write error, expecting %d, got %d.",
|
||||
(int)block_size, (int)s2);
|
||||
log_dbg("Write error, expecting %zu, got %zd.",
|
||||
block_size, s2);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@@ -722,17 +806,17 @@ static int copy_data_backward(struct reenc_ctx *rc, int fd_old, int fd_new,
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
s1 = read(fd_old, buf, working_block);
|
||||
s1 = read_buf(fd_old, buf, working_block);
|
||||
if (s1 < 0 || (s1 != working_block)) {
|
||||
log_dbg("Read error, expecting %d, got %d.",
|
||||
(int)block_size, (int)s1);
|
||||
log_dbg("Read error, expecting %zu, got %zd.",
|
||||
block_size, s1);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
s2 = write(fd_new, buf, working_block);
|
||||
if (s2 < 0) {
|
||||
log_dbg("Write error, expecting %d, got %d.",
|
||||
(int)block_size, (int)s2);
|
||||
log_dbg("Write error, expecting %zu, got %zd.",
|
||||
block_size, s2);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@@ -752,6 +836,41 @@ static int copy_data_backward(struct reenc_ctx *rc, int fd_old, int fd_new,
|
||||
return quit ? -EAGAIN : 0;
|
||||
}
|
||||
|
||||
static void zero_rest_of_device(int fd, size_t block_size, void *buf,
|
||||
uint64_t *bytes, uint64_t offset)
|
||||
{
|
||||
ssize_t s1, s2;
|
||||
|
||||
log_dbg("Zeroing rest of device.");
|
||||
|
||||
if (lseek64(fd, offset, SEEK_SET) < 0) {
|
||||
log_dbg(_("Cannot seek to device offset.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
memset(buf, 0, block_size);
|
||||
s1 = block_size;
|
||||
|
||||
while (!quit && *bytes) {
|
||||
if (*bytes < (uint64_t)s1)
|
||||
s1 = *bytes;
|
||||
|
||||
s2 = write(fd, buf, s1);
|
||||
if (s2 < 0) {
|
||||
log_dbg("Write error, expecting %zu, got %zd.",
|
||||
block_size, s2);
|
||||
return;
|
||||
}
|
||||
|
||||
if (opt_fsync && fsync(fd) < 0) {
|
||||
log_dbg("Write error, fsync.");
|
||||
return;
|
||||
}
|
||||
|
||||
*bytes -= s2;
|
||||
}
|
||||
}
|
||||
|
||||
static int copy_data(struct reenc_ctx *rc)
|
||||
{
|
||||
size_t block_size = opt_bsize * 1024 * 1024;
|
||||
@@ -764,23 +883,32 @@ static int copy_data(struct reenc_ctx *rc)
|
||||
|
||||
fd_old = open(rc->crypt_path_org, O_RDONLY | (opt_directio ? O_DIRECT : 0));
|
||||
if (fd_old == -1) {
|
||||
log_err(_("Cannot open temporary LUKS header file.\n"));
|
||||
log_err(_("Cannot open temporary LUKS device.\n"));
|
||||
goto out;
|
||||
}
|
||||
|
||||
fd_new = open(rc->crypt_path_new, O_WRONLY | (opt_directio ? O_DIRECT : 0));
|
||||
if (fd_new == -1) {
|
||||
log_err(_("Cannot open temporary LUKS header file.\n"));
|
||||
log_err(_("Cannot open temporary LUKS device.\n"));
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Check size */
|
||||
if (ioctl(fd_new, BLKGETSIZE64, &rc->device_size_real) < 0) {
|
||||
if (ioctl(fd_old, BLKGETSIZE64, &rc->device_size_org_real) < 0) {
|
||||
log_err(_("Cannot get device size.\n"));
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc->device_size = opt_device_size ?: rc->device_size_real;
|
||||
if (ioctl(fd_new, BLKGETSIZE64, &rc->device_size_new_real) < 0) {
|
||||
log_err(_("Cannot get device size.\n"));
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (opt_device_size)
|
||||
rc->device_size = opt_device_size;
|
||||
else if (rc->reencrypt_mode == DECRYPT)
|
||||
rc->device_size = rc->device_size_org_real;
|
||||
else
|
||||
rc->device_size = rc->device_size_new_real;
|
||||
|
||||
if (posix_memalign((void *)&buf, alignment(fd_new), block_size)) {
|
||||
log_err(_("Allocation of aligned memory failed.\n"));
|
||||
@@ -796,9 +924,18 @@ static int copy_data(struct reenc_ctx *rc)
|
||||
else
|
||||
r = copy_data_backward(rc, fd_old, fd_new, block_size, buf, &bytes);
|
||||
|
||||
set_int_block(1);
|
||||
print_progress(rc, bytes, 1);
|
||||
|
||||
/* Zero (wipe) rest of now plain-only device when decrypting.
|
||||
* (To not leave any sign of encryption here.) */
|
||||
if (!r && rc->reencrypt_mode == DECRYPT &&
|
||||
rc->device_size_new_real > rc->device_size_org_real) {
|
||||
bytes = rc->device_size_new_real - rc->device_size_org_real;
|
||||
zero_rest_of_device(fd_new, block_size, buf, &bytes, rc->device_size_org_real);
|
||||
}
|
||||
|
||||
set_int_block(1);
|
||||
|
||||
if (r == -EAGAIN)
|
||||
log_err(_("Interrupted by a signal.\n"));
|
||||
else if (r < 0)
|
||||
@@ -844,15 +981,14 @@ static int initialize_uuid(struct reenc_ctx *rc)
|
||||
static int init_passphrase1(struct reenc_ctx *rc, struct crypt_device *cd,
|
||||
const char *msg, int slot_to_check, int check)
|
||||
{
|
||||
int r = -EINVAL, slot, retry_count;
|
||||
|
||||
slot = (slot_to_check == CRYPT_ANY_SLOT) ? 0 : slot_to_check;
|
||||
char *password;
|
||||
int r = -EINVAL, retry_count;
|
||||
size_t passwordLen;
|
||||
|
||||
retry_count = opt_tries ?: 1;
|
||||
while (retry_count--) {
|
||||
set_int_handler(0);
|
||||
r = crypt_get_key(msg, &rc->p[slot].password,
|
||||
&rc->p[slot].passwordLen,
|
||||
r = crypt_get_key(msg, &password, &passwordLen,
|
||||
0, 0, NULL /*opt_key_file*/,
|
||||
0, 0, cd);
|
||||
if (r < 0)
|
||||
@@ -864,42 +1000,49 @@ static int init_passphrase1(struct reenc_ctx *rc, struct crypt_device *cd,
|
||||
set_int_block(1);
|
||||
if (check)
|
||||
r = crypt_activate_by_passphrase(cd, NULL, slot_to_check,
|
||||
rc->p[slot].password, rc->p[slot].passwordLen, 0);
|
||||
password, passwordLen, 0);
|
||||
else
|
||||
r = slot;
|
||||
r = (slot_to_check == CRYPT_ANY_SLOT) ? 0 : slot_to_check;
|
||||
|
||||
if (r < 0) {
|
||||
crypt_safe_free(rc->p[slot].password);
|
||||
rc->p[slot].password = NULL;
|
||||
rc->p[slot].passwordLen = 0;
|
||||
crypt_safe_free(password);
|
||||
password = NULL;
|
||||
passwordLen = 0;
|
||||
}
|
||||
if (r < 0 && r != -EPERM)
|
||||
return r;
|
||||
if (r >= 0) {
|
||||
rc->keyslot = slot;
|
||||
rc->keyslot = r;
|
||||
rc->p[r].password = password;
|
||||
rc->p[r].passwordLen = passwordLen;
|
||||
break;
|
||||
}
|
||||
log_err(_("No key available with this passphrase.\n"));
|
||||
}
|
||||
|
||||
password = NULL;
|
||||
passwordLen = 0;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int init_keyfile(struct reenc_ctx *rc, struct crypt_device *cd, int slot_check)
|
||||
{
|
||||
int r, slot;
|
||||
char *password;
|
||||
int r;
|
||||
size_t passwordLen;
|
||||
|
||||
slot = (slot_check == CRYPT_ANY_SLOT) ? 0 : slot_check;
|
||||
r = crypt_get_key(NULL, &rc->p[slot].password, &rc->p[slot].passwordLen,
|
||||
opt_keyfile_offset, opt_keyfile_size, opt_key_file, 0, 0, cd);
|
||||
r = crypt_get_key(NULL, &password, &passwordLen, opt_keyfile_offset,
|
||||
opt_keyfile_size, opt_key_file, 0, 0, cd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = crypt_activate_by_passphrase(cd, NULL, slot_check,
|
||||
rc->p[slot].password, rc->p[slot].passwordLen, 0);
|
||||
r = crypt_activate_by_passphrase(cd, NULL, slot_check, password,
|
||||
passwordLen, 0);
|
||||
|
||||
/*
|
||||
* Allow keyslot only if it is last slot or if user explicitly
|
||||
* specify whch slot to use (IOW others will be disabled).
|
||||
* specify which slot to use (IOW others will be disabled).
|
||||
*/
|
||||
if (r >= 0 && opt_key_slot == CRYPT_ANY_SLOT &&
|
||||
crypt_keyslot_status(cd, r) != CRYPT_SLOT_ACTIVE_LAST) {
|
||||
@@ -909,14 +1052,17 @@ static int init_keyfile(struct reenc_ctx *rc, struct crypt_device *cd, int slot_
|
||||
}
|
||||
|
||||
if (r < 0) {
|
||||
crypt_safe_free(rc->p[slot].password);
|
||||
rc->p[slot].password = NULL;
|
||||
rc->p[slot].passwordLen = 0;
|
||||
crypt_safe_free(password);
|
||||
if (r == -EPERM)
|
||||
log_err(_("No key available with this passphrase.\n"));
|
||||
return r;
|
||||
} else
|
||||
rc->keyslot = slot;
|
||||
} else {
|
||||
rc->keyslot = r;
|
||||
rc->p[r].password = password;
|
||||
rc->p[r].passwordLen = passwordLen;
|
||||
}
|
||||
|
||||
password = NULL;
|
||||
passwordLen = 0;
|
||||
|
||||
return r;
|
||||
}
|
||||
@@ -930,8 +1076,8 @@ static int initialize_passphrase(struct reenc_ctx *rc, const char *device)
|
||||
|
||||
log_dbg("Passhrases initialization.");
|
||||
|
||||
if (opt_new && !rc->in_progress) {
|
||||
r = init_passphrase1(rc, cd, _("Enter new passphrase: "), 0, 0);
|
||||
if (rc->reencrypt_mode == ENCRYPT && !rc->in_progress) {
|
||||
r = init_passphrase1(rc, cd, _("Enter new passphrase: "), opt_key_slot, 0);
|
||||
return r > 0 ? 0 : r;
|
||||
}
|
||||
|
||||
@@ -942,11 +1088,18 @@ static int initialize_passphrase(struct reenc_ctx *rc, const char *device)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (opt_key_slot != CRYPT_ANY_SLOT)
|
||||
snprintf(msg, sizeof(msg),
|
||||
_("Enter passphrase for key slot %u: "), opt_key_slot);
|
||||
else
|
||||
snprintf(msg, sizeof(msg), _("Enter any existing passphrase: "));
|
||||
|
||||
if (opt_key_file) {
|
||||
r = init_keyfile(rc, cd, opt_key_slot);
|
||||
} else if (rc->in_progress) {
|
||||
r = init_passphrase1(rc, cd, _("Enter any existing passphrase: "),
|
||||
CRYPT_ANY_SLOT, 1);
|
||||
} else if (rc->in_progress ||
|
||||
opt_key_slot != CRYPT_ANY_SLOT ||
|
||||
rc->reencrypt_mode == DECRYPT) {
|
||||
r = init_passphrase1(rc, cd, msg, opt_key_slot, 1);
|
||||
} else for (i = 0; i < MAX_SLOT; i++) {
|
||||
ki = crypt_keyslot_status(cd, i);
|
||||
if (ki != CRYPT_SLOT_ACTIVE && ki != CRYPT_SLOT_ACTIVE_LAST)
|
||||
@@ -1012,6 +1165,13 @@ static int initialize_context(struct reenc_ctx *rc, const char *device)
|
||||
rc->reencrypt_direction = BACKWARD;
|
||||
rc->device_offset = (uint64_t)~0;
|
||||
}
|
||||
|
||||
if (opt_new)
|
||||
rc->reencrypt_mode = ENCRYPT;
|
||||
else if (opt_decrypt)
|
||||
rc->reencrypt_mode = DECRYPT;
|
||||
else
|
||||
rc->reencrypt_mode = REENCRYPT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1045,7 +1205,7 @@ static void destroy_context(struct reenc_ctx *rc)
|
||||
static int run_reencrypt(const char *device)
|
||||
{
|
||||
int r = -EINVAL;
|
||||
struct reenc_ctx rc = {};
|
||||
static struct reenc_ctx rc = {};
|
||||
|
||||
if (initialize_context(&rc, device))
|
||||
goto out;
|
||||
@@ -1053,26 +1213,41 @@ static int run_reencrypt(const char *device)
|
||||
log_dbg("Running reencryption.");
|
||||
|
||||
if (!rc.in_progress) {
|
||||
if (opt_new) {
|
||||
if ((r = initialize_passphrase(&rc, rc.device)) ||
|
||||
if ((r = initialize_passphrase(&rc, rc.device)))
|
||||
goto out;
|
||||
|
||||
if (rc.reencrypt_mode == ENCRYPT) {
|
||||
/* Create fake header for exising device */
|
||||
if ((r = backup_fake_header(&rc)))
|
||||
goto out;
|
||||
} else {
|
||||
if ((r = backup_luks_headers(&rc)))
|
||||
goto out;
|
||||
/* Create fake header for decrypted device */
|
||||
if (rc.reencrypt_mode == DECRYPT &&
|
||||
(r = backup_fake_header(&rc)))
|
||||
goto out;
|
||||
} else if ((r = initialize_passphrase(&rc, rc.device)) ||
|
||||
(r = backup_luks_headers(&rc)) ||
|
||||
(r = device_check(&rc, MAKE_UNUSABLE)))
|
||||
goto out;
|
||||
goto out;
|
||||
if ((r = device_check(&rc, MAKE_UNUSABLE)))
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
if ((r = initialize_passphrase(&rc, rc.header_file_new)))
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((r = activate_luks_headers(&rc)))
|
||||
goto out;
|
||||
if (!opt_keep_key) {
|
||||
log_dbg("Running data area reencryption.");
|
||||
if ((r = activate_luks_headers(&rc)))
|
||||
goto out;
|
||||
|
||||
if ((r = copy_data(&rc)))
|
||||
goto out;
|
||||
if ((r = copy_data(&rc)))
|
||||
goto out;
|
||||
} else
|
||||
log_dbg("Keeping existing key, skipping data area reencryption.");
|
||||
|
||||
r = restore_luks_header(&rc);
|
||||
// FIXME: fix error path above to not skip this
|
||||
if (rc.reencrypt_mode != DECRYPT)
|
||||
r = restore_luks_header(&rc);
|
||||
out:
|
||||
destroy_context(&rc);
|
||||
return r;
|
||||
@@ -1109,13 +1284,14 @@ int main(int argc, const char **argv)
|
||||
{ "cipher", 'c', POPT_ARG_STRING, &opt_cipher, 0, N_("The cipher used to encrypt the disk (see /proc/crypto)"), NULL },
|
||||
{ "key-size", 's', POPT_ARG_INT, &opt_key_size, 0, N_("The size of the encryption key"), N_("BITS") },
|
||||
{ "hash", 'h', POPT_ARG_STRING, &opt_hash, 0, N_("The hash used to create the encryption key from the passphrase"), NULL },
|
||||
{ "keep-key", '\0', POPT_ARG_NONE, &opt_keep_key, 0, N_("Do not change key, no data area reencryption."), NULL },
|
||||
{ "key-file", 'd', POPT_ARG_STRING, &opt_key_file, 0, N_("Read the key from a file."), NULL },
|
||||
{ "iter-time", 'i', POPT_ARG_INT, &opt_iteration_time, 0, N_("PBKDF2 iteration time for LUKS (in ms)"), N_("msecs") },
|
||||
{ "batch-mode", 'q', POPT_ARG_NONE, &opt_batch_mode, 0, N_("Do not ask for confirmation"), NULL },
|
||||
{ "tries", 'T', POPT_ARG_INT, &opt_tries, 0, N_("How often the input of the passphrase can be retried"), NULL },
|
||||
{ "use-random", '\0', POPT_ARG_NONE, &opt_random, 0, N_("Use /dev/random for generating volume key."), NULL },
|
||||
{ "use-urandom", '\0', POPT_ARG_NONE, &opt_urandom, 0, N_("Use /dev/urandom for generating volume key."), NULL },
|
||||
{ "use-directio", '\0', POPT_ARG_NONE, &opt_directio, 0, N_("Use direct-io when accesing devices."), NULL },
|
||||
{ "use-directio", '\0', POPT_ARG_NONE, &opt_directio, 0, N_("Use direct-io when accessing devices."), NULL },
|
||||
{ "use-fsync", '\0', POPT_ARG_NONE, &opt_fsync, 0, N_("Use fsync after each block."), NULL },
|
||||
{ "write-log", '\0', POPT_ARG_NONE, &opt_write_log, 0, N_("Update log file after every block."), NULL },
|
||||
{ "key-slot", 'S', POPT_ARG_INT, &opt_key_slot, 0, N_("Use only this slot (others will be disabled)."), NULL },
|
||||
@@ -1123,7 +1299,8 @@ int main(int argc, const char **argv)
|
||||
{ "keyfile-size", 'l', POPT_ARG_LONG, &opt_keyfile_size, 0, N_("Limits the read from keyfile"), N_("bytes") },
|
||||
{ "reduce-device-size",'\0', POPT_ARG_STRING, &opt_reduce_size_str, 0, N_("Reduce data device size (move data offset). DANGEROUS!"), N_("bytes") },
|
||||
{ "device-size", '\0', POPT_ARG_STRING, &opt_device_size_str, 0, N_("Use only specified device size (ignore rest of device). DANGEROUS!"), N_("bytes") },
|
||||
{ "new", 'N', POPT_ARG_NONE,&opt_new, 0, N_("Create new header on not encrypted device."), NULL },
|
||||
{ "new", 'N', POPT_ARG_NONE, &opt_new, 0, N_("Create new header on not encrypted device."), NULL },
|
||||
{ "decrypt", '\0', POPT_ARG_NONE, &opt_decrypt, 0, N_("Permanently decrypt device (remove encryption)."), NULL },
|
||||
POPT_TABLEEND
|
||||
};
|
||||
poptContext popt_context;
|
||||
@@ -1152,12 +1329,10 @@ int main(int argc, const char **argv)
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
if (!opt_batch_mode) {
|
||||
log_std(_("WARNING: this is experimental code, it can completely break your data.\n"));
|
||||
if (!opt_batch_mode)
|
||||
log_verbose(_("Reencryption will change: volume key%s%s%s%s.\n"),
|
||||
opt_hash ? _(", set hash to ") : "", opt_hash ?: "",
|
||||
opt_cipher ? _(", set cipher to "): "", opt_cipher ?: "");
|
||||
}
|
||||
|
||||
action_argv = poptGetArgs(popt_context);
|
||||
if(!action_argv)
|
||||
@@ -1195,12 +1370,12 @@ int main(int argc, const char **argv)
|
||||
poptGetInvocationName(popt_context));
|
||||
|
||||
if (opt_device_size_str &&
|
||||
crypt_string_to_size(NULL, opt_device_size_str, &opt_device_size))
|
||||
tools_string_to_size(NULL, opt_device_size_str, &opt_device_size))
|
||||
usage(popt_context, EXIT_FAILURE, _("Invalid device size specification."),
|
||||
poptGetInvocationName(popt_context));
|
||||
|
||||
if (opt_reduce_size_str &&
|
||||
crypt_string_to_size(NULL, opt_reduce_size_str, &opt_reduce_size))
|
||||
tools_string_to_size(NULL, opt_reduce_size_str, &opt_reduce_size))
|
||||
usage(popt_context, EXIT_FAILURE, _("Invalid device size specification."),
|
||||
poptGetInvocationName(popt_context));
|
||||
if (opt_reduce_size > 64 * 1024 * 1024)
|
||||
@@ -1214,6 +1389,18 @@ int main(int argc, const char **argv)
|
||||
usage(popt_context, EXIT_FAILURE, _("Option --new must be used together with --reduce-device-size."),
|
||||
poptGetInvocationName(popt_context));
|
||||
|
||||
if (opt_keep_key && ((!opt_hash && !opt_iteration_time) || opt_cipher || opt_new))
|
||||
usage(popt_context, EXIT_FAILURE, _("Option --keep-key can be used only with --hash or --iter-time."),
|
||||
poptGetInvocationName(popt_context));
|
||||
|
||||
if (opt_new && opt_decrypt)
|
||||
usage(popt_context, EXIT_FAILURE, _("Option --new cannot be used together with --decrypt."),
|
||||
poptGetInvocationName(popt_context));
|
||||
|
||||
if (opt_decrypt && (opt_cipher || opt_hash || opt_reduce_size || opt_keep_key || opt_device_size))
|
||||
usage(popt_context, EXIT_FAILURE, _("Option --decrypt is incompatible with specified parameters."),
|
||||
poptGetInvocationName(popt_context));
|
||||
|
||||
if (opt_debug) {
|
||||
opt_verbose = 1;
|
||||
crypt_set_debug_level(-1);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Password quality check wrapper
|
||||
*
|
||||
* Copyright (C) 2012, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2012, Milan Broz
|
||||
* Copyright (C) 2012-2014, Milan Broz
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
int opt_force_password = 0;
|
||||
|
||||
#if ENABLE_PWQUALITY
|
||||
#if defined ENABLE_PWQUALITY
|
||||
#include <pwquality.h>
|
||||
|
||||
static int tools_check_pwquality(const char *password)
|
||||
@@ -58,12 +58,59 @@ static int tools_check_pwquality(const char *password)
|
||||
pwquality_free_settings(pwq);
|
||||
return r;
|
||||
}
|
||||
#else /* ENABLE_PWQUALITY */
|
||||
#elif defined ENABLE_PASSWDQC
|
||||
#include <passwdqc.h>
|
||||
|
||||
static int tools_check_pwquality(const char *password)
|
||||
{
|
||||
passwdqc_params_t params;
|
||||
char *parse_reason;
|
||||
const char *check_reason;
|
||||
const char *config = PASSWDQC_CONFIG_FILE;
|
||||
|
||||
passwdqc_params_reset(¶ms);
|
||||
|
||||
if (*config && passwdqc_params_load(¶ms, &parse_reason, config)) {
|
||||
log_err(_("Cannot check password quality: %s\n"),
|
||||
(parse_reason ? parse_reason : "Out of memory"));
|
||||
free(parse_reason);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
check_reason = passwdqc_check(¶ms.qc, password, NULL, NULL);
|
||||
if (check_reason) {
|
||||
log_err(_("Password quality check failed: Bad passphrase (%s)\n"),
|
||||
check_reason);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else /* !(ENABLE_PWQUALITY || ENABLE_PASSWDQC) */
|
||||
static int tools_check_pwquality(const char *password)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* ENABLE_PWQUALITY */
|
||||
#endif /* ENABLE_PWQUALITY || ENABLE_PASSWDQC */
|
||||
|
||||
int tools_is_cipher_null(const char *cipher)
|
||||
{
|
||||
if (!cipher)
|
||||
return 0;
|
||||
|
||||
return !strcmp(cipher, "cipher_null") ? 1 : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Keyfile - is standard input treated as a binary file (no EOL handling).
|
||||
*/
|
||||
int tools_is_stdin(const char *key_file)
|
||||
{
|
||||
if (!key_file)
|
||||
return 1;
|
||||
|
||||
return strcmp(key_file, "-") ? 0 : 1;
|
||||
}
|
||||
|
||||
int tools_get_key(const char *prompt,
|
||||
char **key, size_t *key_size,
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
/*
|
||||
* cryptsetup - setup cryptographic volumes for dm-crypt
|
||||
*
|
||||
* Copyright (C) 2004, Christophe Saout <christophe@saout.de>
|
||||
* Copyright (C) 2004, Jana Saout <jana@saout.de>
|
||||
* Copyright (C) 2004-2007, Clemens Fruhwirth <clemens@endorphin.org>
|
||||
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2009-2012, Milan Broz
|
||||
* Copyright (C) 2009-2014, Milan Broz
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -143,6 +143,7 @@ int yesDialog(const char *msg, void *usrptr __attribute__((unused)))
|
||||
if(isatty(STDIN_FILENO) && !opt_batch_mode) {
|
||||
log_std("\nWARNING!\n========\n");
|
||||
log_std("%s\n\nAre you sure? (Type uppercase yes): ", msg);
|
||||
fflush(stdout);
|
||||
if(getline(&answer, &size, stdin) == -1) {
|
||||
r = 0;
|
||||
/* Aborted by signal */
|
||||
@@ -163,7 +164,7 @@ int yesDialog(const char *msg, void *usrptr __attribute__((unused)))
|
||||
|
||||
void show_status(int errcode)
|
||||
{
|
||||
char error[256], *error_;
|
||||
char error[256];
|
||||
|
||||
if(!opt_verbose)
|
||||
return;
|
||||
@@ -175,12 +176,16 @@ void show_status(int errcode)
|
||||
|
||||
crypt_get_error(error, sizeof(error));
|
||||
|
||||
if (!error[0]) {
|
||||
error_ = strerror_r(-errcode, error, sizeof(error));
|
||||
if (error_ != error) {
|
||||
if (*error) {
|
||||
#ifdef STRERROR_R_CHAR_P /* GNU-specific strerror_r */
|
||||
char *error_ = strerror_r(-errcode, error, sizeof(error));
|
||||
if (error_ != error)
|
||||
strncpy(error, error_, sizeof(error));
|
||||
error[sizeof(error) - 1] = '\0';
|
||||
}
|
||||
#else /* POSIX strerror_r variant */
|
||||
if (strerror_r(-errcode, error, sizeof(error)))
|
||||
*error = '\0';
|
||||
#endif
|
||||
error[sizeof(error) - 1] = '\0';
|
||||
}
|
||||
|
||||
log_err(_("Command failed with code %i"), -errcode);
|
||||
@@ -257,3 +262,68 @@ int translate_errno(int r)
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* Device size string parsing, suffixes:
|
||||
* s|S - 512 bytes sectors
|
||||
* k |K |m |M |g |G |t |T - 1024 base
|
||||
* kiB|KiB|miB|MiB|giB|GiB|tiB|TiB - 1024 base
|
||||
* kb |KB |mM |MB |gB |GB |tB |TB - 1000 base
|
||||
*/
|
||||
int tools_string_to_size(struct crypt_device *cd, const char *s, uint64_t *size)
|
||||
{
|
||||
char *endp = NULL;
|
||||
size_t len;
|
||||
uint64_t mult_base, mult, tmp;
|
||||
|
||||
*size = strtoull(s, &endp, 10);
|
||||
if (!isdigit(s[0]) ||
|
||||
(errno == ERANGE && *size == ULLONG_MAX) ||
|
||||
(errno != 0 && *size == 0))
|
||||
return -EINVAL;
|
||||
|
||||
if (!endp || !*endp)
|
||||
return 0;
|
||||
|
||||
len = strlen(endp);
|
||||
/* Allow "B" and "iB" suffixes */
|
||||
if (len > 3 ||
|
||||
(len == 3 && (endp[1] != 'i' || endp[2] != 'B')) ||
|
||||
(len == 2 && endp[1] != 'B'))
|
||||
return -EINVAL;
|
||||
|
||||
if (len == 1 || len == 3)
|
||||
mult_base = 1024;
|
||||
else
|
||||
mult_base = 1000;
|
||||
|
||||
mult = 1;
|
||||
switch (endp[0]) {
|
||||
case 's':
|
||||
case 'S': mult = 512;
|
||||
break;
|
||||
case 't':
|
||||
case 'T': mult *= mult_base;
|
||||
/* Fall through */
|
||||
case 'g':
|
||||
case 'G': mult *= mult_base;
|
||||
/* Fall through */
|
||||
case 'm':
|
||||
case 'M': mult *= mult_base;
|
||||
/* Fall through */
|
||||
case 'k':
|
||||
case 'K': mult *= mult_base;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tmp = *size * mult;
|
||||
if ((tmp / *size) != mult) {
|
||||
log_dbg("Device size overflow.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*size = tmp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/*
|
||||
* veritysetup - setup cryptographic volumes for dm-verity
|
||||
*
|
||||
* Copyright (C) 2012, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2012-2013, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2012-2013, Milan Broz
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
||||
@@ -5,7 +5,9 @@ TESTS = api-test \
|
||||
discards-test \
|
||||
mode-test \
|
||||
password-hash-test \
|
||||
tcrypt-compat-test
|
||||
tcrypt-compat-test \
|
||||
luks1-compat-test \
|
||||
device-test
|
||||
|
||||
if VERITYSETUP
|
||||
TESTS += verity-compat-test
|
||||
@@ -16,21 +18,25 @@ TESTS += reencryption-compat-test
|
||||
endif
|
||||
|
||||
EXTRA_DIST = compatimage.img.bz2 compatv10image.img.bz2 \
|
||||
img_fs_ext4.img.bz2 img_fs_vfat.img.bz2 img_fs_xfs.img.bz2 \
|
||||
valid_header_file.bz2 \
|
||||
evil_hdr-payload_overwrite.bz2 \
|
||||
evil_hdr-stripes_payload_dmg.bz2 \
|
||||
evil_hdr-luks_hdr_damage.bz2 \
|
||||
evil_hdr-small_luks_device.bz2 \
|
||||
tcrypt-images.tar.bz2 \
|
||||
luks1-images.tar.bz2 \
|
||||
compat-test loopaes-test align-test discards-test mode-test password-hash-test \
|
||||
verity-compat-test \
|
||||
reencryption-compat-test \
|
||||
tcrypt-compat-test \
|
||||
luks1-compat-test \
|
||||
device-test \
|
||||
cryptsetup-valg-supps valg.sh valg-api.sh
|
||||
|
||||
CLEANFILES = cryptsetup-tst* valglog*
|
||||
clean-local:
|
||||
-rm -rf tcrypt-images
|
||||
-rm -rf tcrypt-images luks1-images
|
||||
|
||||
differ_SOURCES = differ.c
|
||||
differ_CFLAGS = $(AM_CFLAGS) -Wall -O2
|
||||
|
||||
@@ -3,11 +3,16 @@
|
||||
CRYPTSETUP="../src/cryptsetup"
|
||||
DEV=""
|
||||
DEV_STACKED="luks0xbabe"
|
||||
MNT_DIR="./mnt_luks"
|
||||
PWD1="93R4P4pIqAH8"
|
||||
PWD2="mymJeD8ivEhE"
|
||||
|
||||
cleanup() {
|
||||
udevadm settle >/dev/null 2>&1
|
||||
if [ -d "$MNT_DIR" ] ; then
|
||||
umount -f $MNT_DIR 2>/dev/null
|
||||
rmdir $MNT_DIR 2>/dev/null
|
||||
fi
|
||||
[ -b /dev/mapper/$DEV_STACKED ] && dmsetup remove $DEV_STACKED >/dev/null 2>&1
|
||||
rmmod scsi_debug 2>/dev/null
|
||||
sleep 2
|
||||
@@ -15,12 +20,18 @@ cleanup() {
|
||||
|
||||
fail()
|
||||
{
|
||||
echo "FAIL"
|
||||
[ -n "$1" ] && echo "$1"
|
||||
if [ -n "$1" ] ; then echo "FAIL $1" ; else echo "FAIL" ; fi
|
||||
cleanup
|
||||
exit 100
|
||||
}
|
||||
|
||||
skip()
|
||||
{
|
||||
echo "TEST SKIPPED: $1"
|
||||
cleanup
|
||||
exit 0
|
||||
}
|
||||
|
||||
add_device() {
|
||||
modprobe scsi_debug $@
|
||||
if [ $? -ne 0 ] ; then
|
||||
@@ -29,7 +40,7 @@ add_device() {
|
||||
fi
|
||||
|
||||
sleep 2
|
||||
DEV=$(grep scsi_debug /sys/block/*/device/model | cut -f4 -d /)
|
||||
DEV=$(grep -l -e scsi_debug /sys/block/*/device/model | cut -f4 -d /)
|
||||
|
||||
if [ ! -e /sys/block/$DEV/alignment_offset ] ; then
|
||||
echo "This kernel seems to not support topology info, test skipped."
|
||||
@@ -76,10 +87,10 @@ format_null()
|
||||
{
|
||||
if [ $3 -eq 0 ] ; then
|
||||
echo -n "Formatting using topology info ($1 bits key) [slot 0"
|
||||
echo $PWD1 | $CRYPTSETUP luksFormat $DEV -q -i1 -c null -s $1
|
||||
echo | $CRYPTSETUP luksFormat $DEV -q -i1 -c null -s $1
|
||||
else
|
||||
echo -n "Formatting using forced sector alignment $3 ($1 bits key) [slot 0"
|
||||
echo $PWD1 | $CRYPTSETUP luksFormat $DEV -q -i1 -c null -s $1 --align-payload=$3
|
||||
echo | $CRYPTSETUP luksFormat $DEV -q -i1 -c null -s $1 --align-payload=$3
|
||||
fi
|
||||
|
||||
POFF=$(get_offsets "Payload offset")
|
||||
@@ -87,7 +98,7 @@ format_null()
|
||||
[ $POFF != $2 ] && fail "Expected data offset differs: expected $2 != detected $POFF"
|
||||
if [ -n "$4" ] ; then
|
||||
for j in 1 2 3 4 5 6 7 ; do
|
||||
echo -e "$PWD1\n$PWD2$j" | $CRYPTSETUP luksAddKey $DEV -q -i1 --key-slot $j -c null $PARAMS
|
||||
echo -e "\n" | $CRYPTSETUP luksAddKey $DEV -q -i1 --key-slot $j -c null $PARAMS
|
||||
echo -n $j
|
||||
[ $? -ne 0 ] && fail
|
||||
done
|
||||
@@ -198,3 +209,18 @@ format_null 512 4040 8
|
||||
format_null 512 4096 128
|
||||
format_null 512 4096 2048
|
||||
cleanup
|
||||
|
||||
echo "# Create enterprise-class 4K drive with fs and LUKS images."
|
||||
# loop device here presents 512 block but images have 4k block
|
||||
# cryptsetup should properly use 4k block on direct-io
|
||||
add_device dev_size_mb=16 sector_size=4096 physblk_exp=0 num_tgts=1
|
||||
for file in $(ls img_fs_*.img.bz2) ; do
|
||||
echo "Format using fs image $file."
|
||||
bzip2 -d -c $file | dd of=$DEV bs=1M 2>/dev/null || fail "bad image"
|
||||
[ ! -d $MNT_DIR ] && mkdir $MNT_DIR
|
||||
mount $DEV $MNT_DIR || skip "Mounting image is not available."
|
||||
echo $PWD1 | $CRYPTSETUP luksFormat -i 1 $MNT_DIR/luks.img || fail
|
||||
echo $PWD2 | $CRYPTSETUP luksFormat -i 1 $MNT_DIR/luks.img --header $MNT_DIR/luks_header.img || fail
|
||||
umount $MNT_DIR
|
||||
done
|
||||
cleanup
|
||||
|
||||
105
tests/api-test.c
105
tests/api-test.c
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* cryptsetup library API check functions
|
||||
*
|
||||
* Copyright (C) 2009-2012 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2009-2013, Milan Broz
|
||||
* Copyright (C) 2009-2013 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2009-2014, Milan Broz
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -94,6 +94,7 @@ static int global_lines = 0;
|
||||
|
||||
static char *DEVICE_1 = NULL;
|
||||
static char *DEVICE_2 = NULL;
|
||||
static char *DEVICE_3 = NULL;
|
||||
static char *THE_LOOP_DEV = NULL;
|
||||
|
||||
static char *tmp_file_1 = NULL;
|
||||
@@ -123,6 +124,9 @@ static int fips_mode(void)
|
||||
int fd;
|
||||
char buf = 0;
|
||||
|
||||
if (access("/etc/system-fips", F_OK))
|
||||
return 0;
|
||||
|
||||
fd = open("/proc/sys/crypto/fips_enabled", O_RDONLY);
|
||||
|
||||
if (fd < 0)
|
||||
@@ -246,7 +250,7 @@ static int _prepare_keyfile(const char *name, const char *passphrase, int size)
|
||||
{
|
||||
int fd, r;
|
||||
|
||||
fd = open(name, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR);
|
||||
fd = open(name, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR|S_IWUSR);
|
||||
if (fd != -1) {
|
||||
r = write(fd, passphrase, size);
|
||||
close(fd);
|
||||
@@ -371,6 +375,9 @@ static void _cleanup(void)
|
||||
if (crypt_loop_device(DEVICE_2))
|
||||
crypt_loop_detach(DEVICE_2);
|
||||
|
||||
if (crypt_loop_device(DEVICE_3))
|
||||
crypt_loop_detach(DEVICE_3);
|
||||
|
||||
_system("rm -f " IMAGE_EMPTY, 0);
|
||||
_system("rm -f " IMAGE1, 0);
|
||||
|
||||
@@ -391,6 +398,7 @@ static void _cleanup(void)
|
||||
free(THE_LOOP_DEV);
|
||||
free(DEVICE_1);
|
||||
free(DEVICE_2);
|
||||
free(DEVICE_3);
|
||||
}
|
||||
|
||||
static int _setup(void)
|
||||
@@ -455,6 +463,12 @@ static int _setup(void)
|
||||
fd = crypt_loop_attach(DEVICE_2, IMAGE_EMPTY, 0, 0, &ro);
|
||||
close(fd);
|
||||
}
|
||||
if (!DEVICE_3)
|
||||
DEVICE_3 = crypt_loop_get_device();
|
||||
if (!DEVICE_3) {
|
||||
printf("Cannot find free loop device.\n");
|
||||
return 1;
|
||||
}
|
||||
/* Keymaterial offset is less than 8 sectors */
|
||||
_system(" [ ! -e " EVL_HEADER_1 " ] && bzip2 -dk " EVL_HEADER_1 ".bz2", 1);
|
||||
/* keymaterial offset aims into payload area */
|
||||
@@ -961,8 +975,11 @@ static void SuspendDevice(void)
|
||||
suspend_status = crypt_suspend(cd, CDEVICE_1);
|
||||
if (suspend_status == -ENOTSUP) {
|
||||
printf("WARNING: Suspend/Resume not supported, skipping test.\n");
|
||||
goto out;
|
||||
OK_(crypt_deactivate(cd, CDEVICE_1));
|
||||
crypt_free(cd);
|
||||
return;
|
||||
}
|
||||
|
||||
OK_(suspend_status);
|
||||
FAIL_(crypt_suspend(cd, CDEVICE_1), "already suspended");
|
||||
|
||||
@@ -976,10 +993,30 @@ static void SuspendDevice(void)
|
||||
FAIL_(crypt_resume_by_keyfile_offset(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, 1, 0), "wrong key");
|
||||
OK_(crypt_resume_by_keyfile_offset(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, 0, 0));
|
||||
FAIL_(crypt_resume_by_keyfile(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, 0), "not suspended");
|
||||
_remove_keyfiles();
|
||||
out:
|
||||
OK_(crypt_deactivate(cd, CDEVICE_1));
|
||||
crypt_free(cd);
|
||||
|
||||
/* create LUKS device with detached header */
|
||||
OK_(crypt_init(&cd, DEVICE_1));
|
||||
OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
|
||||
OK_(crypt_set_data_device(cd, DEVICE_2));
|
||||
OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEY1, strlen(KEY1), 0));
|
||||
crypt_free(cd);
|
||||
|
||||
/* Should be able to suspend but not resume if not header specified */
|
||||
OK_(crypt_init_by_name(&cd, CDEVICE_1));
|
||||
OK_(crypt_suspend(cd, CDEVICE_1));
|
||||
FAIL_(crypt_suspend(cd, CDEVICE_1), "already suspended");
|
||||
FAIL_(crypt_resume_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEY1, strlen(KEY1)-1), "no header");
|
||||
crypt_free(cd);
|
||||
|
||||
OK_(crypt_init_by_name_and_header(&cd, CDEVICE_1, DEVICE_1));
|
||||
OK_(crypt_resume_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEY1, strlen(KEY1)));
|
||||
|
||||
OK_(crypt_deactivate(cd, CDEVICE_1));
|
||||
crypt_free(cd);
|
||||
|
||||
_remove_keyfiles();
|
||||
}
|
||||
|
||||
static void AddDeviceLuks(void)
|
||||
@@ -1081,6 +1118,14 @@ static void AddDeviceLuks(void)
|
||||
OK_(crypt_init_by_name_and_header(&cd, CDEVICE_1, DMDIR H_DEVICE));
|
||||
FAIL_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, ¶ms), "Context is already formated");
|
||||
EQ_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
|
||||
crypt_free(cd);
|
||||
// check active status without header
|
||||
OK_(crypt_init_by_name_and_header(&cd, CDEVICE_1, NULL));
|
||||
EQ_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
|
||||
OK_(!!crypt_get_type(cd));
|
||||
OK_(strcmp(cipher, crypt_get_cipher(cd)));
|
||||
OK_(strcmp(cipher_mode, crypt_get_cipher_mode(cd)));
|
||||
EQ_((int)key_size, crypt_get_volume_key_size(cd));
|
||||
OK_(crypt_deactivate(cd, CDEVICE_1));
|
||||
crypt_free(cd);
|
||||
|
||||
@@ -1310,8 +1355,8 @@ static void LuksHeaderRestore(void)
|
||||
|
||||
// volume key_size mismatch
|
||||
OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
|
||||
memcpy(key2, key, key_size - 1);
|
||||
OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key2, key_size - 1, ¶ms));
|
||||
memcpy(key2, key, key_size / 2);
|
||||
OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key2, key_size / 2, ¶ms));
|
||||
FAIL_(crypt_header_restore(cd, CRYPT_LUKS1, VALID_HEADER), "Volume keysize mismatch");
|
||||
crypt_free(cd);
|
||||
|
||||
@@ -1425,6 +1470,7 @@ static void LuksHeaderBackup(void)
|
||||
.data_alignment = 2048,
|
||||
};
|
||||
char key[128];
|
||||
int fd, ro = O_RDONLY;
|
||||
|
||||
const char *mk_hex = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a";
|
||||
size_t key_size = strlen(mk_hex) / 2;
|
||||
@@ -1432,6 +1478,8 @@ static void LuksHeaderBackup(void)
|
||||
const char *cipher_mode = "cbc-essiv:sha256";
|
||||
uint64_t r_payload_offset;
|
||||
|
||||
const char *passphrase = PASSPHRASE;
|
||||
|
||||
crypt_decode_key(key, mk_hex, key_size);
|
||||
|
||||
OK_(get_luks_offsets(0, key_size, params.data_alignment, 0, NULL, &r_payload_offset));
|
||||
@@ -1441,6 +1489,8 @@ static void LuksHeaderBackup(void)
|
||||
OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
|
||||
OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, ¶ms));
|
||||
OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0));
|
||||
EQ_(crypt_keyslot_add_by_volume_key(cd, 7, key, key_size, passphrase, strlen(passphrase)), 7);
|
||||
EQ_(crypt_keyslot_add_by_volume_key(cd, 0, key, key_size, passphrase, strlen(passphrase)), 0);
|
||||
OK_(crypt_header_backup(cd, CRYPT_LUKS1, BACKUP_FILE));
|
||||
OK_(crypt_deactivate(cd, CDEVICE_1));
|
||||
crypt_free(cd);
|
||||
@@ -1454,6 +1504,43 @@ static void LuksHeaderBackup(void)
|
||||
OK_(crypt_deactivate(cd, CDEVICE_1));
|
||||
crypt_free(cd);
|
||||
|
||||
// exercise luksOpen using backup header in file
|
||||
OK_(crypt_init(&cd, BACKUP_FILE));
|
||||
OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
|
||||
OK_(crypt_set_data_device(cd, DMDIR L_DEVICE_OK));
|
||||
EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, passphrase, strlen(passphrase), 0), 0);
|
||||
EQ_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
|
||||
OK_(crypt_deactivate(cd, CDEVICE_1));
|
||||
crypt_free(cd);
|
||||
|
||||
OK_(crypt_init(&cd, BACKUP_FILE));
|
||||
OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
|
||||
OK_(crypt_set_data_device(cd, DMDIR L_DEVICE_OK));
|
||||
EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, 7, passphrase, strlen(passphrase), 0), 7);
|
||||
EQ_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
|
||||
OK_(crypt_deactivate(cd, CDEVICE_1));
|
||||
crypt_free(cd);
|
||||
|
||||
// exercise luksOpen using backup header on block device
|
||||
fd = crypt_loop_attach(DEVICE_3, BACKUP_FILE, 0, 0, &ro);
|
||||
close(fd);
|
||||
OK_(fd < 0);
|
||||
OK_(crypt_init(&cd, DEVICE_3));
|
||||
OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
|
||||
OK_(crypt_set_data_device(cd, DMDIR L_DEVICE_OK));
|
||||
EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, passphrase, strlen(passphrase), 0), 0);
|
||||
EQ_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
|
||||
OK_(crypt_deactivate(cd, CDEVICE_1));
|
||||
crypt_free(cd);
|
||||
|
||||
OK_(crypt_init(&cd, DEVICE_3));
|
||||
OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
|
||||
OK_(crypt_set_data_device(cd, DMDIR L_DEVICE_OK));
|
||||
EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, 7, passphrase, strlen(passphrase), 0), 7);
|
||||
EQ_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
|
||||
OK_(crypt_deactivate(cd, CDEVICE_1));
|
||||
crypt_free(cd);
|
||||
|
||||
_cleanup_dmdevices();
|
||||
}
|
||||
|
||||
@@ -1842,7 +1929,7 @@ static void NonFIPSAlg(void)
|
||||
struct crypt_device *cd;
|
||||
struct crypt_params_luks1 params = {0};
|
||||
char key[128] = "";
|
||||
size_t key_size = 128;
|
||||
size_t key_size = 128 / 8;
|
||||
const char *cipher = "aes";
|
||||
const char *cipher_mode = "cbc-essiv:sha256";
|
||||
int ret;
|
||||
|
||||
@@ -39,7 +39,7 @@ KEY_MATERIAL5_EXT="S331776-395264"
|
||||
TEST_UUID="12345678-1234-1234-1234-123456789abc"
|
||||
|
||||
LOOPDEV=$(losetup -f 2>/dev/null)
|
||||
FIPS_MODE=$(cat /proc/sys/crypto/fips_enabled 2>/dev/null)
|
||||
[ -f /etc/system-fips ] && FIPS_MODE=$(cat /proc/sys/crypto/fips_enabled 2>/dev/null)
|
||||
|
||||
function remove_mapping()
|
||||
{
|
||||
@@ -229,7 +229,7 @@ echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV $DEV_NAME || fail
|
||||
|
||||
# Key Slot 1 and key material section 1 must change, the rest must not
|
||||
prepare "[9] add key test for key files"
|
||||
echo $PWD1 | $CRYPTSETUP luksAddKey $LOOPDEV $KEY1 || fail
|
||||
echo $PWD1 | $CRYPTSETUP luksAddKey -i1 $LOOPDEV $KEY1 || fail
|
||||
check "$KEY_SLOT1 $KEY_MATERIAL1"
|
||||
$CRYPTSETUP -d $KEY1 luksOpen $LOOPDEV $DEV_NAME || fail
|
||||
|
||||
@@ -263,33 +263,33 @@ $CRYPTSETUP -q luksClose $DEV_NAME || fail
|
||||
prepare "[14] format/open - passphrase on stdin & new line" wipe
|
||||
# stdin defined by "-" must take even newline
|
||||
#echo -n -e "$PWD1\n$PWD2" | $CRYPTSETUP -q luksFormat $LOOPDEV - || fail
|
||||
echo -n -e "$PWD1\n$PWD2" | $CRYPTSETUP -q --key-file=- luksFormat $LOOPDEV || fail
|
||||
echo -n -e "$PWD1\n$PWD2" | $CRYPTSETUP -i1 -q --key-file=- luksFormat $LOOPDEV || fail
|
||||
echo -n -e "$PWD1\n$PWD2" | $CRYPTSETUP -q --key-file=- luksOpen $LOOPDEV $DEV_NAME || fail
|
||||
$CRYPTSETUP -q luksClose $DEV_NAME || fail
|
||||
echo -n -e "$PWD1\n$PWD2" | $CRYPTSETUP -q luksOpen $LOOPDEV $DEV_NAME 2>/dev/null && fail
|
||||
# now also try --key-file
|
||||
echo -n -e "$PWD1\n$PWD2" | $CRYPTSETUP -q luksFormat $LOOPDEV --key-file=- || fail
|
||||
echo -n -e "$PWD1\n$PWD2" | $CRYPTSETUP -i1 -q luksFormat $LOOPDEV --key-file=- || fail
|
||||
echo -n -e "$PWD1\n$PWD2" | $CRYPTSETUP -q --key-file=- luksOpen $LOOPDEV $DEV_NAME || fail
|
||||
$CRYPTSETUP -q luksClose $DEV_NAME || fail
|
||||
# process newline if from stdin
|
||||
echo -n -e "$PWD1\n$PWD2" | $CRYPTSETUP -q luksFormat $LOOPDEV || fail
|
||||
echo -n -e "$PWD1\n$PWD2" | $CRYPTSETUP -i1 -q luksFormat $LOOPDEV || fail
|
||||
echo "$PWD1" | $CRYPTSETUP -q luksOpen $LOOPDEV $DEV_NAME || fail
|
||||
$CRYPTSETUP -q luksClose $DEV_NAME || fail
|
||||
|
||||
prepare "[15] UUID - use and report provided UUID" wipe
|
||||
echo $PWD1 | $CRYPTSETUP -q luksFormat --uuid blah $LOOPDEV 2>/dev/null && fail
|
||||
echo $PWD1 | $CRYPTSETUP -q luksFormat --uuid $TEST_UUID $LOOPDEV || fail
|
||||
echo $PWD1 | $CRYPTSETUP -q luksFormat -i1 --uuid blah $LOOPDEV 2>/dev/null && fail
|
||||
echo $PWD1 | $CRYPTSETUP -q luksFormat -i1 --uuid $TEST_UUID $LOOPDEV || fail
|
||||
tst=$($CRYPTSETUP -q luksUUID $LOOPDEV)
|
||||
[ "$tst"x = "$TEST_UUID"x ] || fail
|
||||
echo $PWD1 | $CRYPTSETUP -q luksFormat $LOOPDEV || fail
|
||||
echo $PWD1 | $CRYPTSETUP -q luksFormat -i1 $LOOPDEV || fail
|
||||
$CRYPTSETUP -q luksUUID --uuid $TEST_UUID $LOOPDEV || fail
|
||||
tst=$($CRYPTSETUP -q luksUUID $LOOPDEV)
|
||||
[ "$tst"x = "$TEST_UUID"x ] || fail
|
||||
|
||||
prepare "[16] luksFormat" wipe
|
||||
echo $PWD1 | $CRYPTSETUP -q luksFormat --master-key-file /dev/urandom $LOOPDEV || fail
|
||||
echo $PWD1 | $CRYPTSETUP -q luksFormat --master-key-file /dev/urandom $LOOPDEV -d $KEY1 || fail
|
||||
$CRYPTSETUP -q luksFormat --master-key-file /dev/urandom -s 256 --uuid $TEST_UUID $LOOPDEV $KEY1 || fail
|
||||
echo $PWD1 | $CRYPTSETUP -q luksFormat -i1 --master-key-file /dev/urandom $LOOPDEV || fail
|
||||
echo $PWD1 | $CRYPTSETUP -q luksFormat -i1 --master-key-file /dev/urandom $LOOPDEV -d $KEY1 || fail
|
||||
$CRYPTSETUP -q luksFormat -i1 --master-key-file /dev/urandom -s 256 --uuid $TEST_UUID $LOOPDEV $KEY1 || fail
|
||||
$CRYPTSETUP luksOpen -d $KEY1 $LOOPDEV $DEV_NAME || fail
|
||||
$CRYPTSETUP -q luksClose $DEV_NAME || fail
|
||||
# open by UUID
|
||||
@@ -298,37 +298,54 @@ $CRYPTSETUP luksOpen -d $KEY1 UUID=X$TEST_UUID $DEV_NAME 2>/dev/null && fail
|
||||
$CRYPTSETUP luksOpen -d $KEY1 UUID=$TEST_UUID $DEV_NAME || fail
|
||||
$CRYPTSETUP -q luksClose $DEV_NAME || fail
|
||||
# empty keyfile
|
||||
$CRYPTSETUP -q luksFormat $LOOPDEV $KEYE || fail
|
||||
$CRYPTSETUP -q luksFormat -i1 $LOOPDEV $KEYE || fail
|
||||
$CRYPTSETUP luksOpen -d $KEYE $LOOPDEV $DEV_NAME || fail
|
||||
$CRYPTSETUP -q luksClose $DEV_NAME || fail
|
||||
# open by volume key
|
||||
echo $PWD1 | $CRYPTSETUP -q luksFormat -s 256 --master-key-file $KEY1 $LOOPDEV || fail
|
||||
echo $PWD1 | $CRYPTSETUP -q luksFormat -i1 -s 256 --master-key-file $KEY1 $LOOPDEV || fail
|
||||
$CRYPTSETUP luksOpen --master-key-file /dev/urandom $LOOPDEV $DEV_NAME 2>/dev/null && fail
|
||||
$CRYPTSETUP luksOpen --master-key-file $KEY1 $LOOPDEV $DEV_NAME || fail
|
||||
$CRYPTSETUP -q luksClose $DEV_NAME || fail
|
||||
|
||||
prepare "[17] AddKey volume key, passphrase and keyfile" wipe
|
||||
# masterkey
|
||||
echo $PWD1 | $CRYPTSETUP -q luksFormat $LOOPDEV --master-key-file /dev/zero --key-slot 3 || fail
|
||||
echo $PWD1 | $CRYPTSETUP -q luksFormat -i1 $LOOPDEV --master-key-file /dev/zero --key-slot 3 || fail
|
||||
echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV --test-passphrase || fail
|
||||
$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 3: ENABLED" || fail
|
||||
echo $PWD2 | $CRYPTSETUP luksAddKey $LOOPDEV --master-key-file /dev/zero --key-slot 4 || fail
|
||||
echo $PWD2 | $CRYPTSETUP luksAddKey -i1 $LOOPDEV --master-key-file /dev/zero --key-slot 4 || fail
|
||||
echo $PWD2 | $CRYPTSETUP luksOpen $LOOPDEV --test-passphrase --key-slot 4 || fail
|
||||
$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 4: ENABLED" || fail
|
||||
echo $PWD3 | $CRYPTSETUP luksAddKey $LOOPDEV --master-key-file /dev/null --key-slot 5 2>/dev/null && fail
|
||||
echo $PWD3 | $CRYPTSETUP luksAddKey -i1 $LOOPDEV --master-key-file /dev/null --key-slot 5 2>/dev/null && fail
|
||||
$CRYPTSETUP luksAddKey -i1 $LOOPDEV --master-key-file /dev/zero --key-slot 5 $KEY1 || fail
|
||||
$CRYPTSETUP luksOpen $LOOPDEV --test-passphrase --key-slot 5 -d $KEY1 || fail
|
||||
$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 5: ENABLED" || fail
|
||||
|
||||
# special "-" handling
|
||||
$CRYPTSETUP -q luksFormat -i1 $LOOPDEV $KEY1 --key-slot 3 || fail
|
||||
echo $PWD1 | $CRYPTSETUP luksAddKey -i1 $LOOPDEV -d $KEY1 - || fail
|
||||
echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV --test-passphrase 2>/dev/null && fail
|
||||
echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV -d - --test-passphrase || fail
|
||||
echo $PWD1 | $CRYPTSETUP luksAddKey -i1 $LOOPDEV -d - $KEY2 || fail
|
||||
$CRYPTSETUP luksOpen $LOOPDEV -d $KEY2 --test-passphrase || fail
|
||||
|
||||
# [0]PWD1 [1]PWD2 [2]$KEY1/1 [3]$KEY1 [4]$KEY2
|
||||
$CRYPTSETUP -q luksFormat $LOOPDEV $KEY1 --key-slot 3 || fail
|
||||
$CRYPTSETUP -q luksFormat -i1 $LOOPDEV $KEY1 --key-slot 3 || fail
|
||||
$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 3: ENABLED" || fail
|
||||
$CRYPTSETUP luksAddKey $LOOPDEV -d $KEY1 $KEY2 --key-slot 3 2>/dev/null && fail
|
||||
$CRYPTSETUP luksAddKey $LOOPDEV -i1 -d $KEY1 $KEY2 --key-slot 3 2>/dev/null && fail
|
||||
# keyfile/keyfile
|
||||
$CRYPTSETUP luksAddKey $LOOPDEV -d $KEY1 $KEY2 --key-slot 4 || fail
|
||||
$CRYPTSETUP luksAddKey $LOOPDEV -i1 -d $KEY1 $KEY2 --key-slot 4 || fail
|
||||
$CRYPTSETUP luksOpen $LOOPDEV -d $KEY2 --test-passphrase --key-slot 4 || fail
|
||||
$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 4: ENABLED" || fail
|
||||
# passphrase/keyfile
|
||||
echo $PWD1 | $CRYPTSETUP luksAddKey $LOOPDEV -d $KEY1 --key-slot 0 || fail
|
||||
echo $PWD1 | $CRYPTSETUP luksAddKey -i1 $LOOPDEV -d $KEY1 --key-slot 0 || fail
|
||||
$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 0: ENABLED" || fail
|
||||
echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV --test-passphrase --key-slot 0 || fail
|
||||
# passphrase/passphrase
|
||||
echo -e "$PWD1\n$PWD2\n" | $CRYPTSETUP luksAddKey $LOOPDEV --key-slot 1 || fail
|
||||
echo -e "$PWD1\n$PWD2\n" | $CRYPTSETUP luksAddKey -i1 $LOOPDEV --key-slot 1 || fail
|
||||
echo $PWD2 | $CRYPTSETUP luksOpen $LOOPDEV --test-passphrase --key-slot 1 || fail
|
||||
$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 1: ENABLED" || fail
|
||||
# keyfile/passphrase
|
||||
echo -e "$PWD2\n" | $CRYPTSETUP luksAddKey $LOOPDEV $KEY1 --key-slot 2 --new-keyfile-size 1 || fail
|
||||
echo -e "$PWD2\n" | $CRYPTSETUP luksAddKey -i1 $LOOPDEV $KEY1 --key-slot 2 --new-keyfile-size 1 || fail
|
||||
$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 2: ENABLED" || fail
|
||||
|
||||
prepare "[18] RemoveKey passphrase and keyfile" reuse
|
||||
@@ -358,6 +375,10 @@ $CRYPTSETUP -q resize $DEV_NAME --size 100 || fail
|
||||
$CRYPTSETUP -q status $DEV_NAME | grep "size:" | grep -q "100 sectors" || fail
|
||||
$CRYPTSETUP -q resize $DEV_NAME || fail
|
||||
$CRYPTSETUP -q status $DEV_NAME | grep "size:" | grep -q "19997 sectors" || fail
|
||||
# Resize underlying loop device as well
|
||||
truncate -s 16M $IMG || fail
|
||||
$CRYPTSETUP -q resize $DEV_NAME || fail
|
||||
$CRYPTSETUP -q status $DEV_NAME | grep "size:" | grep -q "32765 sectors" || fail
|
||||
$CRYPTSETUP -q remove $DEV_NAME || fail
|
||||
$CRYPTSETUP -q status $DEV_NAME >/dev/null && fail
|
||||
echo $PWD1 | $CRYPTSETUP create $DEV_NAME --hash sha1 $LOOPDEV || fail
|
||||
@@ -392,8 +413,8 @@ echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV $DEV_NAME2 2>/dev/null && fail
|
||||
$CRYPTSETUP luksClose $DEV_NAME || fail
|
||||
|
||||
prepare "[21] luksDump" wipe
|
||||
echo $PWD1 | $CRYPTSETUP -q luksFormat --uuid $TEST_UUID $LOOPDEV $KEY1 || fail
|
||||
echo $PWD1 | $CRYPTSETUP luksAddKey $LOOPDEV -d $KEY1 || fail
|
||||
echo $PWD1 | $CRYPTSETUP -q luksFormat -i1 --uuid $TEST_UUID $LOOPDEV $KEY1 || fail
|
||||
echo $PWD1 | $CRYPTSETUP luksAddKey -i1 $LOOPDEV -d $KEY1 || fail
|
||||
$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 0: ENABLED" || fail
|
||||
$CRYPTSETUP luksDump $LOOPDEV | grep -q $TEST_UUID || fail
|
||||
echo $PWDW | $CRYPTSETUP luksDump $LOOPDEV --dump-master-key 2>/dev/null && fail
|
||||
@@ -402,7 +423,7 @@ $CRYPTSETUP luksDump -q $LOOPDEV --dump-master-key -d $KEY1 | grep -q "MK dump:"
|
||||
|
||||
prepare "[22] remove disappeared device" wipe
|
||||
dmsetup create $DEV_NAME --table "0 5000 linear $LOOPDEV 2" || fail
|
||||
echo $PWD1 | $CRYPTSETUP -q -i 0 luksFormat /dev/mapper/$DEV_NAME || fail
|
||||
echo $PWD1 | $CRYPTSETUP -q -i1 luksFormat /dev/mapper/$DEV_NAME || fail
|
||||
echo $PWD1 | $CRYPTSETUP -q luksOpen /dev/mapper/$DEV_NAME $DEV_NAME2 || fail
|
||||
# underlying device now returns error but node is still present
|
||||
dmsetup load $DEV_NAME --table "0 5000 error" || fail
|
||||
@@ -412,17 +433,17 @@ dmsetup remove $DEV_NAME || fail
|
||||
|
||||
prepare "[23] ChangeKey passphrase and keyfile" wipe
|
||||
# [0]$KEY1 [1]key0
|
||||
$CRYPTSETUP -q luksFormat $LOOPDEV $KEY1 --key-slot 0 || fail
|
||||
echo $PWD1 | $CRYPTSETUP luksAddKey $LOOPDEV -d $KEY1 --key-slot 1 || fail
|
||||
$CRYPTSETUP -q luksFormat $LOOPDEV $KEY1 -i1 --key-slot 0 || fail
|
||||
echo $PWD1 | $CRYPTSETUP luksAddKey $LOOPDEV -i1 -d $KEY1 --key-slot 1 || fail
|
||||
# keyfile [0] / keyfile [0]
|
||||
$CRYPTSETUP luksChangeKey $LOOPDEV -d $KEY1 $KEY2 --key-slot 0 || fail
|
||||
$CRYPTSETUP luksChangeKey $LOOPDEV -i1 -d $KEY1 $KEY2 --key-slot 0 || fail
|
||||
# passphrase [1] / passphrase [1]
|
||||
echo -e "$PWD1\n$PWD2\n" | $CRYPTSETUP luksChangeKey $LOOPDEV --key-slot 1 || fail
|
||||
echo -e "$PWD1\n$PWD2\n" | $CRYPTSETUP luksChangeKey $LOOPDEV -i1 --key-slot 1 || fail
|
||||
# keyfile [0] / keyfile [new]
|
||||
$CRYPTSETUP luksChangeKey $LOOPDEV -d $KEY2 $KEY1 || fail
|
||||
$CRYPTSETUP luksChangeKey $LOOPDEV -i1 -d $KEY2 $KEY1 || fail
|
||||
$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 0: DISABLED" || fail
|
||||
# passphrase [1] / passphrase [new]
|
||||
echo -e "$PWD2\n$PWD1\n" | $CRYPTSETUP luksChangeKey $LOOPDEV || fail
|
||||
echo -e "$PWD2\n$PWD1\n" | $CRYPTSETUP luksChangeKey -i1 $LOOPDEV || fail
|
||||
$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 1: DISABLED" || fail
|
||||
# use all slots
|
||||
$CRYPTSETUP luksAddKey $LOOPDEV -d $KEY1 $KEY2 -i 1 || fail
|
||||
@@ -432,8 +453,8 @@ $CRYPTSETUP luksAddKey $LOOPDEV -d $KEY1 $KEY2 -i 1 || fail
|
||||
$CRYPTSETUP luksAddKey $LOOPDEV -d $KEY1 $KEY2 -i 1 || fail
|
||||
$CRYPTSETUP luksAddKey $LOOPDEV -d $KEY1 $KEY2 -i 1 || fail
|
||||
# still allows replace
|
||||
$CRYPTSETUP luksChangeKey $LOOPDEV -d $KEY1 $KEY2 || fail
|
||||
$CRYPTSETUP luksChangeKey $LOOPDEV -d $KEY1 $KEY2 2>/dev/null && fail
|
||||
$CRYPTSETUP luksChangeKey $LOOPDEV -i1 -d $KEY1 $KEY2 || fail
|
||||
$CRYPTSETUP luksChangeKey $LOOPDEV -i1 -d $KEY1 $KEY2 2>/dev/null && fail
|
||||
|
||||
prepare "[24] Keyfile limit" wipe
|
||||
$CRYPTSETUP -q luksFormat -i1 $LOOPDEV $KEY1 --key-slot 0 -l 13 || fail
|
||||
@@ -488,7 +509,7 @@ $CRYPTSETUP luksResume $DEV_NAME 2>/dev/null && fail
|
||||
$CRYPTSETUP -q remove $DEV_NAME || fail
|
||||
$CRYPTSETUP luksSuspend $DEV_NAME 2>/dev/null && fail
|
||||
# LUKS
|
||||
echo $PWD1 | $CRYPTSETUP -q luksFormat $LOOPDEV || fail
|
||||
echo $PWD1 | $CRYPTSETUP -q luksFormat -i1 $LOOPDEV || fail
|
||||
echo $PWD1 | $CRYPTSETUP -q luksOpen $LOOPDEV $DEV_NAME || fail
|
||||
$CRYPTSETUP luksSuspend $DEV_NAME || fail
|
||||
$CRYPTSETUP -q resize $DEV_NAME 2>/dev/null && fail
|
||||
@@ -498,14 +519,14 @@ $CRYPTSETUP -q luksClose $DEV_NAME || fail
|
||||
|
||||
prepare "[27] luksOpen with specified key slot number" wipe
|
||||
# first, let's try passphrase option
|
||||
echo $PWD3 | $CRYPTSETUP luksFormat -S 5 $LOOPDEV || fail
|
||||
echo $PWD3 | $CRYPTSETUP luksFormat -i1 -S 5 $LOOPDEV || fail
|
||||
check $LUKS_HEADER $KEY_SLOT5 $KEY_MATERIAL5
|
||||
echo $PWD3 | $CRYPTSETUP luksOpen -S 4 $LOOPDEV $DEV_NAME && fail
|
||||
[ -b /dev/mapper/$DEV_NAME ] && fail
|
||||
echo $PWD3 | $CRYPTSETUP luksOpen -S 5 $LOOPDEV $DEV_NAME || fail
|
||||
check_exists
|
||||
$CRYPTSETUP luksClose $DEV_NAME || fail
|
||||
echo -e "$PWD3\n$PWD1" | $CRYPTSETUP luksAddKey -S 0 $LOOPDEV || fail
|
||||
echo -e "$PWD3\n$PWD1" | $CRYPTSETUP luksAddKey -i1 -S 0 $LOOPDEV || fail
|
||||
check $LUKS_HEADER $KEY_SLOT0 $KEY_MATERIAL0
|
||||
echo $PWD3 | $CRYPTSETUP luksOpen -S 0 $LOOPDEV $DEV_NAME && fail
|
||||
[ -b /dev/mapper/$DEV_NAME ] && fail
|
||||
@@ -514,7 +535,7 @@ echo $PWD1 | $CRYPTSETUP luksOpen -S 5 $LOOPDEV $DEV_NAME && fail
|
||||
# second, try it with keyfiles
|
||||
$CRYPTSETUP luksFormat -q -S 5 -d $KEY5 $LOOPDEV || fail
|
||||
check $LUKS_HEADER $KEY_SLOT5 $KEY_MATERIAL5
|
||||
$CRYPTSETUP luksAddKey -S 1 -d $KEY5 $LOOPDEV $KEY1 || fail
|
||||
$CRYPTSETUP luksAddKey -i1 -S 1 -d $KEY5 $LOOPDEV $KEY1 || fail
|
||||
check $LUKS_HEADER $KEY_SLOT1 $KEY_MATERIAL1
|
||||
$CRYPTSETUP luksOpen -S 5 -d $KEY5 $LOOPDEV $DEV_NAME || fail
|
||||
check_exists
|
||||
@@ -533,9 +554,15 @@ echo $PWD1 | $CRYPTSETUP luksFormat -i1 $LOOPDEV --header $HEADER_IMG --align-pa
|
||||
echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV --header $HEADER_IMG $DEV_NAME || fail
|
||||
$CRYPTSETUP -q resize $DEV_NAME --size 100 --header $HEADER_IMG || fail
|
||||
$CRYPTSETUP -q status $DEV_NAME --header $HEADER_IMG | grep "size:" | grep -q "100 sectors" || fail
|
||||
$CRYPTSETUP -q status $DEV_NAME | grep "type:" | grep -q "n/a" || fail
|
||||
$CRYPTSETUP -q status $DEV_NAME | grep "size:" | grep -q "100 sectors" || fail
|
||||
$CRYPTSETUP luksSuspend $DEV_NAME --header $HEADER_IMG || fail
|
||||
echo $PWD1 | $CRYPTSETUP luksResume $DEV_NAME --header $HEADER_IMG || fail
|
||||
$CRYPTSETUP luksClose $DEV_NAME || fail
|
||||
echo $PWD1 | $CRYPTSETUP luksAddKey -i1 -S 5 _fakedev_ --header $HEADER_IMG $KEY5 || fail
|
||||
$CRYPTSETUP luksDump _fakedev_ --header $HEADER_IMG | grep -q "Key Slot 5: ENABLED" || fail
|
||||
$CRYPTSETUP luksKillSlot -q _fakedev_ --header $HEADER_IMG 5 || fail
|
||||
$CRYPTSETUP luksDump _fakedev_ --header $HEADER_IMG | grep -q "Key Slot 5: DISABLED" || fail
|
||||
|
||||
prepare "[29] Repair metadata" wipe
|
||||
$CRYPTSETUP -q luksFormat -i1 $LOOPDEV $KEY1 --key-slot 0 || fail
|
||||
@@ -546,5 +573,14 @@ $CRYPTSETUP -q repair $LOOPDEV >/dev/null 2>&1 || fail
|
||||
$CRYPTSETUP luksOpen -d $KEY1 $LOOPDEV $DEV_NAME || fail
|
||||
$CRYPTSETUP luksClose $DEV_NAME || fail
|
||||
|
||||
prepare "[30] LUKS erase" wipe
|
||||
$CRYPTSETUP -q luksFormat -i1 $LOOPDEV $KEY5 --key-slot 5 || fail
|
||||
$CRYPTSETUP luksAddKey -i1 -S 1 -d $KEY5 $LOOPDEV $KEY1 || fail
|
||||
$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 1: ENABLED" || fail
|
||||
$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 5: ENABLED" || fail
|
||||
$CRYPTSETUP luksErase -q $LOOPDEV || fail
|
||||
$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 1: DISABLED" || fail
|
||||
$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 5: DISABLED" || fail
|
||||
|
||||
remove_mapping
|
||||
exit 0
|
||||
|
||||
86
tests/device-test
Executable file
86
tests/device-test
Executable file
@@ -0,0 +1,86 @@
|
||||
#!/bin/bash
|
||||
|
||||
CRYPTSETUP="../src/cryptsetup"
|
||||
MNT_DIR="./mnt_luks"
|
||||
DEV_NAME="dummy"
|
||||
PWD1="93R4P4pIqAH8"
|
||||
PWD2="mymJeD8ivEhE"
|
||||
|
||||
cleanup() {
|
||||
[ -b /dev/mapper/$DEV_NAME ] && dmsetup remove $DEV_NAME
|
||||
udevadm settle >/dev/null 2>&1
|
||||
if [ -d "$MNT_DIR" ] ; then
|
||||
umount -f $MNT_DIR 2>/dev/null
|
||||
rmdir $MNT_DIR 2>/dev/null
|
||||
fi
|
||||
sleep 2
|
||||
}
|
||||
|
||||
fail()
|
||||
{
|
||||
if [ -n "$1" ] ; then echo "FAIL $1" ; else echo "FAIL" ; fi
|
||||
cleanup
|
||||
exit 100
|
||||
}
|
||||
|
||||
skip()
|
||||
{
|
||||
echo "TEST SKIPPED: $1"
|
||||
cleanup
|
||||
exit 0
|
||||
}
|
||||
|
||||
format() # key_bits expected [forced]
|
||||
{
|
||||
dd if=/dev/zero of=$DEV bs=1M count=5 >/dev/null 2>&1
|
||||
|
||||
echo $PWD1 | $CRYPTSETUP luksFormat $DEV -q -i1 -c aes-cbc-essiv:sha256
|
||||
[ $? -ne 0 ] && fail "Format failed."
|
||||
|
||||
# test some operation, just in case
|
||||
echo -e "$PWD1\n$PWD2" | $CRYPTSETUP luksAddKey $DEV -i1 --key-slot 1
|
||||
[ $? -ne 0 ] && fail "Keyslot add failed."
|
||||
|
||||
$CRYPTSETUP -q luksKillSlot $DEV 1
|
||||
[ $? -ne 0 ] && fail "Keyslot removal failed."
|
||||
}
|
||||
|
||||
if [ $(id -u) != 0 ]; then
|
||||
echo "WARNING: You must be root to run this test, test skipped."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
[ ! -d $MNT_DIR ] && mkdir $MNT_DIR
|
||||
|
||||
echo "[1] Using tmpfs for image"
|
||||
DEV="$MNT_DIR/test.img"
|
||||
mount -t tmpfs none $MNT_DIR || skip "Mounting tmpfs not available."
|
||||
format
|
||||
|
||||
echo "[2] Kernel dmcrypt performace options"
|
||||
echo -e "$PWD1" | $CRYPTSETUP open --type plain $DEV $DEV_NAME --perf-same_cpu_crypt >/dev/null 2>&1
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "TEST SKIPPED: dmcrypt options not available"
|
||||
else
|
||||
$CRYPTSETUP close $DEV_NAME || fail
|
||||
# plain
|
||||
echo -e "$PWD1" | $CRYPTSETUP open --type plain $DEV $DEV_NAME --perf-same_cpu_crypt --perf-submit_from_crypt_cpus || fail
|
||||
$CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt || fail
|
||||
$CRYPTSETUP status $DEV_NAME | grep -q submit_from_crypt_cpus || fail
|
||||
$CRYPTSETUP close $DEV_NAME || fail
|
||||
echo -e "$PWD1" | $CRYPTSETUP open --type plain $DEV $DEV_NAME --perf-same_cpu_crypt --allow-discards || fail
|
||||
$CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt || fail
|
||||
$CRYPTSETUP status $DEV_NAME | grep -q discards || fail
|
||||
$CRYPTSETUP close $DEV_NAME || fail
|
||||
# LUKS
|
||||
echo -e "$PWD1" | $CRYPTSETUP open --type luks1 $DEV $DEV_NAME --perf-same_cpu_crypt --perf-submit_from_crypt_cpus || fail
|
||||
$CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt || fail
|
||||
$CRYPTSETUP status $DEV_NAME | grep -q submit_from_crypt_cpus || fail
|
||||
$CRYPTSETUP close $DEV_NAME || fail
|
||||
echo -e "$PWD1" | $CRYPTSETUP open --type luks1 $DEV $DEV_NAME --perf-same_cpu_crypt --allow-discards || fail
|
||||
$CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt || fail
|
||||
$CRYPTSETUP status $DEV_NAME | grep -q discards || fail
|
||||
$CRYPTSETUP close $DEV_NAME || fail
|
||||
fi
|
||||
|
||||
cleanup
|
||||
@@ -27,7 +27,7 @@ add_device() {
|
||||
fi
|
||||
|
||||
sleep 2
|
||||
DEV=$(grep scsi_debug /sys/block/*/device/model | cut -f4 -d /)
|
||||
DEV=$(grep -l -e scsi_debug /sys/block/*/device/model | cut -f4 -d /)
|
||||
|
||||
DEV="/dev/$DEV"
|
||||
[ -b $DEV ] || fail "Cannot find $DEV."
|
||||
|
||||
BIN
tests/img_fs_ext4.img.bz2
Normal file
BIN
tests/img_fs_ext4.img.bz2
Normal file
Binary file not shown.
BIN
tests/img_fs_vfat.img.bz2
Normal file
BIN
tests/img_fs_vfat.img.bz2
Normal file
Binary file not shown.
BIN
tests/img_fs_xfs.img.bz2
Normal file
BIN
tests/img_fs_xfs.img.bz2
Normal file
Binary file not shown.
84
tests/luks1-compat-test
Executable file
84
tests/luks1-compat-test
Executable file
@@ -0,0 +1,84 @@
|
||||
#!/bin/bash
|
||||
|
||||
# check luks1 images parsing
|
||||
|
||||
# NOTE: if image with whirlpool hash fails, check
|
||||
# that you are not using old gcrypt with flawed whirlpool
|
||||
# (see cryptsetup debug output)
|
||||
|
||||
CRYPTSETUP=../src/cryptsetup
|
||||
TST_DIR=luks1-images
|
||||
MAP=luks1tst
|
||||
KEYFILE=keyfile1
|
||||
|
||||
function remove_mapping()
|
||||
{
|
||||
[ -b /dev/mapper/$MAP ] && dmsetup remove $MAP
|
||||
}
|
||||
|
||||
function fail()
|
||||
{
|
||||
[ -n "$1" ] && echo "$1"
|
||||
echo " [FAILED]"
|
||||
remove_mapping
|
||||
exit 2
|
||||
}
|
||||
|
||||
function skip()
|
||||
{
|
||||
[ -n "$1" ] && echo "$1"
|
||||
echo "Test skipped."
|
||||
exit 0
|
||||
}
|
||||
|
||||
function test_one()
|
||||
{
|
||||
$CRYPTSETUP benchmark -c "$1" -s "$2" | grep -v "#" || skip
|
||||
}
|
||||
|
||||
function test_required()
|
||||
{
|
||||
which lsblk >/dev/null 2>&1 || skip "WARNING: lsblk tool required."
|
||||
|
||||
echo "REQUIRED KDF TEST"
|
||||
$CRYPTSETUP benchmark -h whirlpool | grep "N/A" && skip
|
||||
|
||||
echo "REQUIRED CIPHERS TEST"
|
||||
echo "# Algorithm | Key | Encryption | Decryption"
|
||||
|
||||
test_one aes-xts 256
|
||||
test_one twofish-xts 256
|
||||
test_one serpent-xts 256
|
||||
test_one aes-cbc 256
|
||||
test_one aes-lrw 256
|
||||
}
|
||||
|
||||
export LANG=C
|
||||
|
||||
if [ $(id -u) != 0 ]; then
|
||||
echo "WARNING: You must be root to run activation part of test, test skipped."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
test_required
|
||||
[ ! -d $TST_DIR ] && tar xjf luks1-images.tar.bz2
|
||||
|
||||
echo "ACTIVATION FS UUID CHECK"
|
||||
for file in $(ls $TST_DIR/luks1_*) ; do
|
||||
echo -n " $file"
|
||||
$CRYPTSETUP luksOpen -d $TST_DIR/$KEYFILE $file $MAP 2>/dev/null
|
||||
ret=$?
|
||||
# ignore missing whirlpool (pwd failed is exit code 2)
|
||||
[ $ret -eq 1 ] && (echo $file | grep -q -e "whirlpool") && echo " [N/A]" && continue
|
||||
# ignore flawed whirlpool (pwd failed is exit code 2)
|
||||
[ $ret -eq 2 ] && (echo $file | grep -q -e "whirlpool") && \
|
||||
($CRYPTSETUP luksDump $file --debug | grep -q -e "flawed whirlpool") && \
|
||||
echo " [IGNORED (flawed Whirlpool library)]" && continue
|
||||
[ $ret -ne 0 ] && fail
|
||||
$CRYPTSETUP status $MAP >/dev/null || fail
|
||||
$CRYPTSETUP status /dev/mapper/$MAP >/dev/null || fail
|
||||
UUID=$(lsblk -n -o UUID /dev/mapper/$MAP)
|
||||
$CRYPTSETUP remove $MAP || fail
|
||||
[ "$UUID" != "DEAD-BABE" ] && fail "UUID check failed."
|
||||
echo " [OK]"
|
||||
done
|
||||
BIN
tests/luks1-images.tar.bz2
Normal file
BIN
tests/luks1-images.tar.bz2
Normal file
Binary file not shown.
@@ -6,6 +6,7 @@ CRYPTSETUP=../src/cryptsetup
|
||||
DEV_NAME=dmc_test
|
||||
HEADER_IMG=mode-test.img
|
||||
PASSWORD=3xrododenron
|
||||
PASSWORD1=$PASSWORD
|
||||
|
||||
# cipher-chainmode-ivopts:ivmode
|
||||
CIPHERS="aes twofish serpent"
|
||||
@@ -52,7 +53,7 @@ add_device() {
|
||||
dmcrypt_check() # device outstring
|
||||
{
|
||||
X=$(dmsetup table $1 2>/dev/null | sed 's/.*: //' | cut -d' ' -f 4)
|
||||
if [ $X = $2 ] ; then
|
||||
if [ "$X" = $2 ] ; then
|
||||
echo -n "[table OK]"
|
||||
else
|
||||
echo "[table FAIL]"
|
||||
@@ -65,7 +66,7 @@ dmcrypt_check() # device outstring
|
||||
echo -n "[status OK]"
|
||||
else
|
||||
echo "[status FAIL]"
|
||||
echo " Expecting $2 got $X."
|
||||
echo " Expecting $2 got \"$X\"."
|
||||
fail
|
||||
fi
|
||||
|
||||
@@ -134,10 +135,12 @@ dmcrypt aes aes-cbc-plain
|
||||
dmcrypt aes-plain aes-cbc-plain
|
||||
|
||||
# empty cipher
|
||||
PASSWORD=""
|
||||
dmcrypt null cipher_null-ecb
|
||||
dmcrypt cipher_null cipher_null-cbc-plain
|
||||
dmcrypt cipher_null-ecb
|
||||
|
||||
PASSWORD=$PASSWORD1
|
||||
# codebook doesn't support IV at all
|
||||
for cipher in $CIPHERS ; do
|
||||
dmcrypt "$cipher-ecb"
|
||||
|
||||
@@ -20,13 +20,20 @@ cleanup() {
|
||||
exit $1
|
||||
}
|
||||
|
||||
crypt_key() # hash keysize pwd/file name outkey [limit]
|
||||
function fail()
|
||||
{
|
||||
echo " $1 [FAILED]"
|
||||
cleanup 2
|
||||
}
|
||||
|
||||
crypt_key() # hash keysize pwd/file name outkey [limit] [offset]
|
||||
{
|
||||
DEV2=$DEV_NAME"_x"
|
||||
LIMIT=""
|
||||
MODE=aes-cbc-essiv:sha256
|
||||
[ $2 -gt 256 ] && MODE=aes-xts-plain
|
||||
[ -n "$6" ] && LIMIT="-l $6"
|
||||
[ -n "$7" ] && LIMIT="$LIMIT --keyfile-offset $7"
|
||||
|
||||
echo -n "HASH: $1 KSIZE: $2 / $3"
|
||||
case "$3" in
|
||||
@@ -46,12 +53,21 @@ crypt_key() # hash keysize pwd/file name outkey [limit]
|
||||
cat $4 | $CRYPTSETUP create -c $MODE -h $1 -s $2 $LIMIT $DEV2 /dev/mapper/$DEV_NAME 2>/dev/null
|
||||
ret=$?
|
||||
;;
|
||||
file)
|
||||
$CRYPTSETUP create -c $MODE -d $4 -h $1 -s $2 $DEV2 /dev/mapper/$DEV_NAME 2>/dev/null
|
||||
cat-)
|
||||
cat $4 | $CRYPTSETUP create -c $MODE -h $1 -s $2 $LIMIT $DEV2 -d - /dev/mapper/$DEV_NAME 2>/dev/null
|
||||
ret=$?
|
||||
;;
|
||||
file)
|
||||
$CRYPTSETUP create -q -c $MODE -d $4 -h $1 -s $2 $DEV2 /dev/mapper/$DEV_NAME 2>/dev/null
|
||||
ret=$?
|
||||
;;
|
||||
failpwd)
|
||||
echo -e -n "$4" | $CRYPTSETUP create -c $MODE -h $1 -s $2 $LIMIT $DEV2 /dev/mapper/$DEV_NAME 2>/dev/null && fail "Expecting failure"
|
||||
echo " [OK]"
|
||||
return
|
||||
;;
|
||||
*)
|
||||
fail
|
||||
fail ""
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -107,11 +123,15 @@ crypt_key unknown* 256 file /dev/zero 00000000000000000000000000000000000000000
|
||||
crypt_key sha256:20 256 pwd "xxx" cd2eb0837c9b4c962c22d2ff8b5441b7b4580588000000000000000000000000
|
||||
crypt_key sha256:32 256 pwd "xxx" cd2eb0837c9b4c962c22d2ff8b5441b7b45805887f051d39bf133b583baf6860
|
||||
|
||||
crypt_key sha256: 256 failpwd "xxx" x
|
||||
crypt_key sha256:xx 256 failpwd "xxx" x
|
||||
|
||||
# key file, 80 chars
|
||||
echo -n -e "0123456789abcdef\n\x01\x00\x03\xff\xff\r\xff\xff\n\r" \
|
||||
"2352j3rkjhadcfasc823rqaw7e1 3dq sdq3d 2dkjqw3h2=====" >$KEY_FILE
|
||||
KEY_FILE_HEX="303132333435363738396162636465660a010003ffff0dffff0a0d20323335326a33726b6a686164636661736338323372716177376531203364712073647133"
|
||||
|
||||
# ignore hash if keyfile is specified
|
||||
crypt_key ripemd160 256 file $KEY_FILE ${KEY_FILE_HEX:0:64}
|
||||
crypt_key sha256 256 file $KEY_FILE ${KEY_FILE_HEX:0:64}
|
||||
crypt_key sha256 128 file $KEY_FILE ${KEY_FILE_HEX:0:32}
|
||||
@@ -120,7 +140,27 @@ crypt_key sha256 512 file $KEY_FILE $KEY_FILE_HEX
|
||||
# stdin can be limited
|
||||
crypt_key plain 128 cat /dev/zero 00000000000000000000000000000000 16
|
||||
crypt_key plain 128 cat /dev/zero 00000000000000000000000000000000 17
|
||||
|
||||
# read key only up to \n
|
||||
crypt_key plain 128 cat $KEY_FILE ${KEY_FILE_HEX:0:28}0000 14
|
||||
|
||||
# read full key, ignore keyfile length
|
||||
crypt_key plain 128 cat- $KEY_FILE ${KEY_FILE_HEX:0:32}
|
||||
crypt_key plain 128 cat- $KEY_FILE ${KEY_FILE_HEX:0:32} 14
|
||||
|
||||
# but do not ignore hash if keysgfile is "-"
|
||||
crypt_key sha256 128 cat- $KEY_FILE f3b827c8a6f159ad8c8ed5bd5ab3f8c5
|
||||
crypt_key sha256 128 cat- $KEY_FILE f3b827c8a6f159ad8c8ed5bd5ab3f8c5 0
|
||||
crypt_key sha256 128 cat- $KEY_FILE f3b827c8a6f159ad8c8ed5bd5ab3f8c5 80
|
||||
crypt_key sha256 128 cat- $KEY_FILE a82c9227cc54c7475620ce85ba1fca1e 14
|
||||
crypt_key sha256 128 cat- $KEY_FILE 7df3f4a41a33805596be85c781cac3b4 14 2
|
||||
crypt_key sha256 128 cat- $KEY_FILE ebbe65a178e886ddbb778e0a5538db72 40 40
|
||||
|
||||
# limiting plain (no hash)
|
||||
crypt_key plain 256 pwd "xxxxxxxx" 7878787878787878000000000000000000000000000000000000000000000000
|
||||
crypt_key plain:2 256 pwd "xxxxxxxx" 7878000000000000000000000000000000000000000000000000000000000000
|
||||
crypt_key plain:9 256 failpwd "xxxxxxxx" x
|
||||
|
||||
crypt_key sha256 128 cat $KEY_FILE a82c9227cc54c7475620ce85ba1fca1e 14
|
||||
crypt_key sha256:14 128 cat $KEY_FILE a82c9227cc54c7475620ce85ba1f0000 14
|
||||
|
||||
|
||||
@@ -6,22 +6,38 @@ REENC=../src/cryptsetup-reencrypt
|
||||
DEV_NAME=reenc9768
|
||||
DEV_NAME2=reenc1273
|
||||
IMG=reenc-data
|
||||
ORIG_IMG=reenc-data-orig
|
||||
KEY1=key1
|
||||
PWD1="93R4P4pIqAH8"
|
||||
PWD2="1cND4319812f"
|
||||
PWD3="1-9Qu5Ejfnqv"
|
||||
|
||||
MNT_DIR=./mnt_luks
|
||||
START_DIR=$(pwd)
|
||||
|
||||
function del_scsi_device()
|
||||
{
|
||||
rmmod scsi_debug 2>/dev/null
|
||||
sleep 2
|
||||
}
|
||||
|
||||
function remove_mapping()
|
||||
{
|
||||
[ -b /dev/mapper/$DEV_NAME2 ] && dmsetup remove $DEV_NAME2
|
||||
[ -b /dev/mapper/$DEV_NAME ] && dmsetup remove $DEV_NAME
|
||||
[ ! -z "$LOOPDEV1" ] && losetup -d $LOOPDEV1 >/dev/null 2>&1
|
||||
rm -f $IMG $KEY1 >/dev/null 2>&1
|
||||
rm -f $IMG $ORIG_IMG $KEY1 >/dev/null 2>&1
|
||||
umount $MNT_DIR > /dev/null 2>&1
|
||||
rmdir $MNT_DIR > /dev/null 2>&1
|
||||
LOOPDEV1=""
|
||||
del_scsi_device
|
||||
}
|
||||
|
||||
function fail()
|
||||
{
|
||||
[ -n "$1" ] && echo "$1"
|
||||
echo "FAILED"
|
||||
cd $START_DIR
|
||||
remove_mapping
|
||||
exit 2
|
||||
}
|
||||
@@ -32,12 +48,25 @@ function skip()
|
||||
exit 0
|
||||
}
|
||||
|
||||
function add_scsi_device() {
|
||||
del_scsi_device
|
||||
modprobe scsi_debug $@
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "This kernel seems to not support proper scsi_debug module, test skipped."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
sleep 2
|
||||
SCSI_DEV="/dev/"$(grep -l -e scsi_debug /sys/block/*/device/model | cut -f4 -d /)
|
||||
[ -b $SCSI_DEV ] || fail "Cannot find $SCSI_DEV."
|
||||
}
|
||||
|
||||
function open_crypt()
|
||||
{
|
||||
if [ -n "$1" ] ; then
|
||||
echo "$1" | $CRYPTSETUP luksOpen $LOOPDEV1 $DEV_NAME || fail
|
||||
else
|
||||
$CRYPTSETUP luksOpen -d key1 $LOOPDEV1 $DEV_NAME || fail
|
||||
$CRYPTSETUP luksOpen -d $KEY1 $LOOPDEV1 $DEV_NAME || fail
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -50,6 +79,7 @@ function wipe() # $1 pass
|
||||
{
|
||||
open_crypt $1
|
||||
wipe_dev /dev/mapper/$DEV_NAME
|
||||
udevadm settle >/dev/null 2>&1
|
||||
$CRYPTSETUP luksClose $DEV_NAME || fail
|
||||
}
|
||||
|
||||
@@ -80,17 +110,107 @@ function check_hash() # $1 pwd, $2 hash
|
||||
$CRYPTSETUP remove $DEV_NAME || fail
|
||||
}
|
||||
|
||||
function backup_orig()
|
||||
{
|
||||
sync
|
||||
losetup -d $LOOPDEV1
|
||||
cp $IMG $ORIG_IMG
|
||||
losetup $LOOPDEV1 $IMG
|
||||
}
|
||||
|
||||
function rollback()
|
||||
{
|
||||
sync
|
||||
losetup -d $LOOPDEV1
|
||||
cp $ORIG_IMG $IMG
|
||||
losetup $LOOPDEV1 $IMG
|
||||
}
|
||||
|
||||
function check_slot() #space separeted list of ENABLED key slots
|
||||
{
|
||||
local _KS0=DISABLED
|
||||
local _KS1=$_KS0 _KS2=$_KS0 _KS3=$_KS0 _KS4=$_KS0 _KS5=$_KS0 _KS6=$_KS0 _KS7=$_KS0
|
||||
local _tmp
|
||||
|
||||
for _tmp in $*; do
|
||||
eval _KS$_tmp=ENABLED
|
||||
done
|
||||
|
||||
local _out=$($CRYPTSETUP luksDump $LOOPDEV1 | grep -e "Key Slot" | cut -d ' ' -f 4)
|
||||
|
||||
local _i=0
|
||||
for _tmp in $_out; do
|
||||
eval local _orig="\${_KS${_i}}"
|
||||
if [ "$_tmp" != "$_orig" ]; then
|
||||
echo "Keyslot $_i is $_tmp, expected result: $_orig"
|
||||
return 1
|
||||
fi
|
||||
_i=$[_i+1]
|
||||
done
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
function simple_scsi_reenc()
|
||||
{
|
||||
echo -n "$1"
|
||||
echo $PWD1 | $CRYPTSETUP luksFormat -i1 $SCSI_DEV || fail
|
||||
|
||||
echo $PWD1 | $CRYPTSETUP luksOpen $SCSI_DEV $DEV_NAME || fail
|
||||
HASH=$(sha256sum /dev/mapper/$DEV_NAME | cut -d' ' -f 1)
|
||||
$CRYPTSETUP luksClose $DEV_NAME || fail
|
||||
|
||||
echo $PWD1 | $REENC -q -i 1 $SCSI_DEV || fail
|
||||
|
||||
echo $PWD1 | $CRYPTSETUP luksOpen $SCSI_DEV $DEV_NAME || fail
|
||||
check_hash_dev /dev/mapper/$DEV_NAME $HASH
|
||||
$CRYPTSETUP luksClose $DEV_NAME || fail
|
||||
}
|
||||
|
||||
function mount_and_test() {
|
||||
test -d $MNT_DIR || mkdir -p $MNT_DIR
|
||||
mount $@ $MNT_DIR 2>/dev/null || {
|
||||
echo -n "failed to mount [SKIP]"
|
||||
return 0
|
||||
}
|
||||
rm $MNT_DIR/* 2>/dev/null
|
||||
cd $MNT_DIR
|
||||
echo $PWD2 | $START_DIR/$REENC $LOOPDEV1 -q --use-fsync --use-directio --write-log || return 1
|
||||
cd $START_DIR
|
||||
umount $MNT_DIR
|
||||
echo -n [OK]
|
||||
}
|
||||
|
||||
function test_logging_tmpfs() {
|
||||
echo -n "[tmpfs]"
|
||||
mount_and_test -t tmpfs none -o size=$[25*1024*1024] || return 1
|
||||
echo
|
||||
}
|
||||
|
||||
function test_logging() {
|
||||
echo -n "$1:"
|
||||
for img in $(ls img_fs*img.bz2) ; do
|
||||
wipefs -a $SCSI_DEV > /dev/null
|
||||
echo -n "[${img%.img.bz2}]"
|
||||
bzip2 -d -c $img | dd of=$SCSI_DEV >/dev/null 2>&1
|
||||
mount_and_test $SCSI_DEV || return 1
|
||||
done
|
||||
echo
|
||||
}
|
||||
|
||||
[ $(id -u) != 0 ] && skip "WARNING: You must be root to run this test, test skipped."
|
||||
[ ! -x "$REENC" ] && skip "Cannot find $REENC, test skipped."
|
||||
which wipefs >/dev/null || skip "Cannot find wipefs, test skipped."
|
||||
|
||||
# REENCRYPTION tests
|
||||
|
||||
HASH1=b69dae56a14d1a8314ed40664c4033ea0a550eea2673e04df42a66ac6b9faf2c
|
||||
HASH2=d85ef2a08aeac2812a648deb875485a6e3848fc3d43ce4aa380937f08199f86b
|
||||
HASH3=e4e5749032a5163c45125eccf3e8598ba5ed840df442c97e1d5ad4ad84359605
|
||||
HASH4=2daeb1f36095b44b318410b3f4e8b5d989dcc7bb023d1426c492dab0a3053e74
|
||||
|
||||
echo "[1] Reencryption"
|
||||
prepare 8192
|
||||
prepare 8192
|
||||
echo $PWD1 | $CRYPTSETUP -q luksFormat -s 128 -c aes-cbc-plain -i 1 --align-payload 4096 $LOOPDEV1 || fail
|
||||
wipe $PWD1
|
||||
check_hash $PWD1 $HASH1
|
||||
@@ -112,12 +232,15 @@ echo $PWD1 | $REENC $LOOPDEV1 -q -i 1 || fail
|
||||
check_hash $PWD1 $HASH2
|
||||
|
||||
echo "[3] Reencryption with keyfile"
|
||||
echo $PWD1 | $CRYPTSETUP -q luksFormat -d key1 -c aes-cbc-essiv:sha256 -s 128 -i 1 --align-payload 4096 $LOOPDEV1 || fail
|
||||
echo $PWD1 | $CRYPTSETUP -q luksFormat -d $KEY1 -c aes-cbc-essiv:sha256 -s 128 -i 1 --align-payload 4096 $LOOPDEV1 || fail
|
||||
wipe
|
||||
check_hash "" $HASH1
|
||||
echo $PWD1 | $CRYPTSETUP -q luksAddKey -d key1 $LOOPDEV1 || fail
|
||||
$REENC $LOOPDEV1 -d key1 -S 0 -i 1 -q || fail
|
||||
echo $PWD1 | $CRYPTSETUP -q luksAddKey -d $KEY1 $LOOPDEV1 || fail
|
||||
$REENC $LOOPDEV1 -d $KEY1 -i 1 -q 2>/dev/null && fail
|
||||
$REENC $LOOPDEV1 -d $KEY1 -S 0 -i 1 -q || fail
|
||||
check_hash "" $HASH1
|
||||
check_slot 0 || fail "Only keyslot 0 expected to be enabled"
|
||||
$REENC $LOOPDEV1 -d $KEY1 -i 1 -q || fail
|
||||
# FIXME echo $PWD1 | $REENC ...
|
||||
|
||||
echo "[4] Encryption of not yet encrypted device"
|
||||
@@ -131,5 +254,75 @@ dmsetup remove $DEV_NAME2 || fail
|
||||
echo $PWD1 | $REENC $LOOPDEV1 -c aes-cbc-essiv:sha256 -s 128 --new --reduce-device-size "$OFFSET"S -q
|
||||
check_hash $PWD1 $HASH3
|
||||
|
||||
echo "[5] Reencryption using specific keyslot"
|
||||
echo $PWD2 | $CRYPTSETUP -q luksFormat -i 1 $LOOPDEV1 || fail
|
||||
echo -e "$PWD2\n$PWD1" | $CRYPTSETUP -q luksAddKey -i 1 -S 1 $LOOPDEV1 || fail
|
||||
echo -e "$PWD2\n$PWD2" | $CRYPTSETUP -q luksAddKey -i 1 -S 2 $LOOPDEV1 || fail
|
||||
echo -e "$PWD2\n$PWD1" | $CRYPTSETUP -q luksAddKey -i 1 -S 3 $LOOPDEV1 || fail
|
||||
echo -e "$PWD2\n$PWD2" | $CRYPTSETUP -q luksAddKey -i 1 -S 4 $LOOPDEV1 || fail
|
||||
echo -e "$PWD2\n$PWD1" | $CRYPTSETUP -q luksAddKey -i 1 -S 5 $LOOPDEV1 || fail
|
||||
echo -e "$PWD2\n$PWD2" | $CRYPTSETUP -q luksAddKey -i 1 -S 6 $LOOPDEV1 || fail
|
||||
echo -e "$PWD2\n$PWD3" | $CRYPTSETUP -q luksAddKey -i 1 -S 7 $LOOPDEV1 || fail
|
||||
backup_orig
|
||||
echo $PWD2 | $REENC -i 1 -S 0 -q $LOOPDEV1 || fail
|
||||
check_slot 0 || fail "Only keyslot 0 expected to be enabled"
|
||||
wipe $PWD2
|
||||
rollback
|
||||
echo $PWD1 | $REENC -i 1 -S 1 -q $LOOPDEV1 || fail
|
||||
check_slot 1 || fail "Only keyslot 1 expected to be enabled"
|
||||
wipe $PWD1
|
||||
rollback
|
||||
echo $PWD2 | $REENC -i 1 -S 6 -q $LOOPDEV1 || fail
|
||||
check_slot 6 || fail "Only keyslot 6 expected to be enabled"
|
||||
wipe $PWD2
|
||||
rollback
|
||||
echo $PWD3 | $REENC -i 1 -S 7 -q $LOOPDEV1 || fail
|
||||
check_slot 7 || fail "Only keyslot 7 expected to be enabled"
|
||||
wipe $PWD3
|
||||
rollback
|
||||
|
||||
echo "[6] Reencryption using all active keyslots"
|
||||
echo -e "$PWD2\n$PWD1\n$PWD2\n$PWD1\n$PWD2\n$PWD1\n$PWD2\n$PWD3" | $REENC -q $LOOPDEV1 || fail
|
||||
check_slot 0 1 2 3 4 5 6 7 || fail "All keyslots expected to be enabled"
|
||||
|
||||
echo "[7] Reencryption of block devices with different block size"
|
||||
add_scsi_device sector_size=512 dev_size_mb=8
|
||||
simple_scsi_reenc "[512 sector]"
|
||||
add_scsi_device sector_size=4096 dev_size_mb=8
|
||||
simple_scsi_reenc "[4096 sector]"
|
||||
add_scsi_device sector_size=512 physblk_exp=3 dev_size_mb=8
|
||||
simple_scsi_reenc "[4096/512 sector]"
|
||||
echo "[OK]"
|
||||
|
||||
echo "[8] Header only reencryption (hash and iteration time)"
|
||||
echo $PWD1 | $CRYPTSETUP -q luksFormat --hash sha1 $LOOPDEV1 || fail
|
||||
wipe $PWD1
|
||||
check_hash $PWD1 $HASH1
|
||||
echo $PWD1 | $REENC $LOOPDEV1 -q --keep-key --hash sha256 --iter-time 1
|
||||
check_hash $PWD1 $HASH1
|
||||
echo $PWD1 | $REENC $LOOPDEV1 -q --keep-key --hash sha512
|
||||
check_hash $PWD1 $HASH1
|
||||
echo $PWD1 | $REENC $LOOPDEV1 -q --keep-key --iter-time 1
|
||||
check_hash $PWD1 $HASH1
|
||||
|
||||
echo "[9] Test log I/Os on various underlaying block devices"
|
||||
prepare 8192
|
||||
echo $PWD2 | $CRYPTSETUP -q luksFormat -i 1 $LOOPDEV1 || fail
|
||||
add_scsi_device sector_size=512 dev_size_mb=25
|
||||
test_logging "[512 sector]" || fail
|
||||
add_scsi_device sector_size=4096 dev_size_mb=25
|
||||
test_logging "[4096 sector]" || fail
|
||||
add_scsi_device sector_size=512 dev_size_mb=25 physblk_exp=3
|
||||
test_logging "[4096/512 sector]" || fail
|
||||
test_logging_tmpfs || fail
|
||||
|
||||
echo "[10] Removal of encryption"
|
||||
prepare 8192
|
||||
echo $PWD1 | $CRYPTSETUP -q luksFormat -i 1 $LOOPDEV1 || fail
|
||||
wipe $PWD1
|
||||
check_hash $PWD1 $HASH1
|
||||
echo $PWD1 | $REENC $LOOPDEV1 -q --decrypt
|
||||
check_hash_dev $LOOPDEV1 $HASH4
|
||||
|
||||
remove_mapping
|
||||
exit 0
|
||||
|
||||
@@ -65,27 +65,28 @@ function test_required()
|
||||
}
|
||||
|
||||
test_required
|
||||
export LANG=C
|
||||
|
||||
[ ! -d $TST_DIR ] && tar xjf tcrypt-images.tar.bz2
|
||||
|
||||
echo "HEADER CHECK"
|
||||
for file in $(ls $TST_DIR/tc_*) ; do
|
||||
for file in $(ls $TST_DIR/[tv]c_*) ; do
|
||||
echo -n " $file"
|
||||
echo $PASSWORD | $CRYPTSETUP tcryptDump $file >/dev/null || fail
|
||||
echo $PASSWORD | $CRYPTSETUP tcryptDump --veracrypt $file >/dev/null || fail
|
||||
echo " [OK]"
|
||||
done
|
||||
|
||||
echo "HEADER CHECK (HIDDEN)"
|
||||
for file in $(ls $TST_DIR/tc_*-hidden) ; do
|
||||
for file in $(ls $TST_DIR/[tv]c_*-hidden) ; do
|
||||
echo -n " $file (hidden)"
|
||||
echo $PASSWORD_HIDDEN | $CRYPTSETUP tcryptDump --tcrypt-hidden $file >/dev/null || fail
|
||||
echo $PASSWORD_HIDDEN | $CRYPTSETUP tcryptDump --tcrypt-hidden --veracrypt $file >/dev/null || fail
|
||||
echo " [OK]"
|
||||
done
|
||||
|
||||
echo "HEADER KEYFILES CHECK"
|
||||
for file in $(ls $TST_DIR/tck_*) ; do
|
||||
for file in $(ls $TST_DIR/[tv]ck_*) ; do
|
||||
echo -n " $file"
|
||||
echo $PASSWORD | $CRYPTSETUP tcryptDump -d $TST_DIR/keyfile1 -d $TST_DIR/keyfile2 $file >/dev/null || fail
|
||||
echo $PASSWORD | $CRYPTSETUP tcryptDump --veracrypt -d $TST_DIR/keyfile1 -d $TST_DIR/keyfile2 $file >/dev/null || fail
|
||||
echo " [OK]"
|
||||
done
|
||||
|
||||
@@ -95,10 +96,14 @@ if [ $(id -u) != 0 ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "ACTIVATION FS UUID CHECK (LRW/XTS modes only)"
|
||||
for file in $(ls $TST_DIR/tc_*-lrw-* $TST_DIR/tc_*-xts-*) ; do
|
||||
echo "ACTIVATION FS UUID CHECK"
|
||||
for file in $(ls $TST_DIR/[tv]c_*) ; do
|
||||
echo -n " $file"
|
||||
echo $PASSWORD | $CRYPTSETUP tcryptOpen -r $file $MAP || fail
|
||||
out=$(echo $PASSWORD | $CRYPTSETUP tcryptOpen --veracrypt -r $file $MAP 2>&1)
|
||||
ret=$?
|
||||
[ $ret -eq 1 ] && ( echo "$out" | grep -q -e "TCRYPT legacy mode" ) && echo " [N/A]" && continue
|
||||
[ $ret -eq 1 ] && ( echo "$out" | grep -q -e "TCRYPT compatible mapping" ) && echo " [N/A]" && continue
|
||||
[ $ret -ne 0 ] && fail
|
||||
$CRYPTSETUP status $MAP >/dev/null || fail
|
||||
$CRYPTSETUP status /dev/mapper/$MAP >/dev/null || fail
|
||||
UUID=$(lsblk -n -o UUID /dev/mapper/$MAP)
|
||||
@@ -107,10 +112,14 @@ for file in $(ls $TST_DIR/tc_*-lrw-* $TST_DIR/tc_*-xts-*) ; do
|
||||
echo " [OK]"
|
||||
done
|
||||
|
||||
echo "ACTIVATION FS UUID (HIDDEN) CHECK (LRW/XTS modes only)"
|
||||
for file in $(ls $TST_DIR/tc_*-lrw-*-hidden $TST_DIR/tc_*-xts-*-hidden) ; do
|
||||
echo "ACTIVATION FS UUID (HIDDEN) CHECK"
|
||||
for file in $(ls $TST_DIR/[tv]c_*-hidden) ; do
|
||||
echo -n " $file"
|
||||
echo $PASSWORD_HIDDEN | $CRYPTSETUP tcryptOpen -r $file $MAP --tcrypt-hidden || fail
|
||||
out=$(echo $PASSWORD_HIDDEN | $CRYPTSETUP tcryptOpen --veracrypt -r $file $MAP --tcrypt-hidden 2>&1)
|
||||
ret=$?
|
||||
[ $ret -eq 1 ] && ( echo "$out" | grep -q -e "TCRYPT legacy mode" ) && echo " [N/A]" && continue
|
||||
[ $ret -eq 1 ] && ( echo "$out" | grep -q -e "TCRYPT compatible mapping" ) && echo " [N/A]" && continue
|
||||
[ $ret -ne 0 ] && fail
|
||||
UUID=$(lsblk -n -o UUID /dev/mapper/$MAP)
|
||||
$CRYPTSETUP remove $MAP || fail
|
||||
[ "$UUID" != "CAFE-BABE" ] && fail "UUID check failed."
|
||||
|
||||
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user