Compare commits

..

5 Commits

Author SHA1 Message Date
Milan Broz
0fd1c62de9 Add disable-luks2 reencryption configure option.
The option --disable-luks2-reencryption completely disable
LUKS2 reencryption code.

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

Devices with online reencryption in progress cannot be activated.

This option can cause some incompatibilities. Please use with care.
2022-01-12 22:54:23 +01:00
Ondrej Kozina
9cc749d9fa Avoid name clash with newer json-c library.
This is partial revert of previous commit and also
fixes wrong decision to name our internal helpers with
json_object prefix.
2022-01-12 21:10:59 +01:00
Ondrej Kozina
46a4c80269 Properly align LUKS2 keyslots area on conversion.
If LUKS1 payload offset (data offset) is not aligned to
4KiB we create unaligned keyslots area in LUKS2 metadata
during upconversion. Unaligned keyslots area is not valid
from LUKS2 perspective. Fix it by properly aligning future
keyslots area and also check if LUKS1 keyslots area fit
in the new one.

Fixes: #534.
2022-01-12 21:10:47 +01:00
Björn Esser
5fec16407b Add support for upcoming json-c 0.14.0.
* TRUE/FALSE are not defined anymore.  1 and 0 are used instead.
  * json_object_get_uint64() and json_object_new_uint64() are part
    of the upstream API now.
2022-01-12 21:04:04 +01:00
Milan Broz
cebc1638e3 Remove obsolete AC_HEADER_STDC macro.
This should be no longer used.
We do not support systems without standard headers anyway.
2022-01-12 21:00:16 +01:00
221 changed files with 25667 additions and 40318 deletions

1
.gitignore vendored
View File

@@ -25,7 +25,6 @@ config.sub
configure
cryptsetup
cryptsetup-reencrypt
cryptsetup-ssh
depcomp
install-sh
integritysetup

View File

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

View File

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

View File

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

View File

@@ -17,8 +17,6 @@ MAKE="make -j2"
DUMP_CONFIG_LOG="short"
export TS_OPT_parsable="yes"
export RUN_SSH_PLUGIN_TEST=1
function configure_travis
{
./configure "$@"
@@ -40,8 +38,6 @@ function check_nonroot
configure_travis \
--enable-cryptsetup-reencrypt \
--enable-internal-sse-argon2 \
--enable-external-tokens \
--enable-ssh-token \
"$cfg_opts" \
|| return
@@ -56,11 +52,9 @@ function check_root
[ -z "$cfg_opts" ] && return
configure_travis \
configure_travis \
--enable-cryptsetup-reencrypt \
--enable-internal-sse-argon2 \
--enable-external-tokens \
--enable-ssh-token \
"$cfg_opts" \
|| return
@@ -108,15 +102,7 @@ function travis_install_script
keyutils \
libjson-c-dev \
libblkid-dev \
dkms \
linux-headers-$(uname -r) \
linux-modules-extra-$(uname -r) \
libssh-dev \
sshpass \
|| return
# For VeraCrypt test
sudo apt-get install gost-crypto-dkms
}
function travis_before_script

View File

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

6
ChangeLog Normal file
View File

@@ -0,0 +1,6 @@
Since version 1.6 this file is no longer maintained.
See docs/*ReleaseNotes for release changes documentation.
See version control history for full commit messages.
https://gitlab.com/cryptsetup/cryptsetup/commits/master

3102
FAQ

File diff suppressed because it is too large Load Diff

229
INSTALL Normal file
View File

@@ -0,0 +1,229 @@
Copyright 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software
Foundation, Inc.
This file is free documentation; the Free Software Foundation gives
unlimited permission to copy, distribute and modify it.
Basic Installation
==================
These are generic installation instructions.
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a `Makefile' in each directory of the package.
It may also create one or more `.h' files containing system-dependent
definitions. Finally, it creates a shell script `config.status' that
you can run in the future to recreate the current configuration, and a
file `config.log' containing compiler output (useful mainly for
debugging `configure').
It can also use an optional file (typically called `config.cache'
and enabled with `--cache-file=config.cache' or simply `-C') that saves
the results of its tests to speed up reconfiguring. (Caching is
disabled by default to prevent problems with accidental use of stale
cache files.)
If you need to do unusual things to compile the package, please try
to figure out how `configure' could check whether to do them, and mail
diffs or instructions to the address given in the `README' so they can
be considered for the next release. If you are using the cache, and at
some point `config.cache' contains results you don't want to keep, you
may remove or edit it.
The file `configure.ac' (or `configure.in') is used to create
`configure' by a program called `autoconf'. You only need
`configure.ac' if you want to change it or regenerate `configure' using
a newer version of `autoconf'.
The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system. If you're
using `csh' on an old version of System V, you might need to type
`sh ./configure' instead to prevent `csh' from trying to execute
`configure' itself.
Running `configure' takes a while. While running, it prints some
messages telling which features it is checking for.
2. Type `make' to compile the package.
3. Optionally, type `make check' to run any self-tests that come with
the package.
4. Type `make install' to install the programs and any data files and
documentation.
5. You can remove the program binaries and object files from the
source code directory by typing `make clean'. To also remove the
files that `configure' created (so you can compile the package for
a different kind of computer), type `make distclean'. There is
also a `make maintainer-clean' target, but that is intended mainly
for the package's developers. If you use it, you may have to get
all sorts of other programs in order to regenerate files that came
with the distribution.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that
the `configure' script does not know about. Run `./configure --help'
for details on some of the pertinent environment variables.
You can give `configure' initial values for configuration parameters
by setting variables in the command line or in the environment. Here
is an example:
./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
*Note Defining Variables::, for more details.
Compiling For Multiple Architectures
====================================
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you must use a version of `make' that
supports the `VPATH' variable, such as GNU `make'. `cd' to the
directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'.
If you have to use a `make' that does not support the `VPATH'
variable, you have to compile the package for one architecture at a
time in the source code directory. After you have installed the
package for one architecture, use `make distclean' before reconfiguring
for another architecture.
Installation Names
==================
By default, `make install' will install the package's files in
`/usr/local/bin', `/usr/local/man', etc. You can specify an
installation prefix other than `/usr/local' by giving `configure' the
option `--prefix=PATH'.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
give `configure' the option `--exec-prefix=PATH', the package will use
PATH as the prefix for installing programs and libraries.
Documentation and other data files will still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=PATH' to specify different values for particular
kinds of files. Run `configure --help' for a list of the directories
you can set and what kinds of files go in them.
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
Optional Features
=================
Some packages pay attention to `--enable-FEATURE' options to
`configure', where FEATURE indicates an optional part of the package.
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
is something like `gnu-as' or `x' (for the X Window System). The
`README' should mention any `--enable-' and `--with-' options that the
package recognizes.
For packages that use the X Window System, `configure' can usually
find the X include and library files automatically, but if it doesn't,
you can use the `configure' options `--x-includes=DIR' and
`--x-libraries=DIR' to specify their locations.
Specifying the System Type
==========================
There may be some features `configure' cannot figure out
automatically, but needs to determine by the type of machine the package
will run on. Usually, assuming the package is built to be run on the
_same_ architectures, `configure' can figure that out, but if it prints
a message saying it cannot guess the machine type, give it the
`--build=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name which has the form:
CPU-COMPANY-SYSTEM
where SYSTEM can have one of these forms:
OS KERNEL-OS
See the file `config.sub' for the possible values of each field. If
`config.sub' isn't included in this package, then this package doesn't
need to know the machine type.
If you are _building_ compiler tools for cross-compiling, you should
use the `--target=TYPE' option to select the type of system they will
produce code for.
If you want to _use_ a cross compiler, that generates code for a
platform different from the build platform, you should specify the
"host" platform (i.e., that on which the generated programs will
eventually be run) with `--host=TYPE'.
Sharing Defaults
================
If you want to set default values for `configure' scripts to share,
you can create a site shell script called `config.site' that gives
default values for variables like `CC', `cache_file', and `prefix'.
`configure' looks for `PREFIX/share/config.site' if it exists, then
`PREFIX/etc/config.site' if it exists. Or, you can set the
`CONFIG_SITE' environment variable to the location of the site script.
A warning: not all `configure' scripts look for a site script.
Defining Variables
==================
Variables not defined in a site shell script can be set in the
environment passed to `configure'. However, some packages may run
configure again during the build, and the customized values of these
variables may be lost. In order to avoid this problem, you should set
them in the `configure' command line, using `VAR=value'. For example:
./configure CC=/usr/local2/bin/gcc
will cause the specified gcc to be used as the C compiler (unless it is
overridden in the site shell script).
`configure' Invocation
======================
`configure' recognizes the following options to control how it
operates.
`--help'
`-h'
Print a summary of the options to `configure', and exit.
`--version'
`-V'
Print the version of Autoconf used to generate the `configure'
script, and exit.
`--cache-file=FILE'
Enable the cache: use and save the results of the tests in FILE,
traditionally `config.cache'. FILE defaults to `/dev/null' to
disable caching.
`--config-cache'
`-C'
Alias for `--cache-file=config.cache'.
`--quiet'
`--silent'
`-q'
Do not print messages saying which checks are being made. To
suppress all normal output, redirect it to `/dev/null' (any error
messages will still be shown).
`--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
`configure' also accepts some other, not widely useful, options. Run
`configure --help' for more details.

View File

@@ -1,4 +1,4 @@
EXTRA_DIST = README.md COPYING.LGPL FAQ docs misc
EXTRA_DIST = COPYING.LGPL FAQ docs misc
SUBDIRS = po tests
CLEANFILES =
DISTCLEAN_TARGETS =
@@ -11,8 +11,7 @@ AM_CPPFLAGS = \
-DLIBDIR=\""$(libdir)"\" \
-DPREFIX=\""$(prefix)"\" \
-DSYSCONFDIR=\""$(sysconfdir)"\" \
-DVERSION=\""$(VERSION)"\" \
-DEXTERNAL_LUKS2_TOKENS_PATH=\"${EXTERNAL_LUKS2_TOKENS_PATH}\"
-DVERSION=\""$(VERSION)"\"
AM_CFLAGS = -Wall
AM_LDFLAGS =
@@ -20,13 +19,10 @@ LDADD = $(LTLIBINTL) -lm
tmpfilesddir = @DEFAULT_TMPFILESDIR@
include_HEADERS =
lib_LTLIBRARIES =
noinst_LTLIBRARIES =
sbin_PROGRAMS =
man8_MANS =
tmpfilesd_DATA =
pkgconfig_DATA =
include man/Makemodule.am
@@ -39,14 +35,12 @@ include lib/crypto_backend/Makemodule.am
include lib/Makemodule.am
include src/Makemodule.am
include tokens/Makemodule.am
ACLOCAL_AMFLAGS = -I m4
DISTCHECK_CONFIGURE_FLAGS = \
--with-tmpfilesdir=$$dc_install_base/usr/lib/tmpfiles.d \
--enable-internal-argon2 --enable-internal-sse-argon2 \
--enable-external-tokens --enable-ssh-token
--enable-internal-argon2 --enable-internal-sse-argon2
distclean-local:
-find . -name \*~ -o -name \*.orig -o -name \*.rej | xargs rm -f

1
NEWS Normal file
View File

@@ -0,0 +1 @@
See docs/* directory for Release Notes.

31
README Normal file
View File

@@ -0,0 +1,31 @@
cryptsetup
setup cryptographic volumes for dm-crypt (including LUKS extension)
WEB PAGE:
https://gitlab.com/cryptsetup/cryptsetup/
FAQ:
https://gitlab.com/cryptsetup/cryptsetup/wikis/FrequentlyAskedQuestions
MAILING LIST:
E-MAIL: dm-crypt@saout.de
URL: http://www.saout.de/mailman/listinfo/dm-crypt
DOWNLOAD:
https://www.kernel.org/pub/linux/utils/cryptsetup/
SOURCE CODE:
URL: https://gitlab.com/cryptsetup/cryptsetup/tree/master
Checkout: git clone https://gitlab.com/cryptsetup/cryptsetup.git
NLS (PO TRANSLATIONS):
PO files are maintained by:
http://translationproject.org/domain/cryptsetup.html

View File

@@ -5,12 +5,12 @@ What the ...?
**Cryptsetup** is a utility used to conveniently set up disk encryption based
on the [DMCrypt](https://gitlab.com/cryptsetup/cryptsetup/wikis/DMCrypt) kernel module.
These include **plain** **dm-crypt** volumes, **LUKS** volumes, **loop-AES**,
**TrueCrypt** (including **VeraCrypt** extension) and **BitLocker** formats.
These include **plain** **dm-crypt** volumes, **LUKS** volumes, **loop-AES**
and **TrueCrypt** (including **VeraCrypt** extension) formats.
The project also includes a **veritysetup** utility used to conveniently setup
[DMVerity](https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity) block integrity checking kernel module
and **integritysetup** to setup
and, since version 2.0, **integritysetup** to setup
[DMIntegrity](https://gitlab.com/cryptsetup/cryptsetup/wikis/DMIntegrity) block integrity kernel module.
@@ -44,19 +44,16 @@ Download
--------
All release tarballs and release notes are hosted on [kernel.org](https://www.kernel.org/pub/linux/utils/cryptsetup/).
**The latest release candidate cryptsetup version is 2.4.0-rc1**
* [cryptsetup-2.4.0-rc1.tar.xz](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.4/cryptsetup-2.4.0-rc1.tar.xz)
* Signature [cryptsetup-2.4.0-rc1.tar.sign](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.4/cryptsetup-2.4.0-rc1.tar.sign)
**The latest cryptsetup version is 2.2.2**
* [cryptsetup-2.2.2.tar.xz](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.2/cryptsetup-2.2.2.tar.xz)
* Signature [cryptsetup-2.2.2.tar.sign](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.2/cryptsetup-2.2.2.tar.sign)
_(You need to decompress file first to check signature.)_
* [Cryptsetup 2.4.0-rc1 Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.4/v2.4.0-rc1-ReleaseNotes).
**The latest stable cryptsetup version is 2.3.6**
* [cryptsetup-2.3.6.tar.xz](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.3/cryptsetup-2.3.6.tar.xz)
* Signature [cryptsetup-2.3.6.tar.sign](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.3/cryptsetup-2.3.6.tar.sign)
_(You need to decompress file first to check signature.)_
* [Cryptsetup 2.3.6 Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.3/v2.3.6-ReleaseNotes).
* [Cryptsetup 2.2.2 Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.2/v2.2.2-ReleaseNotes).
Previous versions
* [Version 2.2.1](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.2/cryptsetup-2.2.1.tar.xz) -
[Signature](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.2/cryptsetup-2.2.1.tar.sign) -
[Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.2/v2.2.0-ReleaseNotes).
* [Version 2.0.6](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.0/cryptsetup-2.0.6.tar.xz) -
[Signature](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.0/cryptsetup-2.0.6.tar.sign) -
[Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.0/v2.0.6-ReleaseNotes).
@@ -73,19 +70,7 @@ For libcryptsetup documentation see [libcryptsetup API](https://mbroz.fedorapeop
The libcryptsetup API/ABI changes are tracked in [compatibility report](https://abi-laboratory.pro/tracker/timeline/cryptsetup/).
NLS PO files are maintained by [TranslationProject](https://translationproject.org/domain/cryptsetup.html).
Required packages
-----------------
All distributions provide cryptsetup as distro package. If you need to compile cryptsetup youfself, some packages are required for compilation. Please always prefer distro specific build tools to manually configuring cryptsetup.
Fo available compile options, check ``configure --help`` for more info. If you are using a git snapshot, you need to generate configure script with ``autogen.sh`` script.
Here is the list of packages needed for the compilation of project for particular distributions:
* For Fedora: `git gcc make autoconf automake gettext-devel pkgconfig openssl-devel popt-devel device-mapper-devel libuuid-devel json-c-devel libblkid-devel findutils libtool libssh-devel tar`. Optionally `libargon2-devel libpwquality-devel`. To run internal testsuite you also need `sharutils device-mapper jq vim-common expect keyutils netcat shadow-utils openssh-clients openssh sshpass`.
* For Debian and Ubuntu: `git gcc make autoconf automake autopoint pkg-config libtool gettext libssl-dev libdevmapper-dev libpopt-dev uuid-dev libsepol1-dev libjson-c-dev libssh-dev libblkid-dev tar`. Optionally `libargon2-0-dev libpwquality-dev`. To run internal testsuite you also need `sharutils dmsetup jq xxd expect keyutils netcat passwd openssh-client sshpass`
Note that the list could change as distributions evolve.
NLS PO files are maintained by [TranslationProject](http://translationproject.org/domain/cryptsetup.html).
Help!
-----
@@ -94,5 +79,5 @@ For cryptsetup and LUKS related questions, please use the dm-crypt mailing list,
If you want to subscribe just send an empty mail to [dm-crypt-subscribe@saout.de](mailto:dm-crypt-subscribe@saout.de).
You can also browse [list archive](https://www.saout.de/pipermail/dm-crypt/) or read and search it through
[web interface on lore.kernel.org](https://lore.kernel.org/dm-crypt/) or alternatively on [marc.info](https://marc.info/?l=dm-crypt).
You can also browse [list archive](http://www.saout.de/pipermail/dm-crypt/) or read it through
[web interface](https://marc.info/?l=dm-crypt).

1
TODO Normal file
View File

@@ -0,0 +1 @@
Please see issues tracked at https://gitlab.com/cryptsetup/cryptsetup/issues.

View File

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

View File

@@ -1,9 +1,9 @@
AC_PREREQ([2.67])
AC_INIT([cryptsetup],[2.4.0-rc1])
AC_INIT([cryptsetup],[2.2.2])
dnl library version from <major>.<minor>.<release>[-<suffix>]
LIBCRYPTSETUP_VERSION=$(echo $PACKAGE_VERSION | cut -f1 -d-)
LIBCRYPTSETUP_VERSION_INFO=19:0:7
LIBCRYPTSETUP_VERSION_INFO=17:0:5
AM_SILENT_RULES([yes])
AC_CONFIG_SRCDIR(src/cryptsetup.c)
@@ -16,7 +16,7 @@ AC_CONFIG_HEADERS([config.h:config.h.in])
# For old automake use this
#AM_INIT_AUTOMAKE(dist-xz subdir-objects)
AM_INIT_AUTOMAKE([dist-xz 1.12 serial-tests subdir-objects foreign])
AM_INIT_AUTOMAKE([dist-xz 1.12 serial-tests subdir-objects])
if test "x$prefix" = "xNONE"; then
sysconfdir=/etc
@@ -33,7 +33,6 @@ AC_PROG_MAKE_SET
AC_ENABLE_STATIC(no)
LT_INIT
PKG_PROG_PKG_CONFIG
AM_ICONV
dnl ==========================================================================
dnl define PKG_CHECK_VAR for old pkg-config <= 0.28
@@ -57,15 +56,8 @@ dnl ==========================================================================
AC_C_RESTRICT
AC_HEADER_DIRENT
AC_HEADER_STDC
AC_CHECK_HEADERS(fcntl.h malloc.h inttypes.h sys/ioctl.h sys/mman.h \
sys/sysmacros.h sys/statvfs.h ctype.h unistd.h locale.h byteswap.h endian.h stdint.h)
AC_CHECK_DECLS([O_CLOEXEC],,[AC_DEFINE([O_CLOEXEC],[0], [Defined to 0 if not provided])],
[[
#ifdef HAVE_FCNTL_H
# include <fcntl.h>
#endif
]])
AC_CHECK_HEADERS(uuid/uuid.h,,[AC_MSG_ERROR([You need the uuid library.])])
AC_CHECK_HEADER(libdevmapper.h,,[AC_MSG_ERROR([You need the device-mapper library.])])
@@ -115,25 +107,6 @@ AC_FUNC_FSEEKO
AC_PROG_GCC_TRADITIONAL
AC_FUNC_STRERROR_R
dnl ==========================================================================
dnl LUKS2 external tokens
AC_ARG_ENABLE([external-tokens],
AS_HELP_STRING([--disable-external-tokens], [disable external LUKS2 tokens]),
[], [enable_external_tokens=yes])
if test "x$enable_external_tokens" = "xyes"; then
AC_DEFINE(USE_EXTERNAL_TOKENS, 1, [Use external tokens])
fi
AC_ARG_ENABLE([ssh-token],
AS_HELP_STRING([--disable-ssh-token], [disable LUKS2 ssh-token]),
[], [enable_ssh_token=yes])
AM_CONDITIONAL(SSHPLUGIN_TOKEN, test "x$enable_ssh_token" = "xyes")
if test "x$enable_ssh_token" = "xyes" -a "x$enable_external_tokens" = "xno"; then
AC_MSG_ERROR([Requested LUKS2 ssh-token build, but external tokens are disabled.])
fi
dnl ==========================================================================
AM_GNU_GETTEXT([external],[need-ngettext])
@@ -165,6 +138,14 @@ AC_DEFUN([NO_FIPS], [
fi
])
dnl LUKS2 online reencryption
AC_ARG_ENABLE([luks2-reencryption],
AS_HELP_STRING([--disable-luks2-reencryption], [disable LUKS2 online reencryption extension]),
[], [enable_luks2_reencryption=yes])
if test "x$enable_luks2_reencryption" = "xyes"; then
AC_DEFINE(USE_LUKS2_REENCRYPTION, 1, [Use LUKS2 online reencryption extension])
fi
dnl ==========================================================================
dnl pwquality library (cryptsetup CLI only)
AC_ARG_ENABLE([pwquality],
@@ -195,15 +176,7 @@ AC_DEFINE_UNQUOTED([PASSWDQC_CONFIG_FILE], ["$use_passwdqc_config"], [passwdqc l
if test "x$enable_passwdqc" = "xyes"; then
AC_DEFINE(ENABLE_PASSWDQC, 1, [Enable password quality checking using passwdqc library])
saved_LIBS="$LIBS"
AC_SEARCH_LIBS([passwdqc_check], [passwdqc])
case "$ac_cv_search_passwdqc_check" in
no) AC_MSG_ERROR([failed to find passwdqc_check]) ;;
-l*) PASSWDQC_LIBS="$ac_cv_search_passwdqc_check" ;;
*) PASSWDQC_LIBS= ;;
esac
AC_CHECK_FUNCS([passwdqc_params_free])
LIBS="$saved_LIBS"
PASSWDQC_LIBS="-lpasswdqc"
fi
if test "x$enable_pwquality$enable_passwdqc" = "xyesyes"; then
@@ -382,7 +355,6 @@ AC_CHECK_DECLS([dm_task_retry_remove], [], [], [#include <libdevmapper.h>])
AC_CHECK_DECLS([dm_task_deferred_remove], [], [], [#include <libdevmapper.h>])
AC_CHECK_DECLS([dm_device_has_mounted_fs], [], [], [#include <libdevmapper.h>])
AC_CHECK_DECLS([dm_device_has_holders], [], [], [#include <libdevmapper.h>])
AC_CHECK_DECLS([dm_device_get_name], [], [], [#include <libdevmapper.h>])
AC_CHECK_DECLS([DM_DEVICE_GET_TARGET_VERSION], [], [], [#include <libdevmapper.h>])
AC_CHECK_DECLS([DM_UDEV_DISABLE_DISK_RULES_FLAG], [have_cookie=yes], [have_cookie=no], [#include <libdevmapper.h>])
if test "x$enable_udev" = xyes; then
@@ -399,12 +371,6 @@ PKG_CHECK_MODULES([JSON_C], [json-c])
AC_CHECK_DECLS([json_object_object_add_ex], [], [], [#include <json-c/json.h>])
AC_CHECK_DECLS([json_object_deep_copy], [], [], [#include <json-c/json.h>])
dnl Check for libssh for SSH plugin
if test "x$enable_ssh_token" = "xyes"; then
PKG_CHECK_MODULES([LIBSSH], [libssh])
AC_CHECK_DECLS([ssh_session_is_known_server], [], [], [#include <libssh/libssh.h>])
fi
dnl Crypto backend configuration.
AC_ARG_WITH([crypto_backend],
AS_HELP_STRING([--with-crypto_backend=BACKEND], [crypto backend (gcrypt/openssl/nss/kernel/nettle) [openssl]]),
@@ -561,8 +527,6 @@ AC_SUBST([JSON_C_LIBS])
AC_SUBST([LIBARGON2_LIBS])
AC_SUBST([BLKID_LIBS])
AC_SUBST([LIBSSH_LIBS])
AC_SUBST([LIBCRYPTSETUP_VERSION])
AC_SUBST([LIBCRYPTSETUP_VERSION_INFO])
@@ -618,7 +582,7 @@ if test "x$enable_luks_adjust_xts_keysize" = "xyes"; then
AC_DEFINE(ENABLE_LUKS_ADJUST_XTS_KEYSIZE, 1, [XTS mode - double default LUKS keysize if needed])
fi
CS_STR_WITH([luks2-pbkdf], [Default PBKDF algorithm (pbkdf2 or argon2i/argon2id) for LUKS2], [argon2id])
CS_STR_WITH([luks2-pbkdf], [Default PBKDF algorithm (pbkdf2 or argon2i/argon2id) for LUKS2], [argon2i])
CS_NUM_WITH([luks1-iter-time], [PBKDF2 iteration time for LUKS1 (in ms)], [2000])
CS_NUM_WITH([luks2-iter-time], [Argon2 PBKDF iteration time for LUKS2 (in ms)], [2000])
CS_NUM_WITH([luks2-memory-kb], [Argon2 PBKDF memory cost for LUKS2 (in kB)], [1048576])
@@ -631,8 +595,7 @@ CS_STR_WITH([loopaes-cipher], [cipher for loop-AES mode], [aes])
CS_NUM_WITH([loopaes-keybits],[key length in bits for loop-AES mode], [256])
CS_NUM_WITH([keyfile-size-maxkb],[maximum keyfile size (in KiB)], [8192])
CS_NUM_WITH([integrity-keyfile-size-maxkb],[maximum integritysetup keyfile size (in KiB)], [4])
CS_NUM_WITH([passphrase-size-max],[maximum passphrase size (in characters)], [512])
CS_NUM_WITH([passphrase-size-max],[maximum keyfile size (in characters)], [512])
CS_STR_WITH([verity-hash], [hash function for verity mode], [sha256])
CS_NUM_WITH([verity-data-block], [data block size for verity mode], [4096])
@@ -660,15 +623,6 @@ test -z "$with_luks2_lock_dir_perms" && with_luks2_lock_dir_perms=0700
DEFAULT_LUKS2_LOCK_DIR_PERMS=$with_luks2_lock_dir_perms
AC_SUBST(DEFAULT_LUKS2_LOCK_DIR_PERMS)
CS_STR_WITH([luks2-external-tokens-path], [path to directory with LUKSv2 external token handlers (plugins)], [LIBDIR/cryptsetup])
if test -n "$with_luks2_external_tokens_path"; then
CS_ABSPATH([${with_luks2_external_tokens_path}],[with-luks2-external-tokens-path])
EXTERNAL_LUKS2_TOKENS_PATH=$with_luks2_external_tokens_path
else
EXTERNAL_LUKS2_TOKENS_PATH="\${libdir}/cryptsetup"
fi
AC_SUBST(EXTERNAL_LUKS2_TOKENS_PATH)
dnl Override default LUKS format version (for cryptsetup or cryptsetup-reencrypt format actions only).
AC_ARG_WITH([default_luks_format],
AS_HELP_STRING([--with-default-luks-format=FORMAT], [default LUKS format version (LUKS1/LUKS2) [LUKS2]]),

View File

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

View File

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

View File

@@ -1,209 +0,0 @@
Cryptsetup 2.3.0 Release Notes
==============================
Stable release with new experimental features and bug fixes.
Cryptsetup 2.3 version introduces support for BitLocker-compatible
devices (BITLK format). This format is used in Windows systems,
and in combination with a filesystem driver, cryptsetup now provides
native read-write access to BitLocker Full Disk Encryption devices.
The BITLK implementation is based on publicly available information
and it is an independent and opensource implementation that allows
to access this proprietary disk encryption.
Changes since version 2.2.2
~~~~~~~~~~~~~~~~~~~~~~~~~~~
* BITLK (Windows BitLocker compatible) device access
BITLK userspace implementation is based on the master thesis and code
provided by Vojtech Trefny. Also, thanks to other opensource projects
like libbde (that provide alternative approach to decode this format)
we were able to verify cryptsetup implementation.
NOTE: Support for the BITLK device is EXPERIMENTAL and will require
a lot of testing. If you get some error message (mainly unsupported
metadata in the on-disk header), please help us by submitting an issue
to cryptsetup project, so we can fix it. Thank you!
Cryptsetup supports BITLK activation through passphrase or recovery
passphrase for existing devices (BitLocker and Bitlocker to Go).
Activation through TPM, SmartCard, or any other key protector
is not supported. And in some situations, mainly for TPM bind to some
PCR registers, it could be even impossible on Linux in the future.
All metadata (key protectors) are handled read-only, cryptsetup cannot
create or modify them. Except for old devices (created in old Vista
systems), all format variants should be recognized.
Data devices can be activated read-write (followed by mounting through
the proper filesystem driver). To access filesystem on the decrypted device
you need properly installed driver (vfat, NTFS or exFAT).
Foe AES-XTS, activation is supported on all recent Linux kernels.
For older AES-CBC encryption, Linux Kernel version 5.3 is required
(support for special IV variant); for AES-CBC with Elephant diffuser,
Linux Kernel 5.6 is required.
Please note that CBC variants are legacy, and we provide it only
for backward compatibility (to be able to access old drives).
Cryptsetup command now supports the new "bitlk" format and implement dump,
open, status, and close actions.
To activate a BITLK device, use
# cryptsetup open --type bitlk <device> <name>
or with alias
# cryptsetup bitlkOpen <device> <name>
Then with properly installed fs driver (usually NTFS, vfat or exFAT),
you can mount the plaintext device /dev/mapper<name> device as a common
filesystem.
To print metadata information about BITLK device, use
# crypotsetup bitlkDump <device>
To print information about the active device, use
# cryptsetup status <name>
Example (activation of disk image):
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Recent blkid recognizes BitLocker device,just to verity
# blkid bitlocker_xts_ntfs.img
bitlocker_xts_ntfs.img: TYPE="BitLocker"
# Print visible metadata information (on-disk, form the image)
# cryptsetup bitlkDump bitlocker_xts_ntfs.img
Info for BITLK device bitlocker_xts_ntfs.img.
Version: 2
GUID: ...
Created: Wed Oct 23 17:38:15 2019
Description: DESKTOP-xxxxxxx E: 23.10.2019
Cipher name: aes
Cipher mode: xts-plain64
Cipher key: 128 bits
Keyslots:
0: VMK
GUID: ...
Protection: VMK protected with passphrase
Salt: ...
Key data size: 44 [bytes]
1: VMK
GUID: ...
Protection: VMK protected with recovery passphrase
Salt: ...
Key data size: 44 [bytes]
2: FVEK
Key data size: 44 [bytes]
# Activation (recovery passphrase works the same as password)
# cryptsetup bitlkOpen bitlocker_xts_ntfs.img test -v
Enter passphrase for bitlocker_xts_ntfs.img:
Command successful.
# Information about the active device
# cryptsetup status test
/dev/mapper/test is active.
type: BITLK
cipher: aes-xts-plain64
keysize: 128 bits
...
# Plaintext device should now contain decrypted NTFS filesystem
# blkid /dev/mapper/test
/dev/mapper/test: UUID="..." TYPE="ntfs"
# And can be mounted
# mount /dev/mapper/test /mnt/tst
# Deactivation
# umount /mnt/tst
# cryptsetup close test
* Veritysetup now supports activation with additional PKCS7 signature
of root hash through --root-hash-signature option.
The signature uses an in-kernel trusted key to validate the signature
of the root hash during activation. This option requires Linux kernel
5.4 with DM_VERITY_VERIFY_ROOTHASH_SIG option.
Verity devices activated with signature now has a special flag
(with signature) active in device status (veritysetup status <name>).
Usage:
# veritysetup open <data_device> name <hash_device> <root_hash> \
--root-hash-signature=<roothash_p7_sig_file>
* Integritysetup now calculates hash integrity size according to algorithm
instead of requiring an explicit tag size.
Previously, when integritysetup formats a device with hash or
HMAC integrity checksums, it required explicitly tag size entry from
a user (or used default value).
This led to confusion and unexpected shortened tag sizes.
Now, libcryptsetup calculates tag size according to real hash output.
Tag size can also be specified, then it warns if these values differ.
* Integritysetup now supports fixed padding for dm-integrity devices.
There was an in-kernel bug that wasted a lot of space when using metadata
areas for integrity-protected devices if a larger sector size than
512 bytes was used.
This problem affects both stand-alone dm-integrity and also LUKS2 with
authenticated encryption and larger sector size.
The new extension to dm-integrity superblock is needed, so devices
with the new optimal padding cannot be activated on older systems.
Integritysetup/Cryptsetup will use new padding automatically if it
detects the proper kernel. To create a compatible device with
the old padding, use --integrity-legacy-padding option.
* A lot of fixes to online LUKS2 reecryption.
* Add crypt_resume_by_volume_key() function to libcryptsetup.
If a user has a volume key available, the LUKS device can be resumed
directly using the provided volume key.
No keyslot derivation is needed, only the key digest is checked.
* Implement active device suspend info.
Add CRYPT_ACTIVATE_SUSPENDED bit to crypt_get_active_device() flags
that informs the caller that device is suspended (luksSuspend).
* Allow --test-passphrase for a detached header.
Before this fix, we required a data device specified on the command
line even though it was not necessary for the passphrase check.
* Allow --key-file option in legacy offline encryption.
The option was ignored for LUKS1 encryption initialization.
* Export memory safe functions.
To make developing of some extensions simpler, we now export
functions to handle memory with proper wipe on deallocation.
* Fail crypt_keyslot_get_pbkdf for inactive LUKS1 keyslot.
Libcryptsetup API extensions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The libcryptsetup API is backward compatible for existing symbols.
New symbols
crypt_set_compatibility
crypt_get_compatibility;
crypt_resume_by_volume_key;
crypt_activate_by_signed_key;
crypt_safe_alloc;
crypt_safe_realloc;
crypt_safe_free;
crypt_safe_memzero;
New defines introduced :
CRYPT_BITLK "BITLK" - BITLK (BitLocker-compatible mode
CRYPT_COMPAT_LEGACY_INTEGRITY_PADDING - dm-integrity legacy padding
CRYPT_VERITY_ROOT_HASH_SIGNATURE - dm-verity root hash signature
CRYPT_ACTIVATE_SUSPENDED - device suspended info flag

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,294 +0,0 @@
Cryptsetup 2.4.0-rc1 Release Notes
==================================
Stable release candidate with new features and bug fixes.
This version introduces support for external libraries
(plugins) for handling LUKS2 token objects.
Changes since version 2.4.0-rc0
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Add cryptsetup --token-type parameter.
It restricts token type to the parameter value in case no specific
token-id is selected.
* Do not retry token operations if PIN entry failed.
* Respect keyslot priority with token-based activation.
* veritysetup: add --root-hash-file option
Allow passing the root hash via a file, rather than verbatim on
the command line, for the open, verify, and format actions.
* Add crypt_reencrypt_run superseding now deprecated crypt_reencrypt
API call (fixes API break in rc0 release).
* Respect keyslot priority with token-based activation.
Changes since version 2.3.6
~~~~~~~~~~~~~~~~~~~~~~~~~~~
* External LUKS token plugins
A LUKS2 token is an object that can describe how to get a passphrase
to unlock a particular keyslot. The generic metadata format is part
of the LUKS2 specification.
Cryptsetup 2.4 adds the possibility to implement token handlers
in external libraries (possibly provided by other projects).
A token library allows cryptsetup to understand metadata and provide
basic operations (activate, resize, dump metadata, handle keyslots).
The library now provides an interface that automatically tries to load
an external library for a token object in LUKS2 metadata.
Token libraries should be installed in the cryptsetup subdirectory
(usually /lib*/cryptsetup). This path is configurable through
--with-luks2-external-tokens-path configure option.
The external plugin loading can be compiled entirely out if
--disable-external-tokens configure option is used. The external token
interface can also be disabled runtime on the command line by
--disable-external-tokens cryptsetup switch or by calling
crypt_token_external_disable() API function.
The name of the loaded token library is determined from the JSON LUKS
metadata token object type. For example, "ssh" token will load library
"libcryptsetup-token-ssh.so".
External projects can use this interface to handle specific hardware
without introducing additional dependencies to libcryptsetup core.
Examples of such tokens are already available for the systemd project
for TPM2 and FIDO2 interfaces.
* Experimental SSH token
As a demonstration of the external LUKS2 token interface, a new SSH
token handler and cryptsetup-ssh utility is now provided and compiled
by default.
Crypsetup SSH token allows using remote keyfile through SSH protocol
(it will authenticate through SSH certificates).
You can disable the build of this token library with
--disable-ssh-token configure option.
To configure the token metadata, you need cryptsetup-ssh utility.
Activation of the device is then performed by the cryptsetup utility.
Example (how to activate LUKS2 through remote keyfile):
- configure existing LUKS2 device with keyslot activated by a keyfile
# cryptsetup luksAddKey <device> keyfile --key-slot 2
- store that keyfile on a remote system accessible through SSH
- configure SSH to use certificate for authentication
- add a LUKS2 token with cryptsetup-ssh utility:
# cryptsetup-ssh add <device>1 --key-slot 2 \
--ssh-server test-vm \
--ssh-user test \
--ssh-path /home/test/keyfile \
--ssh-keypath /home/test/.ssh/test_rsa_key
- you should see token metadata now with "cryptsetup luksDump ..."
...
Tokens:
0: ssh
ssh_server: test-vm
ssh_user: test
ssh_path: /home/test/keyfile
ssh_key_path: /home/test/.ssh/test_rsa_key
Keyslot: 2
- activation now should be automatic
# cryptsetup open <device> test --verbose
SSH token initiating ssh session.
Key slot 2 unlocked.
Command successful.
- to remove a token, you can use "cryptsetup token remove" command
(no plugin library required)
Please note SSH token is just demonstration of plugin interface API,
it is an EXPERIMENTAL feature.
* Default LUKS2 PBKDF is now Argon2id
Cryptsetup LUKS2 was using Argon2 while there were two versions,
data-independent (Argon2i) suitable for the KDF use case and
Argon2d (data-dependent). Later Argon2id was introduced as a new
mandatory algorithm.
We switched the password-based key derivation algorithms
following the latest version of Argon2 RFC draft
(https://datatracker.ietf.org/doc/draft-irtf-cfrg-argon2/) to Argon2id
(from Argon2i) as it is the mandatory and primary version
of the Argon2 algorithm.
There is no need to modify older containers; the main reason is that
RFC makes Argon2id the primary variant, while Argon2i subvariant is
only optional.
Argon2id provides better protection to side-channel attacks while
still providing protection to time-memory tradeoffs.
We will switch to OpenSSL implementation once it is available.
With a crystal ball as a reference, it could happen early in
OpenSSL 3.1 release.
Watch https://github.com/openssl/openssl/issues/4091.
* Increase minimal memory cost for Argon2 benchmark to 64MiB.
This patch increases the benchmarking value to 64 MiB (as minimal
suggested values in Argon2 RFC). For compatibility reasons, we still
allow older limits if set by a parameter.
NOTE: Argon2 RFC draft defines suggested parameters for disk
encryption, but the LUKS2 approach is slightly different. We need to
provide platform-independent values. The values in the draft expect
64bit systems (suggesting using 6 GiB of RAM). In comparison, we need
to provide compatibility with all 32bit systems, so allocating more
than 4GiB memory is not an option for LUKS2.
The maximal limit in LUKS2 stays for 4 GiB, and by default LUKS2 PBKDF
benchmarking sets maximum to 1 GIB, preferring an increase of CPU cost
while running benchmark
* Autodetect optimal encryption sector size on LUKS2 format.
While the support for larger encryption sectors is supported
for several releases, it required an additional parameter.
Code now uses automatic detection of 4096-bytes native sector devices
and automatically enables 4096-bytes encryption size for LUKS2.
If no setor size option is used, sector size is detected
automatically by cryptsetup. For libcryptsetup API, autodetection
happens once you specify sector_size to 0.
NOTE: crypt_format() function runs autodetection ONLY if you
recompile your application to the new API symbol version.
For backward compatibility, older applications ignore this parameter.
* Use VeraCrypt option by default and add --disable-veracrypt option.
While TrueCrypt is no longer developed and supported since 2014,
VeraCrypt devices (a successor of TrueCrypt) are much more used today.
Default is now to support VeraCrypt format (in addition to TrueCrypt),
making the --veracrypt option obsolete (ignored as it is the default).
If you need to disable VeraCrypt support, use the new option
--disable-veracrypt.
This option increases the time to recognize wrong passwords because
some VeraCrypt modes use a high PBKDF2 iteration count, and the code
must try all variants. This could be limited by using --hash and
--cipher options mentioned below.
* Support --hash and --cipher to limit opening time for TCRYPT type
If a user knows which particular PBKDF2 hash or cipher is used for
TrueCrypt/VeraCrypt container, TCRYPT format now supports --hash and
--cipher option.
Note the value means substring (all cipher chains containing
the cipher substring are tried).
For example, you can use
# cryptsetup tcryptDump --hash sha512 <container>
Note: to speed up the scan, the hash option (used for PBKDF)2 matters.
Cipher variants are scanned very quickly.
Use with care.
It can reveal some sensitive attributes of the container!
* Fixed default OpenSSL crypt backend support for OpenSSL3.
For OpenSSL version 3, we need to load legacy provider for older hash
and ciphers. For example, RIPEMD160 and Whirlpool hash algorithms are
no longer available by default.
NOTE: the plain format still uses RIPEMD160 for password hashing by
default. Changing the default would cause incompatibilities for many
old systems. Nevertheless, such a change will be needed very soon.
* integritysetup: add integrity-recalculate-reset flag.
The new dm-integrity option in kernel 5.13 can restart recalculation
from the beginning of the device.
It can be used to change the integrity checksum function.
New integritysetup --integrity-recalculate-reset option is added to
integritysetup, and CRYPT_ACTIVATE_RECALCULATE_RESET flag to API.
* cryptsetup: retains keyslot number in luksChangeKey for LUKS2.
In LUKS1, any change in keyslot means keyslot number change.
In LUKS2, we can retain the keyslot number.
Now luksKeyChange and crypt_keyslot_change_by_passphrase() API
retains keyslot number for LUKS2 by default.
* Fix cryptsetup resize using LUKS2 tokens.
Fix a bug where cryptsetup needlessly asked for a passphrase even
though the volume key was already unlocked via LUKS2 token.
* Add close --deferred and --cancel-deferred options.
All command-line utilities now understand deferred options for the
close command. Deferred close means that the device is removed
automagically after the last user closed the device.
Cancel deferred means to cancel this operation (so the device remains
active even if there a no longer active users).
CRYPT_DEACTIVATE_DEFERRED and CRYPT_DEACTIVATE_DEFERRED_CANCEL flags
are now available for API.
* Rewritten command-line option parsing to avoid libpopt arguments
memory leaks.
Note: some distributions use patched lipopt that still leaks memory
inside internal code (see Debian bug 941814).
* Add --test-args option.
New --test-args option can be used for syntax checking for valid
command-line arguments with no actions performed.
Note that it cannot detect unknown algorithm names and similar where
we need call API functions.
* libcryptsetup C API extensions (see libcryptsetup.h for details)
- crypt_logf - a printf like log function
- crypt_dump_json - dump LUKS2 metadata in JSON format
- crypt_header_is_detached - check if context use detached header
- crypt_token_max - get maximal tokens number
- crypt_token_external_path - get path for plugins (or NULL)
- crypt_token_external_disable - disable runtime support for plugins
- crypt_activate_by_token_pin - activate by token with additional PIN
- crypt_reencrypt - fixed prototype
The token plugin library interface cosists from these versioned
exported symbols (for details see header file and SSH token example):
cryptsetup_token_open
cryptsetup_token_open_pin
cryptsetup_token_buffer_free
cryptsetup_token_validate
cryptsetup_token_dump
cryptsetup_token_version
Since version 2.4 libcryptsetup uses exact symbol versioning
Newly introduced functions have CRYPTSETUP_2.4 namespace (the old
symbol always used CRYPTSETUP_2.0).
There is no change in soname (the library is backward compatible).
* Many fixes and additions to documentation and man pages.

View File

@@ -1,11 +1,11 @@
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA += lib/libcryptsetup.pc
pkgconfig_DATA = lib/libcryptsetup.pc
lib_LTLIBRARIES += libcryptsetup.la
lib_LTLIBRARIES = libcryptsetup.la
noinst_LTLIBRARIES += libutils_io.la
include_HEADERS += lib/libcryptsetup.h
include_HEADERS = lib/libcryptsetup.h
EXTRA_DIST += lib/libcryptsetup.pc.in lib/libcryptsetup.sym
@@ -15,7 +15,14 @@ libutils_io_la_SOURCES = \
lib/utils_io.c \
lib/utils_io.h
libcryptsetup_la_CPPFLAGS = $(AM_CPPFLAGS)
libcryptsetup_la_CPPFLAGS = $(AM_CPPFLAGS) \
-I $(top_srcdir)/lib/crypto_backend \
-I $(top_srcdir)/lib/luks1 \
-I $(top_srcdir)/lib/luks2 \
-I $(top_srcdir)/lib/loopaes \
-I $(top_srcdir)/lib/verity \
-I $(top_srcdir)/lib/tcrypt \
-I $(top_srcdir)/lib/integrity
libcryptsetup_la_DEPENDENCIES = libutils_io.la libcrypto_backend.la lib/libcryptsetup.sym
@@ -32,7 +39,6 @@ libcryptsetup_la_LIBADD = \
@LIBARGON2_LIBS@ \
@JSON_C_LIBS@ \
@BLKID_LIBS@ \
$(LTLIBICONV) \
libcrypto_backend.la \
libutils_io.la
@@ -42,8 +48,6 @@ libcryptsetup_la_SOURCES = \
lib/bitops.h \
lib/nls.h \
lib/libcryptsetup.h \
lib/libcryptsetup_macros.h \
lib/libcryptsetup_symver.h \
lib/utils.c \
lib/utils_benchmark.c \
lib/utils_crypt.c \
@@ -60,7 +64,6 @@ libcryptsetup_la_SOURCES = \
lib/utils_device_locking.c \
lib/utils_device_locking.h \
lib/utils_pbkdf.c \
lib/utils_safe_memory.c \
lib/utils_storage_wrappers.c \
lib/utils_storage_wrappers.h \
lib/libdevmapper.c \
@@ -71,7 +74,7 @@ libcryptsetup_la_SOURCES = \
lib/base64.h \
lib/base64.c \
lib/integrity/integrity.h \
lib/integrity/integrity.c \
lib/integrity/integrity.c \
lib/loopaes/loopaes.h \
lib/loopaes/loopaes.c \
lib/tcrypt/tcrypt.h \
@@ -87,7 +90,7 @@ libcryptsetup_la_SOURCES = \
lib/verity/verity.h \
lib/verity/rs_encode_char.c \
lib/verity/rs_decode_char.c \
lib/verity/rs.h \
lib/verity/rs.h \
lib/luks2/luks2_disk_metadata.c \
lib/luks2/luks2_json_format.c \
lib/luks2/luks2_json_metadata.c \
@@ -104,6 +107,4 @@ libcryptsetup_la_SOURCES = \
lib/luks2/luks2_internal.h \
lib/luks2/luks2.h \
lib/utils_blkid.c \
lib/utils_blkid.h \
lib/bitlk/bitlk.h \
lib/bitlk/bitlk.c
lib/utils_blkid.h

File diff suppressed because it is too large Load Diff

View File

@@ -1,145 +0,0 @@
/*
* BITLK (BitLocker-compatible) header definition
*
* Copyright (C) 2019-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2019-2021 Milan Broz
* Copyright (C) 2019-2021 Vojtech Trefny
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this file; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef _CRYPTSETUP_BITLK_H
#define _CRYPTSETUP_BITLK_H
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
struct crypt_device;
struct device;
struct volume_key;
#define BITLK_NONCE_SIZE 12
#define BITLK_SALT_SIZE 16
#define BITLK_VMK_MAC_TAG_SIZE 16
#define BITLK_STATE_NORMAL 0x0004
typedef enum {
BITLK_ENCRYPTION_TYPE_NORMAL = 0,
BITLK_ENCRYPTION_TYPE_EOW,
BITLK_ENCRYPTION_TYPE_UNKNOWN,
} BITLKEncryptionType;
typedef enum {
BITLK_PROTECTION_CLEAR_KEY = 0,
BITLK_PROTECTION_TPM,
BITLK_PROTECTION_STARTUP_KEY,
BITLK_PROTECTION_TPM_PIN,
BITLK_PROTECTION_RECOVERY_PASSPHRASE,
BITLK_PROTECTION_PASSPHRASE,
BITLK_PROTECTION_SMART_CARD,
BITLK_PROTECTION_UNKNOWN,
} BITLKVMKProtection;
typedef enum {
BITLK_ENTRY_TYPE_PROPERTY = 0x0000,
BITLK_ENTRY_TYPE_VMK = 0x0002,
BITLK_ENTRY_TYPE_FVEK = 0x0003,
BITLK_ENTRY_TYPE_STARTUP_KEY = 0x0006,
BITLK_ENTRY_TYPE_DESCRIPTION = 0x0007,
BITLK_ENTRY_TYPE_VOLUME_HEADER = 0x000f,
} BITLKFVEEntryType;
typedef enum {
BITLK_ENTRY_VALUE_ERASED = 0x0000,
BITLK_ENTRY_VALUE_KEY = 0x0001,
BITLK_ENTRY_VALUE_STRING = 0x0002,
BITLK_ENTRY_VALUE_STRETCH_KEY = 0x0003,
BITLK_ENTRY_VALUE_USE_KEY = 0x0004,
BITLK_ENTRY_VALUE_ENCRYPTED_KEY = 0x0005,
BITLK_ENTRY_VALUE_TPM_KEY = 0x0006,
BITLK_ENTRY_VALUE_VALIDATION = 0x0007,
BITLK_ENTRY_VALUE_VMK = 0x0008,
BITLK_ENTRY_VALUE_EXTERNAL_KEY = 0x0009,
BITLK_ENTRY_VALUE_OFFSET_SIZE = 0x000f,
BITLK_ENTRY_VALUE_RECOVERY_TIME = 0x015,
} BITLKFVEEntryValue;
struct bitlk_vmk {
char *guid;
char *name;
BITLKVMKProtection protection;
uint8_t salt[BITLK_SALT_SIZE];
uint8_t mac_tag[BITLK_VMK_MAC_TAG_SIZE];
uint8_t nonce[BITLK_NONCE_SIZE];
struct volume_key *vk;
struct bitlk_vmk *next;
};
struct bitlk_fvek {
uint8_t mac_tag[BITLK_VMK_MAC_TAG_SIZE];
uint8_t nonce[BITLK_NONCE_SIZE];
struct volume_key *vk;
};
struct bitlk_metadata {
uint16_t sector_size;
bool togo;
bool state;
BITLKEncryptionType type;
const char *cipher;
const char *cipher_mode;
uint16_t key_size;
char *guid;
uint64_t creation_time;
char *description;
uint64_t metadata_offset[3];
uint32_t metadata_version;
uint64_t volume_header_offset;
uint64_t volume_header_size;
struct bitlk_vmk *vmks;
struct bitlk_fvek *fvek;
};
int BITLK_read_sb(struct crypt_device *cd, struct bitlk_metadata *params);
int BITLK_dump(struct crypt_device *cd, struct device *device, struct bitlk_metadata *params);
int BITLK_get_volume_key(struct crypt_device *cd,
const char *password,
size_t passwordLen,
const struct bitlk_metadata *params,
struct volume_key **open_fvek_key);
int BITLK_activate_by_passphrase(struct crypt_device *cd,
const char *name,
const char *password,
size_t passwordLen,
const struct bitlk_metadata *params,
uint32_t flags);
int BITLK_activate_by_volume_key(struct crypt_device *cd,
const char *name,
const char *volume_key,
size_t volume_key_size,
const struct bitlk_metadata *params,
uint32_t flags);
void BITLK_bitlk_fvek_free(struct bitlk_fvek *fvek);
void BITLK_bitlk_vmk_free(struct bitlk_vmk *vmk);
void BITLK_bitlk_metadata_free(struct bitlk_metadata *params);
#endif

View File

@@ -2,8 +2,8 @@
* cryptsetup plain device helper functions
*
* Copyright (C) 2004 Jana Saout <jana@saout.de>
* Copyright (C) 2010-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2021 Milan Broz
* Copyright (C) 2010-2019 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2019 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,8 +1,8 @@
/*
* Argon2 PBKDF2 library wrapper
*
* Copyright (C) 2016-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2016-2021 Milan Broz
* Copyright (C) 2016-2019 Red Hat, Inc. All rights reserved.
* Copyright (C) 2016-2019 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public

View File

@@ -1,8 +1,8 @@
/*
* Cipher performance check
*
* Copyright (C) 2018-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2018-2021 Milan Broz
* Copyright (C) 2018-2019 Red Hat, Inc. All rights reserved.
* Copyright (C) 2018-2019 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -23,10 +23,6 @@
#include <time.h>
#include "crypto_backend_internal.h"
#ifndef CLOCK_MONOTONIC_RAW
#define CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC
#endif
/*
* This is not simulating storage, so using disk block causes extreme overhead.
* Let's use some fixed block size where results are more reliable...

View File

@@ -1,8 +1,8 @@
/*
* Linux kernel cipher generic utilities
*
* Copyright (C) 2018-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2018-2021 Milan Broz
* Copyright (C) 2018-2019 Red Hat, Inc. All rights reserved.
* Copyright (C) 2018-2019 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -31,6 +31,7 @@ struct cipher_alg {
bool wrapped_key;
};
/* FIXME: Getting block size should be dynamic from cipher backend. */
static const struct cipher_alg cipher_algs[] = {
{ "cipher_null", NULL, 16, false },
{ "aes", NULL, 16, false },
@@ -50,7 +51,6 @@ static const struct cipher_alg cipher_algs[] = {
{ "paes", NULL, 16, true }, /* protected AES, s390 wrapped key scheme */
{ "xchacha12,aes", "adiantum", 32, false },
{ "xchacha20,aes", "adiantum", 32, false },
{ "sm4", NULL, 16, false },
{ NULL, NULL, 0, false }
};
@@ -72,13 +72,7 @@ int crypt_cipher_ivsize(const char *name, const char *mode)
{
const struct cipher_alg *ca = _get_alg(name, mode);
if (!ca)
return -EINVAL;
if (mode && !strcasecmp(mode, "ecb"))
return 0;
return ca->blocksize;
return ca ? ca->blocksize : -EINVAL;
}
int crypt_cipher_wrapped_key(const char *name, const char *mode)

View File

@@ -1,8 +1,8 @@
/*
* crypto backend implementation
*
* Copyright (C) 2010-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2021 Milan Broz
* Copyright (C) 2010-2019 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2019 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,12 +26,13 @@
#include <stddef.h>
#include <string.h>
struct crypt_device;
struct crypt_hash;
struct crypt_hmac;
struct crypt_cipher;
struct crypt_storage;
int crypt_backend_init(void);
int crypt_backend_init(struct crypt_device *ctx);
void crypt_backend_destroy(void);
#define CRYPT_BACKEND_KERNEL (1 << 0) /* Crypto uses kernel part, for benchmark */
@@ -62,7 +63,7 @@ int crypt_backend_rng(char *buffer, size_t length, int quality, int fips);
/* PBKDF*/
struct crypt_pbkdf_limits {
uint32_t min_iterations, max_iterations;
uint32_t min_memory, max_memory, min_bench_memory;
uint32_t min_memory, max_memory;
uint32_t min_parallel, max_parallel;
};
@@ -109,7 +110,7 @@ int crypt_cipher_check_kernel(const char *name, const char *mode,
/* Storage encryption wrappers */
int crypt_storage_init(struct crypt_storage **ctx, size_t sector_size,
const char *cipher, const char *cipher_mode,
const void *key, size_t key_length, bool large_iv);
const void *key, size_t key_length);
void crypt_storage_destroy(struct crypt_storage *ctx);
int crypt_storage_decrypt(struct crypt_storage *ctx, uint64_t iv_offset,
uint64_t length, char *buffer);
@@ -118,12 +119,6 @@ int crypt_storage_encrypt(struct crypt_storage *ctx, uint64_t iv_offset,
bool crypt_storage_kernel_only(struct crypt_storage *ctx);
/* Temporary Bitlk helper */
int crypt_bitlk_decrypt_key(const void *key, size_t key_length,
const char *in, char *out, size_t length,
const char *iv, size_t iv_length,
const char *tag, size_t tag_length);
/* Memzero helper (memset on stack can be optimized out) */
static inline void crypt_backend_memzero(void *s, size_t n)
{

View File

@@ -1,8 +1,8 @@
/*
* crypto backend implementation
*
* Copyright (C) 2010-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2021 Milan Broz
* Copyright (C) 2010-2019 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2019 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -23,6 +23,7 @@
#include "crypto_backend.h"
#if USE_INTERNAL_PBKDF2
/* internal PBKDF2 implementation */
int pkcs5_pbkdf2(const char *hash,
const char *P, size_t Plen,
@@ -30,6 +31,7 @@ int pkcs5_pbkdf2(const char *hash,
unsigned int c,
unsigned int dkLen, char *DK,
unsigned int hash_block_size);
#endif
/* Argon2 implementation wrapper */
int argon2(const char *type, const char *password, size_t password_length,
@@ -53,9 +55,5 @@ int crypt_cipher_decrypt_kernel(struct crypt_cipher_kernel *ctx,
const char *in, char *out, size_t length,
const char *iv, size_t iv_length);
void crypt_cipher_destroy_kernel(struct crypt_cipher_kernel *ctx);
int crypt_bitlk_decrypt_key_kernel(const void *key, size_t key_length,
const char *in, char *out, size_t length,
const char *iv, size_t iv_length,
const char *tag, size_t tag_length);
#endif /* _CRYPTO_BACKEND_INTERNAL_H */

View File

@@ -1,8 +1,8 @@
/*
* Linux kernel userspace API crypto backend implementation (skcipher)
*
* Copyright (C) 2012-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2021 Milan Broz
* Copyright (C) 2012-2019 Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2019 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -40,10 +40,6 @@
#define SOL_ALG 279
#endif
#ifndef ALG_SET_AEAD_AUTHSIZE
#define ALG_SET_AEAD_AUTHSIZE 5
#endif
/*
* ciphers
*
@@ -53,7 +49,7 @@
*/
static int _crypt_cipher_init(struct crypt_cipher_kernel *ctx,
const void *key, size_t key_length,
size_t tag_length, struct sockaddr_alg *sa)
struct sockaddr_alg *sa)
{
if (!ctx)
return -EINVAL;
@@ -75,11 +71,6 @@ static int _crypt_cipher_init(struct crypt_cipher_kernel *ctx,
return -EINVAL;
}
if (tag_length && setsockopt(ctx->tfmfd, SOL_ALG, ALG_SET_AEAD_AUTHSIZE, NULL, tag_length) < 0) {
crypt_cipher_destroy_kernel(ctx);
return -EINVAL;
}
ctx->opfd = accept(ctx->tfmfd, NULL, 0);
if (ctx->opfd < 0) {
crypt_cipher_destroy_kernel(ctx);
@@ -96,22 +87,18 @@ int crypt_cipher_init_kernel(struct crypt_cipher_kernel *ctx, const char *name,
.salg_family = AF_ALG,
.salg_type = "skcipher",
};
int r;
if (!strcmp(name, "cipher_null"))
key_length = 0;
r = snprintf((char *)sa.salg_name, sizeof(sa.salg_name), "%s(%s)", mode, name);
if (r < 0 || (size_t)r >= sizeof(sa.salg_name))
return -EINVAL;
snprintf((char *)sa.salg_name, sizeof(sa.salg_name), "%s(%s)", mode, name);
return _crypt_cipher_init(ctx, key, key_length, 0, &sa);
return _crypt_cipher_init(ctx, key, key_length, &sa);
}
/* The in/out should be aligned to page boundary */
static int _crypt_cipher_crypt(struct crypt_cipher_kernel *ctx,
const char *in, size_t in_length,
char *out, size_t out_length,
const char *in, char *out, size_t length,
const char *iv, size_t iv_length,
uint32_t direction)
{
@@ -122,7 +109,7 @@ static int _crypt_cipher_crypt(struct crypt_cipher_kernel *ctx,
uint32_t *type;
struct iovec iov = {
.iov_base = (void*)(uintptr_t)in,
.iov_len = in_length,
.iov_len = length,
};
int iv_msg_size = iv ? CMSG_SPACE(sizeof(*alg_iv) + iv_length) : 0;
char buffer[CMSG_SPACE(sizeof(*type)) + iv_msg_size];
@@ -133,7 +120,7 @@ static int _crypt_cipher_crypt(struct crypt_cipher_kernel *ctx,
.msg_iovlen = 1,
};
if (!in || !out || !in_length)
if (!in || !out || !length)
return -EINVAL;
if ((!iv && iv_length) || (iv && !iv_length))
@@ -155,9 +142,6 @@ static int _crypt_cipher_crypt(struct crypt_cipher_kernel *ctx,
/* Set IV */
if (iv) {
header = CMSG_NXTHDR(&msg, header);
if (!header)
return -EINVAL;
header->cmsg_level = SOL_ALG;
header->cmsg_type = ALG_SET_IV;
header->cmsg_len = iv_msg_size;
@@ -167,14 +151,15 @@ static int _crypt_cipher_crypt(struct crypt_cipher_kernel *ctx,
}
len = sendmsg(ctx->opfd, &msg, 0);
if (len != (ssize_t)(in_length))
if (len != (ssize_t)length) {
r = -EIO;
else {
len = read(ctx->opfd, out, out_length);
if (len != (ssize_t)out_length)
r = -EIO;
goto bad;
}
len = read(ctx->opfd, out, length);
if (len != (ssize_t)length)
r = -EIO;
bad:
crypt_backend_memzero(buffer, sizeof(buffer));
return r;
}
@@ -183,7 +168,7 @@ int crypt_cipher_encrypt_kernel(struct crypt_cipher_kernel *ctx,
const char *in, char *out, size_t length,
const char *iv, size_t iv_length)
{
return _crypt_cipher_crypt(ctx, in, length, out, length,
return _crypt_cipher_crypt(ctx, in, out, length,
iv, iv_length, ALG_OP_ENCRYPT);
}
@@ -191,7 +176,7 @@ int crypt_cipher_decrypt_kernel(struct crypt_cipher_kernel *ctx,
const char *in, char *out, size_t length,
const char *iv, size_t iv_length)
{
return _crypt_cipher_crypt(ctx, in, length, out, length,
return _crypt_cipher_crypt(ctx, in, out, length,
iv, iv_length, ALG_OP_DECRYPT);
}
@@ -232,10 +217,7 @@ int crypt_cipher_check_kernel(const char *name, const char *mode,
}
salg_type = aead ? "aead" : "skcipher";
r = snprintf((char *)sa.salg_type, sizeof(sa.salg_type), "%s", salg_type);
if (r < 0 || (size_t)r >= sizeof(sa.salg_name))
return -EINVAL;
snprintf((char *)sa.salg_type, sizeof(sa.salg_type), "%s", salg_type);
memset(tmp_salg_name, 0, sizeof(tmp_salg_name));
/* FIXME: this is duplicating a part of devmapper backend */
@@ -248,7 +230,7 @@ int crypt_cipher_check_kernel(const char *name, const char *mode,
else
r = snprintf(tmp_salg_name, sizeof(tmp_salg_name), "%s(%s)", real_mode, name);
if (r < 0 || (size_t)r >= sizeof(tmp_salg_name))
if (r <= 0 || r > (int)(sizeof(sa.salg_name) - 1))
return -EINVAL;
memcpy(sa.salg_name, tmp_salg_name, sizeof(sa.salg_name));
@@ -261,56 +243,13 @@ int crypt_cipher_check_kernel(const char *name, const char *mode,
memset(key, 0xab, key_length);
*key = 0xef;
r = _crypt_cipher_init(&c, key, key_length, 0, &sa);
r = _crypt_cipher_init(&c, key, key_length, &sa);
crypt_cipher_destroy_kernel(&c);
free(key);
return r;
}
int crypt_bitlk_decrypt_key_kernel(const void *key, size_t key_length,
const char *in, char *out, size_t length,
const char *iv, size_t iv_length,
const char *tag, size_t tag_length)
{
struct crypt_cipher_kernel c;
struct sockaddr_alg sa = {
.salg_family = AF_ALG,
.salg_type = "aead",
.salg_name = "ccm(aes)",
};
int r;
char buffer[128], ccm_iv[16];
if (length + tag_length > sizeof(buffer))
return -EINVAL;
if (iv_length > sizeof(ccm_iv) - 2)
return -EINVAL;
r = _crypt_cipher_init(&c, key, key_length, tag_length, &sa);
if (r < 0)
return r;
memcpy(buffer, in, length);
memcpy(buffer + length, tag, tag_length);
/* CCM IV - RFC3610 */
memset(ccm_iv, 0, sizeof(ccm_iv));
ccm_iv[0] = 15 - iv_length - 1;
memcpy(ccm_iv + 1, iv, iv_length);
memset(ccm_iv + 1 + iv_length, 0, ccm_iv[0] + 1);
iv_length = sizeof(ccm_iv);
r = _crypt_cipher_crypt(&c, buffer, length + tag_length, out, length,
ccm_iv, iv_length, ALG_OP_DECRYPT);
crypt_cipher_destroy_kernel(&c);
crypt_backend_memzero(buffer, sizeof(buffer));
return r;
}
#else /* ENABLE_AF_ALG */
int crypt_cipher_init_kernel(struct crypt_cipher_kernel *ctx, const char *name,
const char *mode, const void *key, size_t key_length)
@@ -341,11 +280,4 @@ int crypt_cipher_check_kernel(const char *name, const char *mode,
/* Cannot check, expect success. */
return 0;
}
int crypt_bitlk_decrypt_key_kernel(const void *key, size_t key_length,
const char *in, char *out, size_t length,
const char *iv, size_t iv_length,
const char *tag, size_t tag_length)
{
return -ENOTSUP;
}
#endif

View File

@@ -1,8 +1,8 @@
/*
* GCRYPT crypto backend implementation
*
* Copyright (C) 2010-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2021 Milan Broz
* Copyright (C) 2010-2019 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2019 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -51,14 +51,9 @@ struct crypt_cipher {
} u;
};
struct hash_alg {
const char *name;
const char *gcrypt_name;
};
/*
* Test for wrong Whirlpool variant,
* Ref: https://lists.gnupg.org/pipermail/gcrypt-devel/2014-January/002889.html
* Ref: http://lists.gnupg.org/pipermail/gcrypt-devel/2014-January/002889.html
*/
static void crypt_hash_test_whirlpool_bug(void)
{
@@ -94,10 +89,8 @@ static void crypt_hash_test_whirlpool_bug(void)
crypto_backend_whirlpool_bug = 1;
}
int crypt_backend_init(void)
int crypt_backend_init(struct crypt_device *ctx)
{
int r;
if (crypto_backend_initialised)
return 0;
@@ -106,7 +99,7 @@ int crypt_backend_init(void)
return -ENOSYS;
}
/* If gcrypt compiled to support POSIX 1003.1e capabilities,
/* FIXME: If gcrypt compiled to support POSIX 1003.1e capabilities,
* it drops all privileges during secure memory initialisation.
* For now, the only workaround is to disable secure memory in gcrypt.
* cryptsetup always need at least cap_sys_admin privilege for dm-ioctl
@@ -127,12 +120,11 @@ int crypt_backend_init(void)
crypto_backend_initialised = 1;
crypt_hash_test_whirlpool_bug();
r = snprintf(version, sizeof(version), "gcrypt %s%s%s",
snprintf(version, 64, "gcrypt %s%s%s",
gcry_check_version(NULL),
crypto_backend_secmem ? "" : ", secmem disabled",
crypto_backend_whirlpool_bug > 0 ? ", flawed whirlpool" : "");
if (r < 0 || (size_t)r >= sizeof(version))
return -EINVAL;
crypto_backend_whirlpool_bug > 0 ? ", flawed whirlpool" : ""
);
return 0;
}
@@ -158,24 +150,10 @@ uint32_t crypt_backend_flags(void)
static const char *crypt_hash_compat_name(const char *name, unsigned int *flags)
{
const char *hash_name = name;
int i;
static struct hash_alg hash_algs[] = {
{ "blake2b-160", "blake2b_160" },
{ "blake2b-256", "blake2b_256" },
{ "blake2b-384", "blake2b_384" },
{ "blake2b-512", "blake2b_512" },
{ "blake2s-128", "blake2s_128" },
{ "blake2s-160", "blake2s_160" },
{ "blake2s-224", "blake2s_224" },
{ "blake2s-256", "blake2s_256" },
{ NULL, NULL, }};
if (!name)
return NULL;
/* "whirlpool_gcryptbug" is out shortcut to flawed whirlpool
* in libgcrypt < 1.6.0 */
if (!strcasecmp(name, "whirlpool_gcryptbug")) {
if (name && !strcasecmp(name, "whirlpool_gcryptbug")) {
#if GCRYPT_VERSION_NUMBER >= 0x010601
if (flags)
*flags |= GCRY_MD_FLAG_BUGEMU1;
@@ -183,15 +161,6 @@ static const char *crypt_hash_compat_name(const char *name, unsigned int *flags)
hash_name = "whirlpool";
}
i = 0;
while (hash_algs[i].name) {
if (!strcasecmp(name, hash_algs[i].name)) {
hash_name = hash_algs[i].gcrypt_name;
break;
}
i++;
}
return hash_name;
}
@@ -347,7 +316,7 @@ void crypt_hmac_destroy(struct crypt_hmac *ctx)
}
/* RNG */
int crypt_backend_rng(char *buffer, size_t length, int quality, int fips __attribute__((unused)))
int crypt_backend_rng(char *buffer, size_t length, int quality, int fips)
{
switch(quality) {
case CRYPT_RND_NORMAL:
@@ -510,43 +479,3 @@ bool crypt_cipher_kernel_only(struct crypt_cipher *ctx)
{
return ctx->use_kernel;
}
int crypt_bitlk_decrypt_key(const void *key, size_t key_length,
const char *in, char *out, size_t length,
const char *iv, size_t iv_length,
const char *tag, size_t tag_length)
{
#ifdef GCRY_CCM_BLOCK_LEN
gcry_cipher_hd_t hd;
uint64_t l[3];
int r = -EINVAL;
if (gcry_cipher_open(&hd, GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CCM, 0))
return -EINVAL;
if (gcry_cipher_setkey(hd, key, key_length))
goto out;
if (gcry_cipher_setiv(hd, iv, iv_length))
goto out;
l[0] = length;
l[1] = 0;
l[2] = tag_length;
if (gcry_cipher_ctl(hd, GCRYCTL_SET_CCM_LENGTHS, l, sizeof(l)))
goto out;
if (gcry_cipher_decrypt(hd, out, length, in, length))
goto out;
if (gcry_cipher_checktag(hd, tag, tag_length))
goto out;
r = 0;
out:
gcry_cipher_close(hd);
return r;
#else
return -ENOTSUP;
#endif
}

View File

@@ -1,8 +1,8 @@
/*
* Linux kernel userspace API crypto backend implementation
*
* Copyright (C) 2010-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2021 Milan Broz
* Copyright (C) 2010-2019 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2019 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 @@
#include <linux/if_alg.h>
#include "crypto_backend_internal.h"
/* FIXME: remove later */
#ifndef AF_ALG
#define AF_ALG 38
#endif
@@ -61,14 +62,6 @@ static struct hash_alg hash_algs[] = {
{ "stribog256","streebog256", 32, 64 },
{ "stribog512","streebog512", 64, 64 },
{ "sm3", "sm3", 32, 64 },
{ "blake2b-160","blake2b-160",20, 128 },
{ "blake2b-256","blake2b-256",32, 128 },
{ "blake2b-384","blake2b-384",48, 128 },
{ "blake2b-512","blake2b-512",64, 128 },
{ "blake2s-128","blake2s-128",16, 64 },
{ "blake2s-160","blake2s-160",20, 64 },
{ "blake2s-224","blake2s-224",28, 64 },
{ "blake2s-256","blake2s-256",32, 64 },
{ NULL, NULL, 0, 0 }
};
@@ -117,7 +110,7 @@ static int crypt_kernel_socket_init(struct sockaddr_alg *sa, int *tfmfd, int *op
return 0;
}
int crypt_backend_init(void)
int crypt_backend_init(struct crypt_device *ctx)
{
struct utsname uts;
struct sockaddr_alg sa = {
@@ -125,7 +118,7 @@ int crypt_backend_init(void)
.salg_type = "hash",
.salg_name = "sha256",
};
int r, tfmfd = -1, opfd = -1;
int tfmfd = -1, opfd = -1;
if (crypto_backend_initialised)
return 0;
@@ -133,17 +126,15 @@ int crypt_backend_init(void)
if (uname(&uts) == -1 || strcmp(uts.sysname, "Linux"))
return -EINVAL;
r = snprintf(version, sizeof(version), "%s %s kernel cryptoAPI",
uts.sysname, uts.release);
if (r < 0 || (size_t)r >= sizeof(version))
return -EINVAL;
if (crypt_kernel_socket_init(&sa, &tfmfd, &opfd, NULL, 0) < 0)
return -EINVAL;
close(tfmfd);
close(opfd);
snprintf(version, sizeof(version), "%s %s kernel cryptoAPI",
uts.sysname, uts.release);
crypto_backend_initialised = 1;
return 0;
}
@@ -264,7 +255,6 @@ int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
.salg_family = AF_ALG,
.salg_type = "hash",
};
int r;
h = malloc(sizeof(*h));
if (!h)
@@ -277,12 +267,8 @@ int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
}
h->hash_len = ha->length;
r = snprintf((char *)sa.salg_name, sizeof(sa.salg_name),
snprintf((char *)sa.salg_name, sizeof(sa.salg_name),
"hmac(%s)", ha->kernel_name);
if (r < 0 || (size_t)r >= sizeof(sa.salg_name)) {
free(h);
return -EINVAL;
}
if (crypt_kernel_socket_init(&sa, &h->tfmfd, &h->opfd, key, key_length) < 0) {
free(h);
@@ -329,8 +315,7 @@ void crypt_hmac_destroy(struct crypt_hmac *ctx)
}
/* RNG - N/A */
int crypt_backend_rng(char *buffer __attribute__((unused)), size_t length __attribute__((unused)),
int quality __attribute__((unused)), int fips __attribute__((unused)))
int crypt_backend_rng(char *buffer, size_t length, int quality, int fips)
{
return -EINVAL;
}
@@ -403,16 +388,7 @@ int crypt_cipher_decrypt(struct crypt_cipher *ctx,
return crypt_cipher_decrypt_kernel(&ctx->ck, in, out, length, iv, iv_length);
}
bool crypt_cipher_kernel_only(struct crypt_cipher *ctx __attribute__((unused)))
bool crypt_cipher_kernel_only(struct crypt_cipher *ctx)
{
return true;
}
int crypt_bitlk_decrypt_key(const void *key, size_t key_length,
const char *in, char *out, size_t length,
const char *iv, size_t iv_length,
const char *tag, size_t tag_length)
{
return crypt_bitlk_decrypt_key_kernel(key, key_length, in, out, length,
iv, iv_length, tag, tag_length);
}

View File

@@ -1,8 +1,8 @@
/*
* Nettle crypto backend implementation
*
* Copyright (C) 2011-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2011-2021 Milan Broz
* Copyright (C) 2011-2019 Red Hat, Inc. All rights reserved.
* Copyright (C) 2011-2019 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -213,7 +213,7 @@ static struct hash_alg *_get_alg(const char *name)
return NULL;
}
int crypt_backend_init(void)
int crypt_backend_init(struct crypt_device *ctx)
{
return 0;
}
@@ -301,16 +301,12 @@ int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
h->hash = _get_alg(name);
if (!h->hash) {
free(h);
return -EINVAL;
}
if (!h->hash)
goto bad;
h->key = malloc(key_length);
if (!h->key) {
free(h);
return -ENOMEM;
}
if (!h->key)
goto bad;
memcpy(h->key, key, key_length);
h->key_length = key_length;
@@ -320,6 +316,9 @@ int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
*ctx = h;
return 0;
bad:
free(h);
return -EINVAL;
}
static void crypt_hmac_restart(struct crypt_hmac *ctx)
@@ -352,10 +351,7 @@ void crypt_hmac_destroy(struct crypt_hmac *ctx)
}
/* RNG - N/A */
int crypt_backend_rng(char *buffer __attribute__((unused)),
size_t length __attribute__((unused)),
int quality __attribute__((unused)),
int fips __attribute__((unused)))
int crypt_backend_rng(char *buffer, size_t length, int quality, int fips)
{
return -EINVAL;
}
@@ -433,16 +429,7 @@ int crypt_cipher_decrypt(struct crypt_cipher *ctx,
return crypt_cipher_decrypt_kernel(&ctx->ck, in, out, length, iv, iv_length);
}
bool crypt_cipher_kernel_only(struct crypt_cipher *ctx __attribute__((unused)))
bool crypt_cipher_kernel_only(struct crypt_cipher *ctx)
{
return true;
}
int crypt_bitlk_decrypt_key(const void *key, size_t key_length,
const char *in, char *out, size_t length,
const char *iv, size_t iv_length,
const char *tag, size_t tag_length)
{
return crypt_bitlk_decrypt_key_kernel(key, key_length, in, out, length,
iv, iv_length, tag, tag_length);
}

View File

@@ -1,8 +1,8 @@
/*
* NSS crypto backend implementation
*
* Copyright (C) 2010-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2021 Milan Broz
* Copyright (C) 2010-2019 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2019 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -75,10 +75,8 @@ static struct hash_alg *_get_alg(const char *name)
return NULL;
}
int crypt_backend_init(void)
int crypt_backend_init(struct crypt_device *ctx)
{
int r;
if (crypto_backend_initialised)
return 0;
@@ -86,13 +84,10 @@ int crypt_backend_init(void)
return -EINVAL;
#if HAVE_DECL_NSS_GETVERSION
r = snprintf(version, sizeof(version), "NSS %s", NSS_GetVersion());
snprintf(version, 64, "NSS %s", NSS_GetVersion());
#else
r = snprintf(version, sizeof(version), "NSS");
snprintf(version, 64, "NSS");
#endif
if (r < 0 || (size_t)r >= sizeof(version))
return -EINVAL;
crypto_backend_initialised = 1;
return 0;
}
@@ -225,28 +220,28 @@ int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
h->hash = _get_alg(name);
if (!h->hash)
goto err;
goto bad;
h->slot = PK11_GetInternalKeySlot();
if (!h->slot)
goto err;
goto bad;
h->key = PK11_ImportSymKey(h->slot, h->hash->ck_type, PK11_OriginUnwrap,
CKA_SIGN, &keyItem, NULL);
if (!h->key)
goto err;
goto bad;
h->md = PK11_CreateContextBySymKey(h->hash->ck_type, CKA_SIGN, h->key,
&noParams);
if (!h->md)
goto err;
goto bad;
if (PK11_DigestBegin(h->md) != SECSuccess)
goto err;
goto bad;
*ctx = h;
return 0;
err:
bad:
crypt_hmac_destroy(h);
return -EINVAL;
}
@@ -303,7 +298,7 @@ void crypt_hmac_destroy(struct crypt_hmac *ctx)
}
/* RNG */
int crypt_backend_rng(char *buffer, size_t length, int quality __attribute__((unused)), int fips)
int crypt_backend_rng(char *buffer, size_t length, int quality, int fips)
{
if (fips)
return -EINVAL;
@@ -382,16 +377,7 @@ int crypt_cipher_decrypt(struct crypt_cipher *ctx,
return crypt_cipher_decrypt_kernel(&ctx->ck, in, out, length, iv, iv_length);
}
bool crypt_cipher_kernel_only(struct crypt_cipher *ctx __attribute__((unused)))
bool crypt_cipher_kernel_only(struct crypt_cipher *ctx)
{
return true;
}
int crypt_bitlk_decrypt_key(const void *key, size_t key_length,
const char *in, char *out, size_t length,
const char *iv, size_t iv_length,
const char *tag, size_t tag_length)
{
return crypt_bitlk_decrypt_key_kernel(key, key_length, in, out, length,
iv, iv_length, tag, tag_length);
}

View File

@@ -1,8 +1,8 @@
/*
* OPENSSL crypto backend implementation
*
* Copyright (C) 2010-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2021 Milan Broz
* Copyright (C) 2010-2019 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2019 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,24 +28,12 @@
* for all of the code used other than OpenSSL.
*/
/*
* HMAC will be later rewritten to a new API from OpenSSL 3
*/
#define OPENSSL_SUPPRESS_DEPRECATED
#include <string.h>
#include <errno.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/rand.h>
#include "crypto_backend_internal.h"
#if OPENSSL_VERSION_MAJOR >= 3
#include <openssl/provider.h>
static OSSL_PROVIDER *ossl_legacy = NULL;
static OSSL_PROVIDER *ossl_default = NULL;
#endif
#define CONST_CAST(x) (x)(uintptr_t)
static int crypto_backend_initialised = 0;
@@ -73,11 +61,6 @@ struct crypt_cipher {
} u;
};
struct hash_alg {
const char *name;
const char *openssl_name;
};
/*
* Compatible wrappers for OpenSSL < 1.1.0 and LibreSSL < 2.7.0
*/
@@ -89,10 +72,6 @@ static void openssl_backend_init(void)
OpenSSL_add_all_algorithms();
}
static void openssl_backend_exit(void)
{
}
static const char *openssl_backend_version(void)
{
return SSLeay_version(SSLEAY_VERSION);
@@ -132,30 +111,6 @@ static void HMAC_CTX_free(HMAC_CTX *md)
#else
static void openssl_backend_init(void)
{
/*
* OpenSSL >= 3.0.0 provides some algorithms in legacy provider
*/
#if OPENSSL_VERSION_MAJOR >= 3
OPENSSL_init_crypto(OPENSSL_INIT_NO_ATEXIT, NULL);
ossl_legacy = OSSL_PROVIDER_try_load(NULL, "legacy", 0);
ossl_default = OSSL_PROVIDER_try_load(NULL, "default", 0);
#endif
}
static void openssl_backend_exit(void)
{
#if OPENSSL_VERSION_MAJOR >= 3
/*
* If Destructor was already called, we must not call it again
*/
if (OPENSSL_init_crypto(0, NULL) != 0) {
OSSL_PROVIDER_unload(ossl_legacy);
OSSL_PROVIDER_unload(ossl_default);
OPENSSL_cleanup();
}
ossl_legacy = NULL;
ossl_default = NULL;
#endif
}
static const char *openssl_backend_version(void)
@@ -164,7 +119,7 @@ static const char *openssl_backend_version(void)
}
#endif
int crypt_backend_init(void)
int crypt_backend_init(struct crypt_device *ctx)
{
if (crypto_backend_initialised)
return 0;
@@ -178,7 +133,6 @@ int crypt_backend_init(void)
void crypt_backend_destroy(void)
{
crypto_backend_initialised = 0;
openssl_backend_exit();
}
uint32_t crypt_backend_flags(void)
@@ -191,36 +145,11 @@ const char *crypt_backend_version(void)
return openssl_backend_version();
}
static const char *crypt_hash_compat_name(const char *name)
{
const char *hash_name = name;
int i;
static struct hash_alg hash_algs[] = {
{ "blake2b-512", "blake2b512" },
{ "blake2s-256", "blake2s256" },
{ NULL, NULL, }};
if (!name)
return NULL;
i = 0;
while (hash_algs[i].name) {
if (!strcasecmp(name, hash_algs[i].name)) {
hash_name = hash_algs[i].openssl_name;
break;
}
i++;
}
return hash_name;
}
/* HASH */
int crypt_hash_size(const char *name)
{
const EVP_MD *hash_id;
const EVP_MD *hash_id = EVP_get_digestbyname(name);
hash_id = EVP_get_digestbyname(crypt_hash_compat_name(name));
if (!hash_id)
return -EINVAL;
@@ -241,7 +170,7 @@ int crypt_hash_init(struct crypt_hash **ctx, const char *name)
return -ENOMEM;
}
h->hash_id = EVP_get_digestbyname(crypt_hash_compat_name(name));
h->hash_id = EVP_get_digestbyname(name);
if (!h->hash_id) {
EVP_MD_CTX_free(h->md);
free(h);
@@ -326,7 +255,7 @@ int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
return -ENOMEM;
}
h->hash_id = EVP_get_digestbyname(crypt_hash_compat_name(name));
h->hash_id = EVP_get_digestbyname(name);
if (!h->hash_id) {
HMAC_CTX_free(h->md);
free(h);
@@ -380,8 +309,7 @@ void crypt_hmac_destroy(struct crypt_hmac *ctx)
}
/* RNG */
int crypt_backend_rng(char *buffer, size_t length,
int quality __attribute__((unused)), int fips __attribute__((unused)))
int crypt_backend_rng(char *buffer, size_t length, int quality, int fips)
{
if (RAND_bytes((unsigned char *)buffer, length) != 1)
return -EINVAL;
@@ -403,7 +331,7 @@ int crypt_pbkdf(const char *kdf, const char *hash,
return -EINVAL;
if (!strcmp(kdf, "pbkdf2")) {
hash_id = EVP_get_digestbyname(crypt_hash_compat_name(hash));
hash_id = EVP_get_digestbyname(hash);
if (!hash_id)
return -EINVAL;
@@ -442,7 +370,7 @@ static int _cipher_init(EVP_CIPHER_CTX **hd_enc, EVP_CIPHER_CTX **hd_dec, const
key_bits /= 2;
r = snprintf(cipher_name, sizeof(cipher_name), "%s-%d-%s", name, key_bits, mode);
if (r < 0 || (size_t)r >= sizeof(cipher_name))
if (r < 0 || r >= (int)sizeof(cipher_name))
return -EINVAL;
type = EVP_get_cipherbyname(cipher_name);
@@ -577,40 +505,3 @@ bool crypt_cipher_kernel_only(struct crypt_cipher *ctx)
{
return ctx->use_kernel;
}
int crypt_bitlk_decrypt_key(const void *key, size_t key_length __attribute__((unused)),
const char *in, char *out, size_t length,
const char *iv, size_t iv_length,
const char *tag, size_t tag_length)
{
#ifdef EVP_CTRL_CCM_SET_IVLEN
EVP_CIPHER_CTX *ctx;
int len = 0, r = -EINVAL;
ctx = EVP_CIPHER_CTX_new();
if (!ctx)
return -EINVAL;
if (EVP_DecryptInit_ex(ctx, EVP_aes_256_ccm(), NULL, NULL, NULL) != 1)
goto out;
//EVP_CIPHER_CTX_key_length(ctx)
//EVP_CIPHER_CTX_iv_length(ctx)
if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_IVLEN, iv_length, NULL) != 1)
goto out;
if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, tag_length, CONST_CAST(void*)tag) != 1)
goto out;
if (EVP_DecryptInit_ex(ctx, NULL, NULL, key, (const unsigned char*)iv) != 1)
goto out;
if (EVP_DecryptUpdate(ctx, (unsigned char*)out, &len, (const unsigned char*)in, length) == 1)
r = 0;
out:
EVP_CIPHER_CTX_free(ctx);
return r;
#else
return -ENOTSUP;
#endif
}

View File

@@ -2,7 +2,7 @@
* Generic wrapper for storage encryption modes and Initial Vectors
* (reimplementation of some functions from Linux dm-crypt kernel)
*
* Copyright (C) 2014-2021 Milan Broz
* Copyright (C) 2014-2019 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -21,7 +21,6 @@
#include <stdlib.h>
#include <errno.h>
#include <strings.h>
#include "bitops.h"
#include "crypto_backend.h"
@@ -32,16 +31,16 @@
* IV documentation: https://gitlab.com/cryptsetup/cryptsetup/wikis/DMCrypt
*/
struct crypt_sector_iv {
enum { IV_NONE, IV_NULL, IV_PLAIN, IV_PLAIN64, IV_ESSIV, IV_BENBI, IV_PLAIN64BE, IV_EBOIV } type;
enum { IV_NONE, IV_NULL, IV_PLAIN, IV_PLAIN64, IV_ESSIV, IV_BENBI, IV_PLAIN64BE } type;
int iv_size;
char *iv;
struct crypt_cipher *cipher;
int shift;
struct crypt_cipher *essiv_cipher;
int benbi_shift;
};
/* Block encryption storage context */
struct crypt_storage {
size_t sector_size;
unsigned sector_shift;
unsigned iv_shift;
struct crypt_cipher *cipher;
struct crypt_sector_iv cipher_iv;
@@ -57,15 +56,12 @@ static int int_log2(unsigned int x)
static int crypt_sector_iv_init(struct crypt_sector_iv *ctx,
const char *cipher_name, const char *mode_name,
const char *iv_name, const void *key, size_t key_length,
size_t sector_size)
const char *iv_name, const void *key, size_t key_length)
{
int r;
memset(ctx, 0, sizeof(*ctx));
ctx->iv_size = crypt_cipher_ivsize(cipher_name, mode_name);
if (ctx->iv_size < 0 || (strcmp(mode_name, "ecb") && ctx->iv_size < 8))
if (ctx->iv_size < 8)
return -ENOENT;
if (!strcmp(cipher_name, "cipher_null") ||
@@ -90,6 +86,7 @@ static int crypt_sector_iv_init(struct crypt_sector_iv *ctx,
char *hash_name = strchr(iv_name, ':');
int hash_size;
char tmp[256];
int r;
if (!hash_name)
return -EINVAL;
@@ -117,7 +114,7 @@ static int crypt_sector_iv_init(struct crypt_sector_iv *ctx,
return r;
}
r = crypt_cipher_init(&ctx->cipher, cipher_name, "ecb",
r = crypt_cipher_init(&ctx->essiv_cipher, cipher_name, "ecb",
tmp, hash_size);
crypt_backend_memzero(tmp, sizeof(tmp));
if (r)
@@ -130,15 +127,7 @@ static int crypt_sector_iv_init(struct crypt_sector_iv *ctx,
return -EINVAL;
ctx->type = IV_BENBI;
ctx->shift = SECTOR_SHIFT - log;
} else if (!strncasecmp(iv_name, "eboiv", 5)) {
r = crypt_cipher_init(&ctx->cipher, cipher_name, "ecb",
key, key_length);
if (r)
return r;
ctx->type = IV_EBOIV;
ctx->shift = int_log2(sector_size);
ctx->benbi_shift = SECTOR_SHIFT - log;
} else
return -ENOENT;
@@ -174,20 +163,14 @@ static int crypt_sector_iv_generate(struct crypt_sector_iv *ctx, uint64_t sector
case IV_ESSIV:
memset(ctx->iv, 0, ctx->iv_size);
*(uint64_t *)ctx->iv = cpu_to_le64(sector);
return crypt_cipher_encrypt(ctx->cipher,
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->shift) + 1);
val = cpu_to_be64((sector << ctx->benbi_shift) + 1);
memcpy(ctx->iv + ctx->iv_size - sizeof(val), &val, sizeof(val));
break;
case IV_EBOIV:
memset(ctx->iv, 0, ctx->iv_size);
*(uint64_t *)ctx->iv = cpu_to_le64(sector << ctx->shift);
return crypt_cipher_encrypt(ctx->cipher,
ctx->iv, ctx->iv, ctx->iv_size, NULL, 0);
break;
default:
return -EINVAL;
}
@@ -197,8 +180,8 @@ static int crypt_sector_iv_generate(struct crypt_sector_iv *ctx, uint64_t sector
static void crypt_sector_iv_destroy(struct crypt_sector_iv *ctx)
{
if (ctx->type == IV_ESSIV || ctx->type == IV_EBOIV)
crypt_cipher_destroy(ctx->cipher);
if (ctx->type == IV_ESSIV)
crypt_cipher_destroy(ctx->essiv_cipher);
if (ctx->iv) {
memset(ctx->iv, 0, ctx->iv_size);
@@ -214,8 +197,7 @@ int crypt_storage_init(struct crypt_storage **ctx,
size_t sector_size,
const char *cipher,
const char *cipher_mode,
const void *key, size_t key_length,
bool large_iv)
const void *key, size_t key_length)
{
struct crypt_storage *s;
char mode_name[64];
@@ -247,14 +229,14 @@ int crypt_storage_init(struct crypt_storage **ctx,
return r;
}
r = crypt_sector_iv_init(&s->cipher_iv, cipher, mode_name, cipher_iv, key, key_length, sector_size);
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_size = sector_size;
s->iv_shift = large_iv ? int_log2(sector_size) - SECTOR_SHIFT : 0;
s->sector_shift = int_log2(sector_size);
s->iv_shift = s->sector_shift - SECTOR_SHIFT;
*ctx = s;
return 0;
@@ -267,20 +249,19 @@ int crypt_storage_decrypt(struct crypt_storage *ctx,
uint64_t i;
int r = 0;
if (length & (ctx->sector_size - 1))
if (length & ((1 << ctx->sector_shift) - 1))
return -EINVAL;
if (iv_offset & ((ctx->sector_size >> SECTOR_SHIFT) - 1))
return -EINVAL;
length >>= ctx->sector_shift;
for (i = 0; i < length; i += ctx->sector_size) {
r = crypt_sector_iv_generate(&ctx->cipher_iv, (iv_offset + (i >> SECTOR_SHIFT)) >> ctx->iv_shift);
for (i = 0; i < length; i++) {
r = crypt_sector_iv_generate(&ctx->cipher_iv, iv_offset + (uint64_t)(i << ctx->iv_shift));
if (r)
break;
r = crypt_cipher_decrypt(ctx->cipher,
&buffer[i],
&buffer[i],
ctx->sector_size,
&buffer[i << ctx->sector_shift],
&buffer[i << ctx->sector_shift],
1 << ctx->sector_shift,
ctx->cipher_iv.iv,
ctx->cipher_iv.iv_size);
if (r)
@@ -297,20 +278,19 @@ int crypt_storage_encrypt(struct crypt_storage *ctx,
uint64_t i;
int r = 0;
if (length & (ctx->sector_size - 1))
if (length & ((1 << ctx->sector_shift) - 1))
return -EINVAL;
if (iv_offset & ((ctx->sector_size >> SECTOR_SHIFT) - 1))
return -EINVAL;
length >>= ctx->sector_shift;
for (i = 0; i < length; i += ctx->sector_size) {
r = crypt_sector_iv_generate(&ctx->cipher_iv, (iv_offset + (i >> SECTOR_SHIFT)) >> ctx->iv_shift);
for (i = 0; i < length; i++) {
r = crypt_sector_iv_generate(&ctx->cipher_iv, iv_offset + (i << ctx->iv_shift));
if (r)
break;
r = crypt_cipher_encrypt(ctx->cipher,
&buffer[i],
&buffer[i],
ctx->sector_size,
&buffer[i << ctx->sector_shift],
&buffer[i << ctx->sector_shift],
1 << ctx->sector_shift,
ctx->cipher_iv.iv,
ctx->cipher_iv.iv_size);
if (r)

View File

@@ -4,8 +4,8 @@
* Copyright (C) 2004 Free Software Foundation
*
* cryptsetup related changes
* Copyright (C) 2012-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2021 Milan Broz
* Copyright (C) 2012-2019 Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2019 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public

View File

@@ -1,8 +1,8 @@
/*
* PBKDF performance check
* Copyright (C) 2012-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2021 Milan Broz
* Copyright (C) 2016-2020 Ondrej Mosnacek
* Copyright (C) 2012-2019 Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2019 Milan Broz
* Copyright (C) 2016-2019 Ondrej Mosnacek
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -27,10 +27,6 @@
#include <sys/resource.h>
#include "crypto_backend.h"
#ifndef CLOCK_MONOTONIC_RAW
#define CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC
#endif
#define BENCH_MIN_MS 250
#define BENCH_MIN_MS_FAST 10
#define BENCH_PERCENT_ATLEAST 95
@@ -48,7 +44,6 @@ int crypt_pbkdf_get_limits(const char *kdf, struct crypt_pbkdf_limits *limits)
limits->min_iterations = 1000; /* recommendation in NIST SP 800-132 */
limits->max_iterations = UINT32_MAX;
limits->min_memory = 0; /* N/A */
limits->min_bench_memory=0; /* N/A */
limits->max_memory = 0; /* N/A */
limits->min_parallel = 0; /* N/A */
limits->max_parallel = 0; /* N/A */
@@ -56,8 +51,7 @@ int crypt_pbkdf_get_limits(const char *kdf, struct crypt_pbkdf_limits *limits)
} else if (!strcmp(kdf, "argon2i") || !strcmp(kdf, "argon2id")) {
limits->min_iterations = 4;
limits->max_iterations = UINT32_MAX;
limits->min_memory = 32; /* hard limit */
limits->min_bench_memory=64*1024; /* 64 MiB minimum for benchmark */
limits->min_memory = 32;
limits->max_memory = 4*1024*1024; /* 4GiB */
limits->min_parallel = 1;
limits->max_parallel = 4;
@@ -76,7 +70,7 @@ static long time_ms(struct rusage *start, struct rusage *end)
count_kernel_time = 1;
/*
* If there is no self usage info, count system time.
* 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 &&
@@ -363,10 +357,8 @@ static int crypt_pbkdf_check(const char *kdf, const char *hash,
ms = time_ms(&rstart, &rend);
if (ms) {
PBKDF2_temp = (double)iterations * target_ms / ms;
if (PBKDF2_temp > UINT32_MAX) {
r = -EINVAL;
goto out;
}
if (PBKDF2_temp > UINT32_MAX)
return -EINVAL;
*iter_secs = (uint32_t)PBKDF2_temp;
}
@@ -410,19 +402,15 @@ int crypt_pbkdf_perf(const char *kdf, const char *hash,
{
struct crypt_pbkdf_limits pbkdf_limits;
int r = -EINVAL;
uint32_t min_memory;
if (!kdf || !iterations_out || !memory_out)
return -EINVAL;
/* FIXME: whole limits propagation should be more clear here */
r = crypt_pbkdf_get_limits(kdf, &pbkdf_limits);
if (r < 0)
return r;
min_memory = pbkdf_limits.min_bench_memory;
if (min_memory > max_memory_kb)
min_memory = max_memory_kb;
*memory_out = 0;
*iterations_out = 0;
@@ -435,7 +423,7 @@ int crypt_pbkdf_perf(const char *kdf, const char *hash,
r = crypt_argon2_check(kdf, password, password_size,
salt, salt_size, volume_key_size,
pbkdf_limits.min_iterations,
min_memory,
pbkdf_limits.min_memory,
max_memory_kb,
parallel_threads, time_ms, iterations_out,
memory_out, progress, usrptr);

View File

@@ -1,7 +1,7 @@
/*
* Integrity volume handling
*
* Copyright (C) 2016-2021 Milan Broz
* Copyright (C) 2016-2019 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -22,6 +22,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <uuid/uuid.h>
#include "integrity.h"
@@ -40,7 +41,8 @@ static int INTEGRITY_read_superblock(struct crypt_device *cd,
if (read_lseek_blockwise(devfd, device_block_size(cd, device),
device_alignment(device), sb, sizeof(*sb), offset) != sizeof(*sb) ||
memcmp(sb->magic, SB_MAGIC, sizeof(sb->magic)) ||
sb->version < SB_VERSION_1 || sb->version > SB_VERSION_5) {
(sb->version != SB_VERSION_1 && sb->version != SB_VERSION_2 &&
sb->version != SB_VERSION_3)) {
log_std(cd, "No integrity superblock detected on %s.\n",
device_path(device));
r = -EINVAL;
@@ -56,9 +58,7 @@ static int INTEGRITY_read_superblock(struct crypt_device *cd,
return r;
}
int INTEGRITY_read_sb(struct crypt_device *cd,
struct crypt_params_integrity *params,
uint32_t *flags)
int INTEGRITY_read_sb(struct crypt_device *cd, struct crypt_params_integrity *params)
{
struct superblock sb;
int r;
@@ -70,9 +70,6 @@ int INTEGRITY_read_sb(struct crypt_device *cd,
params->sector_size = SECTOR_SIZE << sb.log2_sectors_per_block;
params->tag_size = sb.integrity_tag_size;
if (flags)
*flags = sb.flags;
return 0;
}
@@ -92,15 +89,13 @@ int INTEGRITY_dump(struct crypt_device *cd, struct device *device, uint64_t offs
log_std(cd, "journal_sections %u\n", sb.journal_sections);
log_std(cd, "provided_data_sectors %" PRIu64 "\n", sb.provided_data_sectors);
log_std(cd, "sector_size %u\n", SECTOR_SIZE << sb.log2_sectors_per_block);
if (sb.version >= SB_VERSION_2 && (sb.flags & SB_FLAG_RECALCULATING))
if (sb.version == SB_VERSION_2 && (sb.flags & SB_FLAG_RECALCULATING))
log_std(cd, "recalc_sector %" PRIu64 "\n", sb.recalc_sector);
log_std(cd, "log2_blocks_per_bitmap %u\n", sb.log2_blocks_per_bitmap_bit);
log_std(cd, "flags %s%s%s%s%s\n",
log_std(cd, "flags %s%s%s\n",
sb.flags & SB_FLAG_HAVE_JOURNAL_MAC ? "have_journal_mac " : "",
sb.flags & SB_FLAG_RECALCULATING ? "recalculating " : "",
sb.flags & SB_FLAG_DIRTY_BITMAP ? "dirty_bitmap " : "",
sb.flags & SB_FLAG_FIXED_PADDING ? "fix_padding " : "",
sb.flags & SB_FLAG_FIXED_HMAC ? "fix_hmac " : "");
sb.flags & SB_FLAG_DIRTY_BITMAP ? "dirty_bitmap " : "");
return 0;
}
@@ -120,7 +115,7 @@ int INTEGRITY_data_sectors(struct crypt_device *cd,
return 0;
}
int INTEGRITY_key_size(struct crypt_device *cd __attribute__((unused)), const char *integrity)
int INTEGRITY_key_size(struct crypt_device *cd, const char *integrity)
{
if (!integrity)
return 0;
@@ -142,28 +137,7 @@ int INTEGRITY_key_size(struct crypt_device *cd __attribute__((unused)), const ch
return -EINVAL;
}
/* Return hash or hmac(hash) size, if known */
int INTEGRITY_hash_tag_size(const char *integrity)
{
char hash[MAX_CIPHER_LEN];
int r;
if (!integrity)
return 0;
if (!strcmp(integrity, "crc32") || !strcmp(integrity, "crc32c"))
return 4;
r = sscanf(integrity, "hmac(%" MAX_CIPHER_LEN_STR "[^)]s", hash);
if (r == 1)
r = crypt_hash_size(hash);
else
r = crypt_hash_size(integrity);
return r < 0 ? 0 : r;
}
int INTEGRITY_tag_size(struct crypt_device *cd __attribute__((unused)),
int INTEGRITY_tag_size(struct crypt_device *cd,
const char *integrity,
const char *cipher,
const char *cipher_mode)
@@ -189,7 +163,7 @@ int INTEGRITY_tag_size(struct crypt_device *cd __attribute__((unused)),
if (!integrity || !strcmp(integrity, "none"))
auth_tag_size = 0;
else if (!strcmp(integrity, "aead"))
auth_tag_size = 16; /* gcm- mode only */
auth_tag_size = 16; //FIXME gcm- mode only
else if (!strcmp(integrity, "cmac(aes)"))
auth_tag_size = 16;
else if (!strcmp(integrity, "hmac(sha1)"))
@@ -213,7 +187,7 @@ int INTEGRITY_create_dmd_device(struct crypt_device *cd,
struct volume_key *journal_crypt_key,
struct volume_key *journal_mac_key,
struct crypt_dm_active_device *dmd,
uint32_t flags, uint32_t sb_flags)
uint32_t flags)
{
int r;
@@ -224,16 +198,12 @@ int INTEGRITY_create_dmd_device(struct crypt_device *cd,
.flags = flags,
};
/* Workaround for kernel dm-integrity table bug */
if (sb_flags & SB_FLAG_RECALCULATING)
dmd->flags |= CRYPT_ACTIVATE_RECALCULATE;
r = INTEGRITY_data_sectors(cd, crypt_metadata_device(cd),
crypt_get_data_offset(cd) * SECTOR_SIZE, &dmd->size);
if (r < 0)
return r;
return dm_integrity_target_set(cd, &dmd->segment, 0, dmd->size,
return dm_integrity_target_set(&dmd->segment, 0, dmd->size,
crypt_metadata_device(cd), crypt_data_device(cd),
crypt_get_integrity_tag_size(cd), crypt_get_data_offset(cd),
crypt_get_sector_size(cd), vk, journal_crypt_key,
@@ -243,8 +213,7 @@ int INTEGRITY_create_dmd_device(struct crypt_device *cd,
int INTEGRITY_activate_dmd_device(struct crypt_device *cd,
const char *name,
const char *type,
struct crypt_dm_active_device *dmd,
uint32_t sb_flags)
struct crypt_dm_active_device *dmd)
{
int r;
uint32_t dmi_flags;
@@ -269,22 +238,7 @@ int INTEGRITY_activate_dmd_device(struct crypt_device *cd,
r = dm_create_device(cd, name, type, dmd);
if (r < 0 && (dm_flags(cd, DM_INTEGRITY, &dmi_flags) || !(dmi_flags & DM_INTEGRITY_SUPPORTED))) {
log_err(cd, _("Kernel does not support dm-integrity mapping."));
return -ENOTSUP;
}
if (r < 0 && (sb_flags & SB_FLAG_FIXED_PADDING) && !dm_flags(cd, DM_INTEGRITY, &dmi_flags) &&
!(dmi_flags & DM_INTEGRITY_FIX_PADDING_SUPPORTED)) {
log_err(cd, _("Kernel does not support dm-integrity fixed metadata alignment."));
return -ENOTSUP;
}
if (r < 0 && (dmd->flags & CRYPT_ACTIVATE_RECALCULATE) &&
!(crypt_get_compatibility(cd) & CRYPT_COMPAT_LEGACY_INTEGRITY_RECALC) &&
((sb_flags & SB_FLAG_FIXED_HMAC) ?
(tgt->u.integrity.vk && !tgt->u.integrity.journal_integrity_key) :
(tgt->u.integrity.vk || tgt->u.integrity.journal_integrity_key))) {
log_err(cd, _("Kernel refuses to activate insecure recalculate option (see legacy activation options to override)."));
log_err(cd, _("Kernel doesn't support dm-integrity mapping."));
return -ENOTSUP;
}
@@ -297,16 +251,15 @@ int INTEGRITY_activate(struct crypt_device *cd,
struct volume_key *vk,
struct volume_key *journal_crypt_key,
struct volume_key *journal_mac_key,
uint32_t flags, uint32_t sb_flags)
uint32_t flags)
{
struct crypt_dm_active_device dmd = {};
int r = INTEGRITY_create_dmd_device(cd, params, vk, journal_crypt_key,
journal_mac_key, &dmd, flags, sb_flags);
int r = INTEGRITY_create_dmd_device(cd, params, vk, journal_crypt_key, journal_mac_key, &dmd, flags);
if (r < 0)
return r;
r = INTEGRITY_activate_dmd_device(cd, name, CRYPT_INTEGRITY, &dmd, sb_flags);
r = INTEGRITY_activate_dmd_device(cd, name, CRYPT_INTEGRITY, &dmd);
dm_targets_free(cd, &dmd);
return r;
}
@@ -330,15 +283,13 @@ int INTEGRITY_format(struct crypt_device *cd,
uuid_generate(tmp_uuid_bin);
uuid_unparse(tmp_uuid_bin, tmp_uuid);
r = snprintf(tmp_name, sizeof(tmp_name), "temporary-cryptsetup-%s", tmp_uuid);
if (r < 0 || (size_t)r >= sizeof(tmp_name))
return -EINVAL;
snprintf(tmp_name, sizeof(tmp_name), "temporary-cryptsetup-%s", tmp_uuid);
/* There is no data area, we can actually use fake zeroed key */
if (params && params->integrity_key_size)
vk = crypt_alloc_volume_key(params->integrity_key_size, NULL);
r = dm_integrity_target_set(cd, tgt, 0, dmdi.size, crypt_metadata_device(cd),
r = dm_integrity_target_set(tgt, 0, dmdi.size, crypt_metadata_device(cd),
crypt_data_device(cd), crypt_get_integrity_tag_size(cd),
crypt_get_data_offset(cd), crypt_get_sector_size(cd), vk,
journal_crypt_key, journal_mac_key, params);
@@ -352,7 +303,7 @@ int INTEGRITY_format(struct crypt_device *cd,
r = device_block_adjust(cd, tgt->data_device, DEV_EXCL, tgt->u.integrity.offset, NULL, NULL);
if (r < 0 && (dm_flags(cd, DM_INTEGRITY, &dmi_flags) || !(dmi_flags & DM_INTEGRITY_SUPPORTED))) {
log_err(cd, _("Kernel does not support dm-integrity mapping."));
log_err(cd, _("Kernel doesn't support dm-integrity mapping."));
r = -ENOTSUP;
}
if (r) {

View File

@@ -1,7 +1,7 @@
/*
* Integrity header definition
*
* Copyright (C) 2016-2021 Milan Broz
* Copyright (C) 2016-2019 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -34,14 +34,10 @@ struct crypt_dm_active_device;
#define SB_VERSION_1 1
#define SB_VERSION_2 2
#define SB_VERSION_3 3
#define SB_VERSION_4 4
#define SB_VERSION_5 5
#define SB_FLAG_HAVE_JOURNAL_MAC (1 << 0)
#define SB_FLAG_RECALCULATING (1 << 1) /* V2 only */
#define SB_FLAG_DIRTY_BITMAP (1 << 2) /* V3 only */
#define SB_FLAG_FIXED_PADDING (1 << 3) /* V4 only */
#define SB_FLAG_FIXED_HMAC (1 << 4) /* V5 only */
struct superblock {
uint8_t magic[8];
@@ -57,21 +53,19 @@ struct superblock {
uint64_t recalc_sector; /* V2 only */
} __attribute__ ((packed));
int INTEGRITY_read_sb(struct crypt_device *cd,
struct crypt_params_integrity *params,
uint32_t *flags);
int INTEGRITY_read_sb(struct crypt_device *cd, struct crypt_params_integrity *params);
int INTEGRITY_dump(struct crypt_device *cd, struct device *device, uint64_t offset);
int INTEGRITY_data_sectors(struct crypt_device *cd,
struct device *device, uint64_t offset,
uint64_t *data_sectors);
int INTEGRITY_key_size(struct crypt_device *cd, const char *integrity);
int INTEGRITY_key_size(struct crypt_device *cd,
const char *integrity);
int INTEGRITY_tag_size(struct crypt_device *cd,
const char *integrity,
const char *cipher,
const char *cipher_mode);
int INTEGRITY_hash_tag_size(const char *integrity);
int INTEGRITY_format(struct crypt_device *cd,
const struct crypt_params_integrity *params,
@@ -84,7 +78,7 @@ int INTEGRITY_activate(struct crypt_device *cd,
struct volume_key *vk,
struct volume_key *journal_crypt_key,
struct volume_key *journal_mac_key,
uint32_t flags, uint32_t sb_flags);
uint32_t flags);
int INTEGRITY_create_dmd_device(struct crypt_device *cd,
const struct crypt_params_integrity *params,
@@ -92,11 +86,10 @@ int INTEGRITY_create_dmd_device(struct crypt_device *cd,
struct volume_key *journal_crypt_key,
struct volume_key *journal_mac_key,
struct crypt_dm_active_device *dmd,
uint32_t flags, uint32_t sb_flags);
uint32_t flags);
int INTEGRITY_activate_dmd_device(struct crypt_device *cd,
const char *name,
const char *type,
struct crypt_dm_active_device *dmd,
uint32_t sb_flags);
struct crypt_dm_active_device *dmd);
#endif

View File

@@ -3,8 +3,8 @@
*
* Copyright (C) 2004 Jana Saout <jana@saout.de>
* Copyright (C) 2004-2007 Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2021 Milan Broz
* Copyright (C) 2009-2019 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2019 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -30,7 +30,6 @@
#include <stdlib.h>
#include <unistd.h>
#include <inttypes.h>
#include <fcntl.h>
#include "nls.h"
#include "bitops.h"
@@ -41,25 +40,45 @@
#include "utils_fips.h"
#include "utils_keyring.h"
#include "utils_io.h"
#include "crypto_backend/crypto_backend.h"
#include "crypto_backend.h"
#include "utils_storage_wrappers.h"
#include "libcryptsetup.h"
#include "libcryptsetup_macros.h"
#include "libcryptsetup_symver.h"
/* to silent gcc -Wcast-qual for const cast */
#define CONST_CAST(x) (x)(uintptr_t)
#define SHIFT_4K 12
#define SECTOR_SHIFT 9
#define SECTOR_SIZE (1 << SECTOR_SHIFT)
#define MAX_SECTOR_SIZE 4096 /* min page size among all platforms */
#define DEFAULT_DISK_ALIGNMENT 1048576 /* 1MiB */
#define DEFAULT_MEM_ALIGNMENT 4096
#define LOG_MAX_LEN 4096
#define MAX_DM_DEPS 32
#define CRYPT_SUBDEV "SUBDEV" /* prefix for sublayered devices underneath public crypt types */
#ifndef O_CLOEXEC
#define O_CLOEXEC 0
#define at_least(a, b) ({ __typeof__(a) __at_least = (a); (__at_least >= (b))?__at_least:(b); })
#define MISALIGNED(a, b) ((a) & ((b) - 1))
#define MISALIGNED_4K(a) MISALIGNED((a), 1 << SHIFT_4K)
#define MISALIGNED_512(a) MISALIGNED((a), 1 << SECTOR_SHIFT)
#define NOTPOW2(a) MISALIGNED((a), (a))
#ifndef ARRAY_SIZE
# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
#endif
#define MOVE_REF(x, y) \
do { \
typeof (x) *_px = &(x), *_py = &(y); \
*_px = *_py; \
*_py = NULL; \
} while (0)
struct crypt_device;
struct luks2_reencrypt;
struct luks2_reenc_context;
struct volume_key {
int id;
@@ -120,8 +139,6 @@ void device_sync(struct crypt_device *cd, struct device *device);
int device_check_size(struct crypt_device *cd,
struct device *device,
uint64_t req_offset, int falloc);
void device_set_block_size(struct device *device, size_t size);
size_t device_optimal_encryption_sector_size(struct crypt_device *cd, struct device *device);
int device_open_locked(struct crypt_device *cd, struct device *device, int flags);
int device_read_lock(struct crypt_device *cd, struct device *device);
@@ -162,7 +179,7 @@ char *crypt_get_partition_device(const char *dev_path, uint64_t offset, uint64_t
char *crypt_get_base_device(const char *dev_path);
uint64_t crypt_dev_partition_offset(const char *dev_path);
int lookup_by_disk_id(const char *dm_uuid);
int lookup_by_sysfs_uuid_field(const char *dm_uuid);
int lookup_by_sysfs_uuid_field(const char *dm_uuid, size_t max_len);
int crypt_uuid_cmp(const char *dm_uuid, const char *hdr_uuid);
size_t crypt_getpagesize(void);
@@ -171,10 +188,11 @@ uint64_t crypt_getphysmemory_kb(void);
int init_crypto(struct crypt_device *ctx);
#define log_dbg(c, x...) crypt_logf(c, CRYPT_LOG_DEBUG, x)
#define log_std(c, x...) crypt_logf(c, CRYPT_LOG_NORMAL, x)
#define log_verbose(c, x...) crypt_logf(c, CRYPT_LOG_VERBOSE, x)
#define log_err(c, x...) crypt_logf(c, CRYPT_LOG_ERROR, x)
void logger(struct crypt_device *cd, int level, const char *file, int line, const char *format, ...) __attribute__ ((format (printf, 5, 6)));
#define log_dbg(c, x...) logger(c, CRYPT_LOG_DEBUG, __FILE__, __LINE__, x)
#define log_std(c, x...) logger(c, CRYPT_LOG_NORMAL, __FILE__, __LINE__, x)
#define log_verbose(c, x...) logger(c, CRYPT_LOG_VERBOSE, __FILE__, __LINE__, x)
#define log_err(c, x...) logger(c, CRYPT_LOG_ERROR, __FILE__, __LINE__, x)
int crypt_get_debug_level(void);
@@ -199,8 +217,8 @@ int PLAIN_activate(struct crypt_device *cd,
uint32_t flags);
void *crypt_get_hdr(struct crypt_device *cd, const char *type);
void crypt_set_luks2_reencrypt(struct crypt_device *cd, struct luks2_reencrypt *rh);
struct luks2_reencrypt *crypt_get_luks2_reencrypt(struct crypt_device *cd);
void crypt_set_reenc_context(struct crypt_device *cd, struct luks2_reenc_context *rh);
struct luks2_reenc_context *crypt_get_reenc_context(struct crypt_device *cd);
int onlyLUKS2(struct crypt_device *cd);
int onlyLUKS2mask(struct crypt_device *cd, uint32_t mask);
@@ -226,7 +244,7 @@ int crypt_use_keyring_for_vk(struct crypt_device *cd);
void crypt_drop_keyring_key_by_description(struct crypt_device *cd, const char *key_description, key_type_t ktype);
void crypt_drop_keyring_key(struct crypt_device *cd, struct volume_key *vks);
static inline uint64_t compact_version(uint16_t major, uint16_t minor, uint16_t patch, uint16_t release)
static inline uint64_t version(uint16_t major, uint16_t minor, uint16_t patch, uint16_t release)
{
return (uint64_t)release | ((uint64_t)patch << 16) | ((uint64_t)minor << 32) | ((uint64_t)major << 48);
}
@@ -243,12 +261,4 @@ int crypt_compare_dm_devices(struct crypt_device *cd,
const struct crypt_dm_active_device *tgt);
static inline void *crypt_zalloc(size_t size) { return calloc(1, size); }
static inline bool uint64_mult_overflow(uint64_t *u, uint64_t b, size_t size)
{
*u = (uint64_t)b * size;
if ((uint64_t)(*u / size) != b)
return true;
return false;
}
#endif /* INTERNAL_H */

View File

@@ -3,8 +3,8 @@
*
* Copyright (C) 2004 Jana Saout <jana@saout.de>
* Copyright (C) 2004-2007 Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2021 Milan Broz
* Copyright (C) 2009-2019 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2019 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -215,15 +215,6 @@ void crypt_set_log_callback(struct crypt_device *cd,
* @param msg log message
*/
void crypt_log(struct crypt_device *cd, int level, const char *msg);
/**
* Log function with variable arguments.
*
* @param cd crypt device handle
* @param level log level
* @param format formatted log message
*/
void crypt_logf(struct crypt_device *cd, int level, const char *format, ...);
/** @} */
/**
@@ -423,8 +414,6 @@ int crypt_get_metadata_size(struct crypt_device *cd,
#define CRYPT_TCRYPT "TCRYPT"
/** INTEGRITY dm-integrity device */
#define CRYPT_INTEGRITY "INTEGRITY"
/** BITLK (BitLocker-compatible mode) */
#define CRYPT_BITLK "BITLK"
/** LUKS any version */
#define CRYPT_LUKS NULL
@@ -516,8 +505,6 @@ struct crypt_params_verity {
#define CRYPT_VERITY_CHECK_HASH (1 << 1)
/** Create hash - format hash device */
#define CRYPT_VERITY_CREATE_HASH (1 << 2)
/** Root hash signature required for activation */
#define CRYPT_VERITY_ROOT_HASH_SIGNATURE (1 << 3)
/**
*
@@ -599,7 +586,7 @@ struct crypt_params_luks2 {
const struct crypt_params_integrity *integrity_params; /**< Data integrity parameters or @e NULL*/
size_t data_alignment; /**< data area alignment in 512B sectors, data offset is multiple of this */
const char *data_device; /**< detached encrypted data device or @e NULL */
uint32_t sector_size; /**< encryption sector size, 0 triggers auto-detection for optimal encryption sector size */
uint32_t sector_size; /**< encryption sector size */
const char *label; /**< header label or @e NULL*/
const char *subsystem; /**< header subsystem label or @e NULL*/
};
@@ -642,30 +629,6 @@ int crypt_format(struct crypt_device *cd,
size_t volume_key_size,
void *params);
/**
* Set format compatibility flags.
*
* @param cd crypt device handle
* @param flags CRYPT_COMPATIBILITY_* flags
*/
void crypt_set_compatibility(struct crypt_device *cd, uint32_t flags);
/**
* Get compatibility flags.
*
* @param cd crypt device handle
*
* @returns compatibility flags
*/
uint32_t crypt_get_compatibility(struct crypt_device *cd);
/** dm-integrity device uses less effective (legacy) padding (old kernels) */
#define CRYPT_COMPAT_LEGACY_INTEGRITY_PADDING (1 << 0)
/** dm-integrity device does not protect superblock with HMAC (old kernels) */
#define CRYPT_COMPAT_LEGACY_INTEGRITY_HMAC (1 << 1)
/** dm-integrity allow recalculating of volumes with HMAC keys (old kernels) */
#define CRYPT_COMPAT_LEGACY_INTEGRITY_RECALC (1 << 2)
/**
* Convert to new type for already existing device.
*
@@ -865,20 +828,6 @@ int crypt_resume_by_keyfile(struct crypt_device *cd,
int keyslot,
const char *keyfile,
size_t keyfile_size);
/**
* Resume crypt device using provided volume key.
*
* @param cd crypt device handle
* @param name name of device to resume
* @param volume_key provided volume key
* @param volume_key_size size of volume_key
*
* @return @e 0 on success or negative errno value otherwise.
*/
int crypt_resume_by_volume_key(struct crypt_device *cd,
const char *name,
const char *volume_key,
size_t volume_key_size);
/** @} */
/**
@@ -1112,18 +1061,6 @@ int crypt_keyslot_destroy(struct crypt_device *cd, int keyslot);
#define CRYPT_ACTIVATE_SERIALIZE_MEMORY_HARD_PBKDF (1 << 19)
/** dm-integrity: direct writes, use bitmap to track dirty sectors */
#define CRYPT_ACTIVATE_NO_JOURNAL_BITMAP (1 << 20)
/** device is suspended (key should be wiped from memory), output only */
#define CRYPT_ACTIVATE_SUSPENDED (1 << 21)
/** use IV sector counted in sector_size instead of default 512 bytes sectors */
#define CRYPT_ACTIVATE_IV_LARGE_SECTORS (1 << 22)
/** dm-verity: panic_on_corruption flag - panic kernel on corruption */
#define CRYPT_ACTIVATE_PANIC_ON_CORRUPTION (1 << 23)
/** dm-crypt: bypass internal workqueue and process read requests synchronously. */
#define CRYPT_ACTIVATE_NO_READ_WORKQUEUE (1 << 24)
/** dm-crypt: bypass internal workqueue and process write requests synchronously. */
#define CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE (1 << 25)
/** dm-integrity: reset automatic recalculation */
#define CRYPT_ACTIVATE_RECALCULATE_RESET (1 << 26)
/**
* Active device runtime attributes
@@ -1315,31 +1252,6 @@ int crypt_activate_by_volume_key(struct crypt_device *cd,
size_t volume_key_size,
uint32_t flags);
/**
* Activate VERITY device using provided key and optional signature).
*
* @param cd crypt device handle
* @param name name of device to create
* @param volume_key provided volume key
* @param volume_key_size size of volume_key
* @param signature buffer with signature for the key
* @param signature_size bsize of signature buffer
* @param flags activation flags
*
* @return @e 0 on success or negative errno value otherwise.
*
* @note For VERITY the volume key means root hash required for activation.
* Because kernel dm-verity is always read only, you have to provide
* CRYPT_ACTIVATE_READONLY flag always.
*/
int crypt_activate_by_signed_key(struct crypt_device *cd,
const char *name,
const char *volume_key,
size_t volume_key_size,
const char *signature,
size_t signature_size,
uint32_t flags);
/**
* Activate device using passphrase stored in kernel keyring.
*
@@ -1366,8 +1278,6 @@ int crypt_activate_by_keyring(struct crypt_device *cd,
#define CRYPT_DEACTIVATE_DEFERRED (1 << 0)
/** force deactivation - if the device is busy, it is replaced by error device */
#define CRYPT_DEACTIVATE_FORCE (1 << 1)
/** if set, remove lazy deactivation */
#define CRYPT_DEACTIVATE_DEFERRED_CANCEL (1 << 2)
/**
* Deactivate crypt device. This function tries to remove active device-mapper
@@ -1412,7 +1322,6 @@ int crypt_deactivate(struct crypt_device *cd, const char *name);
*
* @note For TCRYPT cipher chain is the volume key concatenated
* for all ciphers in chain.
* @note For VERITY the volume key means root hash used for activation.
*/
int crypt_volume_key_get(struct crypt_device *cd,
int keyslot,
@@ -1471,17 +1380,6 @@ crypt_status_info crypt_status(struct crypt_device *cd, const char *name);
*/
int crypt_dump(struct crypt_device *cd);
/**
* Dump JSON-formatted information about LUKS2 device
*
* @param cd crypt device handle (only LUKS2 format supported)
* @param json buffer with JSON, if NULL use log callback for output
* @param flags dump flags (reserved)
*
* @return @e 0 on success or negative errno value otherwise.
*/
int crypt_dump_json(struct crypt_device *cd, const char **json, uint32_t flags);
/**
* Get cipher used in device.
*
@@ -1513,11 +1411,11 @@ const char *crypt_get_cipher_mode(struct crypt_device *cd);
const char *crypt_get_uuid(struct crypt_device *cd);
/**
* Get path to underlying device.
* Get path to underlaying device.
*
* @param cd crypt device handle
*
* @return path to underlying device name
* @return path to underlaying device name
*
*/
const char *crypt_get_device_name(struct crypt_device *cd);
@@ -1527,7 +1425,7 @@ const char *crypt_get_device_name(struct crypt_device *cd);
*
* @param cd crypt device handle
*
* @return path to underlying device name
* @return path to underlaying device name
*
*/
const char *crypt_get_metadata_device_name(struct crypt_device *cd);
@@ -1574,21 +1472,6 @@ int crypt_get_volume_key_size(struct crypt_device *cd);
*/
int crypt_get_sector_size(struct crypt_device *cd);
/**
* Check if initialized LUKS context uses detached header
* (LUKS header located on a different device than data.)
*
* @param cd crypt device handle
*
* @return @e 1 if detached header is used, @e 0 if not
* or negative errno value otherwise.
*
* @note This is a runtime attribute, it does not say
* if a LUKS device requires detached header.
* This function works only with LUKS devices.
*/
int crypt_header_is_detached(struct crypt_device *cd);
/**
* Get device parameters for VERITY device.
*
@@ -1986,19 +1869,6 @@ int crypt_wipe(struct crypt_device *cd,
* @{
*/
/**
* Get number of tokens supported for device type.
*
* @param type crypt device type
*
* @return token count or negative errno otherwise if device
* doesn't not support tokens.
*
* @note Real number of supported tokens for a particular device depends
* on usable metadata area size.
*/
int crypt_token_max(const char *type);
/** Iterate through all tokens */
#define CRYPT_ANY_TOKEN -1
@@ -2156,15 +2026,6 @@ int crypt_token_is_assigned(struct crypt_device *cd,
* @param buffer returned allocated buffer with password
* @param buffer_len length of the buffer
* @param usrptr user data in @link crypt_activate_by_token @endlink
*
* @return 0 on success (token passed LUKS2 keyslot passphrase in buffer) or
* negative errno otherwise.
*
* @note Negative ENOANO errno means that token is PIN protected and caller should
* use @link crypt_activate_by_token_pin @endlink with PIN provided.
*
* @note Negative EAGAIN errno means token handler requires additional hardware
* not present in the system.
*/
typedef int (*crypt_token_open_func) (
struct crypt_device *cd,
@@ -2173,38 +2034,6 @@ typedef int (*crypt_token_open_func) (
size_t *buffer_len,
void *usrptr);
/**
* Token handler open with passphrase/PIN function prototype.
* This function retrieves password from a token and return allocated buffer
* containing this password. This buffer has to be deallocated by calling
* free() function and content should be wiped before deallocation.
*
* @param cd crypt device handle
* @param token token id
* @param pin passphrase (or PIN) to unlock token (may be binary data)
* @param pin_size size of @e pin
* @param buffer returned allocated buffer with password
* @param buffer_len length of the buffer
* @param usrptr user data in @link crypt_activate_by_token @endlink
*
* @return 0 on success (token passed LUKS2 keyslot passphrase in buffer) or
* negative errno otherwise.
*
* @note Negative ENOANO errno means that token is PIN protected and PIN was
* missing or wrong.
*
* @note Negative EAGAIN errno means token handler requires additional hardware
* not present in the system.
*/
typedef int (*crypt_token_open_pin_func) (
struct crypt_device *cd,
int token,
const char *pin,
size_t pin_size,
char **buffer,
size_t *buffer_len,
void *usrptr);
/**
* Token handler buffer free function prototype.
* This function is used by library to free the buffer with keyslot
@@ -2242,16 +2071,6 @@ typedef int (*crypt_token_validate_func) (struct crypt_device *cd, const char *j
*/
typedef void (*crypt_token_dump_func) (struct crypt_device *cd, const char *json);
/**
* Token handler version function prototype.
* This function is supposed to return pointer to version string information.
*
* @note The returned string is advised to contain only version.
* For example '1.0.0' or 'v1.2.3.4'.
*
*/
typedef const char * (*crypt_token_version_func) (void);
/**
* Token handler
*/
@@ -2272,30 +2091,6 @@ typedef struct {
*/
int crypt_token_register(const crypt_token_handler *handler);
/**
* Report configured path where library searches for external token handlers
*
* @return @e absolute path when external tokens are enabled or @e NULL otherwise.
*/
const char *crypt_token_external_path(void);
/**
* Disable external token handlers (plugins) support
* If disabled, it cannot be enabled again.
*/
void crypt_token_external_disable(void);
/** ABI version for external token in libcryptsetup-token-<name>.so */
#define CRYPT_TOKEN_ABI_VERSION1 "CRYPTSETUP_TOKEN_1.0"
/** ABI exported symbol for external token */
#define CRYPT_TOKEN_ABI_OPEN "cryptsetup_token_open" /* mandatory */
#define CRYPT_TOKEN_ABI_OPEN_PIN "cryptsetup_token_open_pin"
#define CRYPT_TOKEN_ABI_BUFFER_FREE "cryptsetup_token_buffer_free"
#define CRYPT_TOKEN_ABI_VALIDATE "cryptsetup_token_validate"
#define CRYPT_TOKEN_ABI_DUMP "cryptsetup_token_dump"
#define CRYPT_TOKEN_ABI_VERSION "cryptsetup_token_version"
/**
* Activate device or check key using a token.
*
@@ -2306,71 +2101,12 @@ void crypt_token_external_disable(void);
* @param flags activation flags
*
* @return unlocked key slot number or negative errno otherwise.
*
* @note EPERM errno means token provided passphrase successfully, but
* passphrase did not unlock any keyslot associated with the token.
*
* @note ENOENT errno means no token (or subsequently assigned keyslot) was
* eligible to unlock device.
*
* @note ENOANO errno means that token is PIN protected and you should call
* @link crypt_activate_by_token_pin @endlink with PIN
*
* @note Negative EAGAIN errno means token handler requires additional hardware
* not present in the system.
*
* @note with @param token set to CRYPT_ANY_TOKEN libcryptsetup runs best effort loop
* to unlock device using any available token. It may happen that various token handlers
* return different error codes. At the end loop returns error codes in the following
* order (from the most significant to the least) any negative errno except those
* listed below, non negative token id (success), -ENOANO, -EAGAIN, -EPERM, -ENOENT.
*/
int crypt_activate_by_token(struct crypt_device *cd,
const char *name,
int token,
void *usrptr,
uint32_t flags);
/**
* Activate device or check key using a token with PIN.
*
* @param cd crypt device handle
* @param name name of device to create, if @e NULL only check token
* @param type restrict type of token, if @e NULL all types are allowed
* @param token requested token to check or CRYPT_ANY_TOKEN to check all
* @param pin passphrase (or PIN) to unlock token (may be binary data)
* @param pin_size size of @e pin
* @param usrptr provided identification in callback
* @param flags activation flags
*
* @return unlocked key slot number or negative errno otherwise.
*
* @note EPERM errno means token provided passphrase successfully, but
* passphrase did not unlock any keyslot associated with the token.
*
* @note ENOENT errno means no token (or subsequently assigned keyslot) was
* eligible to unlock device.
*
* @note ENOANO errno means that token is PIN protected and was either missing
* (NULL) or wrong.
*
* @note Negative EAGAIN errno means token handler requires additional hardware
* not present in the system.
*
* @note with @param token set to CRYPT_ANY_TOKEN libcryptsetup runs best effort loop
* to unlock device using any available token. It may happen that various token handlers
* return different error codes. At the end loop returns error codes in the following
* order (from the most significant to the least) any negative errno except those
* listed below, non negative token id (success), -ENOANO, -EAGAIN, -EPERM, -ENOENT.
*/
int crypt_activate_by_token_pin(struct crypt_device *cd,
const char *name,
const char *type,
int token,
const char *pin,
size_t pin_size,
void *usrptr,
uint32_t flags);
/** @} */
/**
@@ -2481,34 +2217,17 @@ int crypt_reencrypt_init_by_keyring(struct crypt_device *cd,
const char *cipher_mode,
const struct crypt_params_reencrypt *params);
/**
* Legacy data reencryption function.
*
* @param cd crypt device handle
* @param progress is a callback function reporting device \b size,
* current \b offset of reencryption and provided \b usrptr identification
*
* @return @e 0 on success or negative errno value otherwise.
*
* @deprecated Use @link crypt_reencrypt_run @endlink instead.
*/
int crypt_reencrypt(struct crypt_device *cd,
int (*progress)(uint64_t size, uint64_t offset, void *usrptr))
__attribute__((deprecated));
/**
* Run data reencryption.
*
* @param cd crypt device handle
* @param progress is a callback function reporting device \b size,
* @param progress is a callback funtion reporting device \b size,
* current \b offset of reencryption and provided \b usrptr identification
* @param usrptr progress specific data
*
* @return @e 0 on success or negative errno value otherwise.
*/
int crypt_reencrypt_run(struct crypt_device *cd,
int (*progress)(uint64_t size, uint64_t offset, void *usrptr),
void *usrptr);
int crypt_reencrypt(struct crypt_device *cd,
int (*progress)(uint64_t size, uint64_t offset, void *usrptr));
/**
* Reencryption status info
@@ -2532,49 +2251,6 @@ crypt_reencrypt_info crypt_reencrypt_status(struct crypt_device *cd,
struct crypt_params_reencrypt *params);
/** @} */
/**
* @defgroup crypt-memory Safe memory helpers functions
* @addtogroup crypt-memory
* @{
*/
/**
* Allocate safe memory (content is safely wiped on deallocation).
*
* @param size size of memory in bytes
*
* @return pointer to allocated memory or @e NULL.
*/
void *crypt_safe_alloc(size_t size);
/**
* Release safe memory, content is safely wiped.
* The pointer must be allocated with @link crypt_safe_alloc @endlink
*
* @param data pointer to memory to be deallocated
*/
void crypt_safe_free(void *data);
/**
* Reallocate safe memory (content is copied and safely wiped on deallocation).
*
* @param data pointer to memory to be deallocated
* @param size new size of memory in bytes
*
* @return pointer to allocated memory or @e NULL.
*/
void *crypt_safe_realloc(void *data, size_t size);
/**
* Safe clear memory area (compile should not compile this call out).
*
* @param data pointer to memory to be cleared
* @param size size of memory in bytes
*/
void crypt_safe_memzero(void *data, size_t size);
/** @} */
#ifdef __cplusplus
}
#endif

View File

@@ -12,9 +12,6 @@ CRYPTSETUP_2.0 {
crypt_set_label;
crypt_set_data_device;
crypt_set_compatibility;
crypt_get_compatibility;
crypt_memory_lock;
crypt_metadata_locking;
crypt_format;
@@ -27,7 +24,6 @@ CRYPTSETUP_2.0 {
crypt_resume_by_keyfile;
crypt_resume_by_keyfile_offset;
crypt_resume_by_keyfile_device_offset;
crypt_resume_by_volume_key;
crypt_free;
crypt_keyslot_add_by_passphrase;
@@ -59,7 +55,6 @@ CRYPTSETUP_2.0 {
crypt_activate_by_keyfile_offset;
crypt_activate_by_keyfile_device_offset;
crypt_activate_by_volume_key;
crypt_activate_by_signed_key;
crypt_activate_by_keyring;
crypt_deactivate;
crypt_deactivate_by_name;
@@ -123,24 +118,6 @@ CRYPTSETUP_2.0 {
crypt_reencrypt_init_by_keyring;
crypt_reencrypt;
crypt_reencrypt_status;
crypt_safe_alloc;
crypt_safe_realloc;
crypt_safe_free;
crypt_safe_memzero;
local:
*;
};
CRYPTSETUP_2.4 {
global:
crypt_reencrypt_run;
crypt_token_max;
crypt_header_is_detached;
crypt_logf;
crypt_activate_by_token_pin;
crypt_dump_json;
crypt_format;
crypt_token_external_disable;
crypt_token_external_path;
} CRYPTSETUP_2.0;

View File

@@ -1,67 +0,0 @@
/*
* Definitions of common constant and generic macros fo libcryptsetup
*
* Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2021 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef _LIBCRYPTSETUP_MACROS_H
#define _LIBCRYPTSETUP_MACROS_H
/* to silent gcc -Wcast-qual for const cast */
#define CONST_CAST(x) (x)(uintptr_t)
#define UNUSED(x) (void)(x)
#ifndef ARRAY_SIZE
# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
#endif
#define BITFIELD_SIZE(BF_PTR) (sizeof(*(BF_PTR)) * 8)
#define MOVE_REF(x, y) \
do { \
__typeof__(x) *_px = &(x), *_py = &(y); \
*_px = *_py; \
*_py = NULL; \
} while (0)
#define FREE_AND_NULL(x) do { free(x); x = NULL; } while (0)
#define AT_LEAST(a, b) ({ __typeof__(a) __at_least = (a); (__at_least >= (b))?__at_least:(b); })
#define SHIFT_4K 12
#define SECTOR_SHIFT 9
#define SECTOR_SIZE (1 << SECTOR_SHIFT)
#define MAX_SECTOR_SIZE 4096 /* min page size among all platforms */
#define ROUND_SECTOR(x) (((x) + SECTOR_SIZE - 1) / SECTOR_SIZE)
#define MISALIGNED(a, b) ((a) & ((b) - 1))
#define MISALIGNED_4K(a) MISALIGNED((a), 1 << SHIFT_4K)
#define MISALIGNED_512(a) MISALIGNED((a), 1 << SECTOR_SHIFT)
#define NOTPOW2(a) MISALIGNED((a), (a))
#define DEFAULT_DISK_ALIGNMENT 1048576 /* 1MiB */
#define DEFAULT_MEM_ALIGNMENT 4096
#define DM_UUID_LEN 129
#define DM_BY_ID_PREFIX "dm-uuid-"
#define DM_BY_ID_PREFIX_LEN 8
#define DM_UUID_PREFIX "CRYPT-"
#define DM_UUID_PREFIX_LEN 6
#endif /* _LIBCRYPTSETUP_MACROS_H */

View File

@@ -1,105 +0,0 @@
/*
* Helpers for defining versioned symbols
*
* Copyright (C) 2021 Red Hat, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef _LIBCRYPTSETUP_SYMVER_H
#define _LIBCRYPTSETUP_SYMVER_H
/*
* Note on usage:
*
* Do not use CRYPT_SYMBOL_EXPORT_NEW and CRYPT_SYMBOL_EXPORT_OLD on public
* symbols being exported only once. Linker will handle it automatically as
* always.
*
* It's supposed to be used only with symbols that are exported in at least
* two versions simultaneously as follows:
*
* - the latest version is marked with _NEW variant and oll other compatible
* symbols should be marked with _OLD variant
*
* Examples:
*
* - int crypt_func_X(unsigned *x, long y) gets introduced in CRYPTSETUP_2.4.
*
* No need to use any macro referenced here, just add proper version
* mapping in libcryptsetup.sym file.
*
* In later version CRYPTSETUP_2.5 symbol crypt_func_X has to fixed
* in incompatible way by adding new function parameter. The new version
* has to be added in mapping file libcryptsetup.sym as well.
*
* The definition of compatible function gets prefixed with following macro:
*
* CRYPT_SYMBOL_EXPORT_OLD(int, crypt_func_X, 2, 4,
* unsigned *x, long y)
* {
* function body
* }
*
* Whereas new version introduced in CRYPTSETUP_2.5 is defined as follows:
*
* CRYPT_SYMBOL_EXPORT_NEW(int, crypt_func_X, 2, 5,
* unsigned *x, long y, void *new_parameter)
* {
* function body
* }
*
* If in later version CRYPTSETUP_2.6 yet another version of crypt_func_X gets
* introduced it will be prefixed with CRYPT_SYMBOL_EXPORT_NEW(int, crypt_func_X, 2, 6...)
* macro and all previous versions CRYPTSETUP_2.4 and CRYPTSETUP_2.5 will be
* under CRYPT_SYMBOL_EXPORT_OLD(int, crypt_func_X, ...) macro
*/
#ifdef __has_attribute
# if __has_attribute(symver)
# define _CRYPT_SYMVER(_local_sym, _public_sym, _ver_str, _maj, _min) \
__attribute__((__symver__(#_public_sym _ver_str #_maj "." #_min)))
# endif
#endif
#if !defined(_CRYPT_SYMVER) && defined(__GNUC__)
# define _CRYPT_SYMVER(_local_sym, _public_sym, _ver_str, _maj, _min) \
asm(".symver " #_local_sym "," #_public_sym _ver_str #_maj "." #_min);
#endif
#define _CRYPT_FUNC(_public_sym, _prefix_str, _maj, _min, _ret, ...) \
_ret __##_public_sym##_v##_maj##_##_min(__VA_ARGS__); \
_CRYPT_SYMVER(__##_public_sym##_v##_maj##_##_min, _public_sym, _prefix_str "CRYPTSETUP_", _maj, _min) \
_ret __##_public_sym##_v##_maj##_##_min(__VA_ARGS__)
#ifdef _CRYPT_SYMVER
# define CRYPT_SYMBOL_EXPORT_OLD(_ret, _public_sym, _maj, _min, ...) \
_CRYPT_FUNC(_public_sym, "@", _maj, _min, _ret, __VA_ARGS__)
# define CRYPT_SYMBOL_EXPORT_NEW(_ret, _public_sym, _maj, _min, ...) \
_CRYPT_FUNC(_public_sym, "@@", _maj, _min, _ret, __VA_ARGS__)
#else /* no support for symbol versioning at all */
# define CRYPT_SYMBOL_EXPORT_OLD(_ret, _public_sym, _maj, _min, ...) \
static inline __attribute__((unused)) \
_ret __##_public_sym##_v##_maj##_##_min(__VA_ARGS__)
# define CRYPT_SYMBOL_EXPORT_NEW(_ret, _public_sym, _maj, _min, ...) \
_ret _public_sym(__VA_ARGS__)
#endif
#endif /* _LIBCRYPTSETUP_SYMVER_H */

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,8 @@
/*
* loop-AES compatible volume handling
*
* Copyright (C) 2011-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2011-2021 Milan Broz
* Copyright (C) 2011-2019 Red Hat, Inc. All rights reserved.
* Copyright (C) 2011-2019 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -81,7 +81,7 @@ static int hash_keys(struct crypt_device *cd,
const char *hash_name;
char tweak, *key_ptr;
unsigned int i;
int r = 0;
int r;
hash_name = hash_override ?: get_hash(key_len_output);
tweak = get_tweak(keys_count);
@@ -242,7 +242,7 @@ int LOOPAES_activate(struct crypt_device *cd,
if (r < 0 && !dm_flags(cd, DM_CRYPT, &dmc_flags) &&
(dmc_flags & req_flags) != req_flags) {
log_err(cd, _("Kernel does not support loop-AES compatible mapping."));
log_err(cd, _("Kernel doesn't support loop-AES compatible mapping."));
r = -ENOTSUP;
}

View File

@@ -1,8 +1,8 @@
/*
* loop-AES compatible volume handling
*
* Copyright (C) 2011-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2011-2021 Milan Broz
* Copyright (C) 2011-2019 Red Hat, Inc. All rights reserved.
* Copyright (C) 2011-2019 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -23,7 +23,7 @@
#define _LOOPAES_H
#include <stdint.h>
#include <stddef.h>
#include <unistd.h>
struct crypt_device;
struct volume_key;

View File

@@ -2,7 +2,7 @@
* AFsplitter - Anti forensic information splitter
*
* Copyright (C) 2004 Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2019 Red Hat, Inc. All rights reserved.
*
* AFsplitter diffuses information over a large stripe of data,
* therefore supporting secure data destruction.

View File

@@ -2,7 +2,7 @@
* AFsplitter - Anti forensic information splitter
*
* Copyright (C) 2004 Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2019 Red Hat, Inc. All rights reserved.
*
* AFsplitter diffuses information over a large stripe of data,
* therefore supporting secure data destruction.
@@ -26,9 +26,6 @@
#include <stddef.h>
struct crypt_device;
struct volume_key;
/*
* AF_split operates on src and produces information split data in
* dst. src is assumed to be of the length blocksize. The data stripe

View File

@@ -2,8 +2,8 @@
* LUKS - Linux Unified Key Setup
*
* Copyright (C) 2004-2006 Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2021 Milan Broz
* Copyright (C) 2009-2019 Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2019 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -22,6 +22,7 @@
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/stat.h>
#include "luks.h"
@@ -88,7 +89,7 @@ static int LUKS_endec_template(char *src, size_t srcLength,
r = device_block_adjust(ctx, crypt_metadata_device(ctx), DEV_OK,
sector, &dmd.size, &dmd.flags);
if (r < 0) {
log_err(ctx, _("Device %s does not exist or access denied."),
log_err(ctx, _("Device %s doesn't exist or access denied."),
device_path(crypt_metadata_device(ctx)));
return -EIO;
}
@@ -153,7 +154,7 @@ int LUKS_encrypt_to_storage(char *src, size_t srcLength,
return -EINVAL;
/* Encrypt buffer */
r = crypt_storage_init(&s, SECTOR_SIZE, cipher, cipher_mode, vk->key, vk->keylength, false);
r = crypt_storage_init(&s, SECTOR_SIZE, cipher, cipher_mode, vk->key, vk->keylength);
if (r)
log_dbg(ctx, "Userspace crypto wrapper cannot use %s-%s (%d).",
@@ -218,7 +219,7 @@ int LUKS_decrypt_from_storage(char *dst, size_t dstLength,
if (MISALIGNED_512(dstLength))
return -EINVAL;
r = crypt_storage_init(&s, SECTOR_SIZE, cipher, cipher_mode, vk->key, vk->keylength, false);
r = crypt_storage_init(&s, SECTOR_SIZE, cipher, cipher_mode, vk->key, vk->keylength);
if (r)
log_dbg(ctx, "Userspace crypto wrapper cannot use %s-%s (%d).",

View File

@@ -2,8 +2,8 @@
* LUKS - Linux Unified Key Setup
*
* Copyright (C) 2004-2006 Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2013-2021 Milan Broz
* Copyright (C) 2009-2019 Red Hat, Inc. All rights reserved.
* Copyright (C) 2013-2019 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -22,6 +22,8 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
@@ -258,7 +260,7 @@ int LUKS_hdr_backup(const char *backup_file, struct crypt_device *ctx)
r = 0;
out:
crypt_safe_memzero(&hdr, sizeof(hdr));
crypt_memzero(&hdr, sizeof(hdr));
crypt_safe_free(buffer);
return r;
}
@@ -282,7 +284,7 @@ int LUKS_hdr_restore(
buffer_size = LUKS_device_sectors(&hdr_file) << SECTOR_SHIFT;
if (r || buffer_size < LUKS_ALIGN_KEYSLOTS) {
log_err(ctx, _("Backup file does not contain valid LUKS header."));
log_err(ctx, _("Backup file doesn't contain valid LUKS header."));
r = -EINVAL;
goto out;
}
@@ -374,13 +376,8 @@ static int _keyslot_repair(struct luks_phdr *phdr, struct crypt_device *ctx)
log_err(ctx, _("Non standard key size, manual repair required."));
return -EINVAL;
}
/*
* cryptsetup 1.0 did not align keyslots to 4k, cannot repair this one
* Also we cannot trust possibly broken keyslots metadata here through LUKS_keyslots_offset().
* Expect first keyslot is aligned, if not, then manual repair is neccessary.
*/
if (phdr->keyblock[0].keyMaterialOffset < (LUKS_ALIGN_KEYSLOTS / SECTOR_SIZE)) {
/* cryptsetup 1.0 did not align to 4k, cannot repair this one */
if (LUKS_keyslots_offset(phdr) < (LUKS_ALIGN_KEYSLOTS / SECTOR_SIZE)) {
log_err(ctx, _("Non standard keyslots alignment, manual repair required."));
return -EINVAL;
}
@@ -390,8 +387,6 @@ static int _keyslot_repair(struct luks_phdr *phdr, struct crypt_device *ctx)
return -EINVAL;
vk = crypt_alloc_volume_key(phdr->keyBytes, NULL);
if (!vk)
return -ENOMEM;
log_verbose(ctx, _("Repairing keyslots."));
@@ -458,7 +453,7 @@ out:
if (r)
log_err(ctx, _("Repair failed."));
crypt_free_volume_key(vk);
crypt_safe_memzero(&temp_phdr, sizeof(temp_phdr));
crypt_memzero(&temp_phdr, sizeof(temp_phdr));
return r;
}
@@ -472,13 +467,12 @@ static int _check_and_convert_hdr(const char *device,
unsigned int i;
char luksMagic[] = LUKS_MAGIC;
hdr->version = be16_to_cpu(hdr->version);
if (memcmp(hdr->magic, luksMagic, LUKS_MAGIC_L)) { /* Check magic */
if(memcmp(hdr->magic, luksMagic, LUKS_MAGIC_L)) { /* Check magic */
log_dbg(ctx, "LUKS header not detected.");
if (require_luks_device)
log_err(ctx, _("Device %s is not a valid LUKS device."), device);
return -EINVAL;
} else if (hdr->version != 1) {
} else if((hdr->version = ntohs(hdr->version)) != 1) { /* Convert every uint16/32_t item from network byte order */
log_err(ctx, _("Unsupported LUKS version %d."), hdr->version);
return -EINVAL;
}
@@ -490,15 +484,15 @@ static int _check_and_convert_hdr(const char *device,
}
/* Header detected */
hdr->payloadOffset = be32_to_cpu(hdr->payloadOffset);
hdr->keyBytes = be32_to_cpu(hdr->keyBytes);
hdr->mkDigestIterations = be32_to_cpu(hdr->mkDigestIterations);
hdr->payloadOffset = ntohl(hdr->payloadOffset);
hdr->keyBytes = ntohl(hdr->keyBytes);
hdr->mkDigestIterations = ntohl(hdr->mkDigestIterations);
for (i = 0; i < LUKS_NUMKEYS; ++i) {
hdr->keyblock[i].active = be32_to_cpu(hdr->keyblock[i].active);
hdr->keyblock[i].passwordIterations = be32_to_cpu(hdr->keyblock[i].passwordIterations);
hdr->keyblock[i].keyMaterialOffset = be32_to_cpu(hdr->keyblock[i].keyMaterialOffset);
hdr->keyblock[i].stripes = be32_to_cpu(hdr->keyblock[i].stripes);
for(i = 0; i < LUKS_NUMKEYS; ++i) {
hdr->keyblock[i].active = ntohl(hdr->keyblock[i].active);
hdr->keyblock[i].passwordIterations = ntohl(hdr->keyblock[i].passwordIterations);
hdr->keyblock[i].keyMaterialOffset = ntohl(hdr->keyblock[i].keyMaterialOffset);
hdr->keyblock[i].stripes = ntohl(hdr->keyblock[i].stripes);
}
if (LUKS_check_keyslots(ctx, hdr))
@@ -650,15 +644,15 @@ int LUKS_write_phdr(struct luks_phdr *hdr,
memset(&convHdr._padding, 0, sizeof(convHdr._padding));
/* Convert every uint16/32_t item to network byte order */
convHdr.version = cpu_to_be16(hdr->version);
convHdr.payloadOffset = cpu_to_be32(hdr->payloadOffset);
convHdr.keyBytes = cpu_to_be32(hdr->keyBytes);
convHdr.mkDigestIterations = cpu_to_be32(hdr->mkDigestIterations);
convHdr.version = htons(hdr->version);
convHdr.payloadOffset = htonl(hdr->payloadOffset);
convHdr.keyBytes = htonl(hdr->keyBytes);
convHdr.mkDigestIterations = htonl(hdr->mkDigestIterations);
for(i = 0; i < LUKS_NUMKEYS; ++i) {
convHdr.keyblock[i].active = cpu_to_be32(hdr->keyblock[i].active);
convHdr.keyblock[i].passwordIterations = cpu_to_be32(hdr->keyblock[i].passwordIterations);
convHdr.keyblock[i].keyMaterialOffset = cpu_to_be32(hdr->keyblock[i].keyMaterialOffset);
convHdr.keyblock[i].stripes = cpu_to_be32(hdr->keyblock[i].stripes);
convHdr.keyblock[i].active = htonl(hdr->keyblock[i].active);
convHdr.keyblock[i].passwordIterations = htonl(hdr->keyblock[i].passwordIterations);
convHdr.keyblock[i].keyMaterialOffset = htonl(hdr->keyblock[i].keyMaterialOffset);
convHdr.keyblock[i].stripes = htonl(hdr->keyblock[i].stripes);
}
r = write_lseek_blockwise(devfd, device_block_size(ctx, device), device_alignment(device),
@@ -698,7 +692,7 @@ int LUKS_check_cipher(struct crypt_device *ctx, size_t keylength, const char *ci
r = LUKS_decrypt_from_storage(buf, sizeof(buf), cipher, cipher_mode, empty_key, 0, ctx);
crypt_free_volume_key(empty_key);
crypt_safe_memzero(buf, sizeof(buf));
crypt_memzero(buf, sizeof(buf));
return r;
}
@@ -793,15 +787,10 @@ int LUKS_generate_phdr(struct luks_phdr *header,
return r;
assert(pbkdf->iterations);
if (pbkdf->flags & CRYPT_PBKDF_NO_BENCHMARK && pbkdf->time_ms == 0)
PBKDF2_temp = LUKS_MKD_ITERATIONS_MIN;
else /* iterations per ms * LUKS_MKD_ITERATIONS_MS */
PBKDF2_temp = (double)pbkdf->iterations * LUKS_MKD_ITERATIONS_MS / pbkdf->time_ms;
PBKDF2_temp = (double)pbkdf->iterations * LUKS_MKD_ITERATIONS_MS / pbkdf->time_ms;
if (PBKDF2_temp > (double)UINT32_MAX)
return -EINVAL;
header->mkDigestIterations = AT_LEAST((uint32_t)PBKDF2_temp, LUKS_MKD_ITERATIONS_MIN);
assert(header->mkDigestIterations);
header->mkDigestIterations = at_least((uint32_t)PBKDF2_temp, LUKS_MKD_ITERATIONS_MIN);
r = crypt_pbkdf(CRYPT_KDF_PBKDF2, header->hashSpec, vk->key,vk->keylength,
header->mkDigestSalt, LUKS_SALTSIZE,
@@ -874,7 +863,7 @@ int LUKS_set_key(unsigned int keyIndex,
* Final iteration count is at least LUKS_SLOT_ITERATIONS_MIN
*/
hdr->keyblock[keyIndex].passwordIterations =
AT_LEAST(pbkdf->iterations, LUKS_SLOT_ITERATIONS_MIN);
at_least(pbkdf->iterations, LUKS_SLOT_ITERATIONS_MIN);
log_dbg(ctx, "Key slot %d use %" PRIu32 " password iterations.", keyIndex,
hdr->keyblock[keyIndex].passwordIterations);
@@ -962,12 +951,12 @@ static int LUKS_open_key(unsigned int keyIndex,
const char *password,
size_t passwordLen,
struct luks_phdr *hdr,
struct volume_key **vk,
struct volume_key *vk,
struct crypt_device *ctx)
{
crypt_keyslot_info ki = LUKS_keyslot_info(hdr, keyIndex);
struct volume_key *derived_key;
char *AfKey = NULL;
char *AfKey;
size_t AFEKSize;
int r;
@@ -981,13 +970,8 @@ static int LUKS_open_key(unsigned int keyIndex,
if (!derived_key)
return -ENOMEM;
*vk = crypt_alloc_volume_key(hdr->keyBytes, NULL);
if (!*vk) {
r = -ENOMEM;
goto out;
}
AFEKSize = AF_split_sectors(hdr->keyBytes, hdr->keyblock[keyIndex].stripes) * SECTOR_SIZE;
assert(vk->keylength == hdr->keyBytes);
AFEKSize = AF_split_sectors(vk->keylength, hdr->keyblock[keyIndex].stripes) * SECTOR_SIZE;
AfKey = crypt_safe_alloc(AFEKSize);
if (!AfKey) {
r = -ENOMEM;
@@ -998,10 +982,8 @@ static int LUKS_open_key(unsigned int keyIndex,
hdr->keyblock[keyIndex].passwordSalt, LUKS_SALTSIZE,
derived_key->key, hdr->keyBytes,
hdr->keyblock[keyIndex].passwordIterations, 0, 0);
if (r < 0) {
log_err(ctx, _("Cannot open keyslot (using hash %s)."), hdr->hashSpec);
if (r < 0)
goto out;
}
log_dbg(ctx, "Reading key slot %d area.", keyIndex);
r = LUKS_decrypt_from_storage(AfKey,
@@ -1013,20 +995,16 @@ static int LUKS_open_key(unsigned int keyIndex,
if (r < 0)
goto out;
r = AF_merge(ctx, AfKey, (*vk)->key, (*vk)->keylength, hdr->keyblock[keyIndex].stripes, hdr->hashSpec);
r = AF_merge(ctx, AfKey, vk->key, vk->keylength, hdr->keyblock[keyIndex].stripes, hdr->hashSpec);
if (r < 0)
goto out;
r = LUKS_verify_volume_key(hdr, *vk);
r = LUKS_verify_volume_key(hdr, vk);
/* Allow only empty passphrase with null cipher */
if (!r && crypt_is_cipher_null(hdr->cipherName) && passwordLen)
if (!r && !strcmp(hdr->cipherName, "cipher_null") && passwordLen)
r = -EPERM;
out:
if (r < 0) {
crypt_free_volume_key(*vk);
*vk = NULL;
}
crypt_safe_free(AfKey);
crypt_free_volume_key(derived_key);
return r;
@@ -1042,14 +1020,16 @@ int LUKS_open_key_with_hdr(int keyIndex,
unsigned int i, tried = 0;
int r;
*vk = crypt_alloc_volume_key(hdr->keyBytes, NULL);
if (keyIndex >= 0) {
r = LUKS_open_key(keyIndex, password, passwordLen, hdr, vk, ctx);
r = LUKS_open_key(keyIndex, password, passwordLen, hdr, *vk, ctx);
return (r < 0) ? r : keyIndex;
}
for (i = 0; i < LUKS_NUMKEYS; i++) {
r = LUKS_open_key(i, password, passwordLen, hdr, vk, ctx);
if (r == 0)
r = LUKS_open_key(i, password, passwordLen, hdr, *vk, ctx);
if(r == 0)
return i;
/* Do not retry for errors that are no -EPERM or -ENOENT,
@@ -1244,7 +1224,7 @@ int LUKS_wipe_header_areas(struct luks_phdr *hdr,
int LUKS_keyslot_pbkdf(struct luks_phdr *hdr, int keyslot, struct crypt_pbkdf_type *pbkdf)
{
if (LUKS_keyslot_info(hdr, keyslot) < CRYPT_SLOT_ACTIVE)
if (keyslot >= LUKS_NUMKEYS || keyslot < 0)
return -EINVAL;
pbkdf->type = CRYPT_KDF_PBKDF2;

View File

@@ -2,7 +2,7 @@
* LUKS - Linux Unified Key Setup
*
* Copyright (C) 2004-2006 Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2019 Red Hat, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License

View File

@@ -1,8 +1,8 @@
/*
* LUKS - Linux Unified Key Setup v2
*
* Copyright (C) 2015-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2021 Milan Broz
* Copyright (C) 2015-2019 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2019 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,8 +23,6 @@
#define _CRYPTSETUP_LUKS2_ONDISK_H
#include <stdbool.h>
#include <stdint.h>
#include <sys/types.h>
#include "libcryptsetup.h"
@@ -44,8 +42,6 @@
#define LUKS2_BUILTIN_TOKEN_PREFIX "luks2-"
#define LUKS2_BUILTIN_TOKEN_PREFIX_LEN 6
#define LUKS2_TOKEN_NAME_MAX 64
#define LUKS2_TOKEN_KEYRING LUKS2_BUILTIN_TOKEN_PREFIX "keyring"
#define LUKS2_DIGEST_MAX 8
@@ -63,10 +59,6 @@
#define LUKS2_REENCRYPT_MAX_HOTZONE_LENGTH 0x40000000
struct device;
struct luks2_reencrypt;
struct crypt_lock_handle;
struct crypt_dm_active_device;
struct luks_phdr; /* LUKS1 for conversion */
/*
* LUKS2 header on-disk.
@@ -102,6 +94,7 @@ struct luks2_hdr_disk {
/*
* LUKS2 header in-memory.
*/
typedef struct json_object json_object;
struct luks2_hdr {
size_t hdr_size;
uint64_t seqid;
@@ -112,7 +105,7 @@ struct luks2_hdr {
uint8_t salt1[LUKS2_SALT_L];
uint8_t salt2[LUKS2_SALT_L];
char uuid[LUKS2_UUID_L];
void *jobj;
json_object *jobj;
};
struct luks2_keyslot_params {
@@ -134,6 +127,77 @@ struct luks2_keyslot_params {
} area;
};
struct reenc_protection {
enum { REENC_PROTECTION_NONE = 0, /* none should be 0 always */
REENC_PROTECTION_CHECKSUM,
REENC_PROTECTION_JOURNAL,
REENC_PROTECTION_DATASHIFT } type;
union {
struct {
} none;
struct {
char hash[LUKS2_CHECKSUM_ALG_L]; // or include luks.h
struct crypt_hash *ch;
size_t hash_size;
/* buffer for checksums */
void *checksums;
size_t checksums_len;
} csum;
struct {
} ds;
} p;
};
struct luks2_reenc_context {
/* reencryption window attributes */
uint64_t offset;
uint64_t progress;
uint64_t length;
uint64_t data_shift;
size_t alignment;
uint64_t device_size;
bool online;
bool fixed_length;
crypt_reencrypt_direction_info direction;
crypt_reencrypt_mode_info mode;
char *device_name;
char *hotzone_name;
char *overlay_name;
uint32_t flags;
/* reencryption window persistence attributes */
struct reenc_protection rp;
int reenc_keyslot;
/* already running reencryption */
json_object *jobj_segs_hot;
json_object *jobj_segs_post;
/* backup segments */
json_object *jobj_segment_new;
int digest_new;
json_object *jobj_segment_old;
int digest_old;
json_object *jobj_segment_moved;
struct volume_key *vks;
void *reenc_buffer;
ssize_t read;
struct crypt_storage_wrapper *cw1;
struct crypt_storage_wrapper *cw2;
uint32_t wflags1;
uint32_t wflags2;
struct crypt_lock_handle *reenc_lock;
};
crypt_reencrypt_info LUKS2_reenc_status(struct luks2_hdr *hdr);
/*
* Supportable header sizes (hdr_disk + JSON area)
* Also used as offset for the 2nd header.
@@ -156,11 +220,13 @@ struct luks2_keyslot_params {
int LUKS2_hdr_version_unlocked(struct crypt_device *cd,
const char *backup_file);
int LUKS2_device_write_lock(struct crypt_device *cd,
struct luks2_hdr *hdr, struct device *device);
int LUKS2_hdr_read(struct crypt_device *cd, struct luks2_hdr *hdr, int repair);
int LUKS2_hdr_write(struct crypt_device *cd, struct luks2_hdr *hdr);
int LUKS2_hdr_write_force(struct crypt_device *cd, struct luks2_hdr *hdr);
int LUKS2_hdr_dump(struct crypt_device *cd, struct luks2_hdr *hdr);
int LUKS2_hdr_dump_json(struct crypt_device *cd, struct luks2_hdr *hdr, const char **json);
int LUKS2_hdr_uuid(struct crypt_device *cd,
struct luks2_hdr *hdr,
@@ -181,9 +247,9 @@ int LUKS2_hdr_restore(struct crypt_device *cd,
struct luks2_hdr *hdr,
const char *backup_file);
uint64_t LUKS2_hdr_and_areas_size(struct luks2_hdr *hdr);
uint64_t LUKS2_keyslots_size(struct luks2_hdr *hdr);
uint64_t LUKS2_metadata_size(struct luks2_hdr *hdr);
uint64_t LUKS2_hdr_and_areas_size(json_object *jobj);
uint64_t LUKS2_keyslots_size(json_object *jobj);
uint64_t LUKS2_metadata_size(json_object *jobj);
int LUKS2_keyslot_cipher_incompatible(struct crypt_device *cd, const char *cipher_spec);
@@ -212,11 +278,28 @@ int LUKS2_keyslot_store(struct crypt_device *cd,
const struct volume_key *vk,
const struct luks2_keyslot_params *params);
int LUKS2_keyslot_reencrypt_store(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot,
const void *buffer,
size_t buffer_length);
int LUKS2_keyslot_reencrypt_create(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot,
const struct crypt_params_reencrypt *params);
int reenc_keyslot_update(struct crypt_device *cd,
const struct luks2_reenc_context *rh);
int LUKS2_keyslot_wipe(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot,
int wipe_area_only);
int LUKS2_keyslot_dump(struct crypt_device *cd,
int keyslot);
crypt_keyslot_priority LUKS2_keyslot_priority_get(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot);
@@ -227,11 +310,6 @@ int LUKS2_keyslot_priority_set(struct crypt_device *cd,
crypt_keyslot_priority priority,
int commit);
int LUKS2_keyslot_swap(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot,
int keyslot2);
/*
* Generic LUKS2 token
*/
@@ -252,12 +330,6 @@ int LUKS2_token_is_assigned(struct crypt_device *cd,
int keyslot,
int token);
int LUKS2_token_assignment_copy(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot_from,
int keyslot_to,
int commit);
int LUKS2_token_create(struct crypt_device *cd,
struct luks2_hdr *hdr,
int token,
@@ -269,25 +341,89 @@ crypt_token_info LUKS2_token_status(struct crypt_device *cd,
int token,
const char **type);
int LUKS2_token_open_and_activate(struct crypt_device *cd,
int LUKS2_builtin_token_get(struct crypt_device *cd,
struct luks2_hdr *hdr,
int token,
const char *name,
const char *type,
const char *pin,
size_t pin_size,
uint32_t flags,
void *usrptr);
void *params);
int LUKS2_token_keyring_get(struct crypt_device *cd,
int LUKS2_builtin_token_create(struct crypt_device *cd,
struct luks2_hdr *hdr,
int token,
struct crypt_token_params_luks2_keyring *keyring_params);
const char *type,
const void *params,
int commit);
int LUKS2_token_keyring_json(char *buffer, size_t buffer_size,
const struct crypt_token_params_luks2_keyring *keyring_params);
int LUKS2_token_open_and_activate(struct crypt_device *cd,
struct luks2_hdr *hdr,
int token,
const char *name,
uint32_t flags,
void *usrptr);
void crypt_token_unload_external_all(struct crypt_device *cd);
int LUKS2_token_open_and_activate_any(struct crypt_device *cd,
struct luks2_hdr *hdr,
const char *name,
uint32_t flags);
int LUKS2_tokens_count(struct luks2_hdr *hdr);
/*
* Generic LUKS2 segment
*/
uint64_t json_segment_get_offset(json_object *jobj_segment, unsigned blockwise);
const char *json_segment_type(json_object *jobj_segment);
uint64_t json_segment_get_iv_offset(json_object *jobj_segment);
uint64_t json_segment_get_size(json_object *jobj_segment, unsigned blockwise);
const char *json_segment_get_cipher(json_object *jobj_segment);
int json_segment_get_sector_size(json_object *jobj_segment);
bool json_segment_is_backup(json_object *jobj_segment);
json_object *json_segments_get_segment(json_object *jobj_segments, int segment);
unsigned json_segments_count(json_object *jobj_segments);
void json_segment_remove_flag(json_object *jobj_segment, const char *flag);
uint64_t json_segments_get_minimal_offset(json_object *jobj_segments, unsigned blockwise);
json_object *json_segment_create_linear(uint64_t offset, const uint64_t *length, unsigned reencryption);
json_object *json_segment_create_crypt(uint64_t offset, uint64_t iv_offset, const uint64_t *length, const char *cipher, uint32_t sector_size, unsigned reencryption);
int json_segments_segment_in_reencrypt(json_object *jobj_segments);
int LUKS2_segments_count(struct luks2_hdr *hdr);
int LUKS2_segment_first_unused_id(struct luks2_hdr *hdr);
int LUKS2_segment_set_flag(json_object *jobj_segment, const char *flag);
json_object *LUKS2_get_segment_by_flag(struct luks2_hdr *hdr, const char *flag);
int LUKS2_get_segment_id_by_flag(struct luks2_hdr *hdr, const char *flag);
int LUKS2_segments_set(struct crypt_device *cd,
struct luks2_hdr *hdr,
json_object *jobj_segments,
int commit);
uint64_t LUKS2_segment_offset(struct luks2_hdr *hdr,
int segment,
unsigned blockwise);
uint64_t LUKS2_segment_size(struct luks2_hdr *hdr,
int segment,
unsigned blockwise);
int LUKS2_segment_is_type(struct luks2_hdr *hdr,
int segment,
const char *type);
int LUKS2_segment_by_type(struct luks2_hdr *hdr,
const char *type);
int LUKS2_last_segment_by_type(struct luks2_hdr *hdr,
const char *type);
int LUKS2_get_default_segment(struct luks2_hdr *hdr);
int LUKS2_reencrypt_digest_new(struct luks2_hdr *hdr);
int LUKS2_reencrypt_digest_old(struct luks2_hdr *hdr);
int LUKS2_reencrypt_data_offset(struct luks2_hdr *hdr, bool blockwise);
/*
* Generic LUKS2 digest
@@ -296,16 +432,29 @@ int LUKS2_digest_any_matching(struct crypt_device *cd,
struct luks2_hdr *hdr,
const struct volume_key *vk);
int LUKS2_digest_by_segment(struct luks2_hdr *hdr, int segment);
int LUKS2_digest_verify_by_digest(struct crypt_device *cd,
struct luks2_hdr *hdr,
int digest,
const struct volume_key *vk);
int LUKS2_digest_verify_by_segment(struct crypt_device *cd,
struct luks2_hdr *hdr,
int segment,
const struct volume_key *vk);
void LUKS2_digests_erase_unused(struct crypt_device *cd,
struct luks2_hdr *hdr);
int LUKS2_digest_verify(struct crypt_device *cd,
struct luks2_hdr *hdr,
const struct volume_key *vk,
int keyslot);
int LUKS2_digest_dump(struct crypt_device *cd,
int digest);
int LUKS2_digest_assign(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot,
@@ -322,8 +471,6 @@ int LUKS2_digest_segment_assign(struct crypt_device *cd,
int LUKS2_digest_by_keyslot(struct luks2_hdr *hdr, int keyslot);
int LUKS2_digest_by_segment(struct luks2_hdr *hdr, int segment);
int LUKS2_digest_create(struct crypt_device *cd,
const char *type,
struct luks2_hdr *hdr,
@@ -343,12 +490,20 @@ int LUKS2_activate_multi(struct crypt_device *cd,
uint64_t device_size,
uint32_t flags);
struct crypt_dm_active_device;
int LUKS2_deactivate(struct crypt_device *cd,
const char *name,
struct luks2_hdr *hdr,
struct crypt_dm_active_device *dmd,
uint32_t flags);
int LUKS2_reload(struct crypt_device *cd,
const char *name,
struct volume_key *vks,
uint64_t device_size,
uint32_t flags);
int LUKS2_generate_hdr(
struct crypt_device *cd,
struct luks2_hdr *hdr,
@@ -368,7 +523,7 @@ int LUKS2_check_metadata_area_size(uint64_t metadata_size);
int LUKS2_check_keyslots_area_size(uint64_t keyslots_size);
int LUKS2_wipe_header_areas(struct crypt_device *cd,
struct luks2_hdr *hdr, bool detached_header);
struct luks2_hdr *hdr);
uint64_t LUKS2_get_data_offset(struct luks2_hdr *hdr);
int LUKS2_get_data_size(struct luks2_hdr *hdr, uint64_t *size, bool *dynamic);
@@ -380,14 +535,19 @@ int LUKS2_keyslot_params_default(struct crypt_device *cd, struct luks2_hdr *hdr,
int LUKS2_get_volume_key_size(struct luks2_hdr *hdr, int segment);
int LUKS2_get_keyslot_stored_key_size(struct luks2_hdr *hdr, int keyslot);
const char *LUKS2_get_keyslot_cipher(struct luks2_hdr *hdr, int keyslot, size_t *key_size);
int LUKS2_keyslot_find_empty(struct crypt_device *cd, struct luks2_hdr *hdr, size_t keylength);
int LUKS2_keyslot_find_empty(struct luks2_hdr *hdr);
int LUKS2_keyslot_active_count(struct luks2_hdr *hdr, int segment);
int LUKS2_keyslot_for_segment(struct luks2_hdr *hdr, int keyslot, int segment);
int LUKS2_find_keyslot(struct luks2_hdr *hdr, const char *type);
crypt_keyslot_info LUKS2_keyslot_info(struct luks2_hdr *hdr, int keyslot);
int LUKS2_keyslot_area(struct luks2_hdr *hdr,
int keyslot,
uint64_t *offset,
uint64_t *length);
int LUKS2_keyslot_pbkdf(struct luks2_hdr *hdr, int keyslot, struct crypt_pbkdf_type *pbkdf);
int LUKS2_set_keyslots_size(struct crypt_device *cd,
struct luks2_hdr *hdr,
uint64_t data_offset);
/*
* Permanent activation flags stored in header
@@ -410,6 +570,7 @@ int LUKS2_volume_key_load_in_keyring_by_keyslot(struct crypt_device *cd,
int LUKS2_volume_key_load_in_keyring_by_digest(struct crypt_device *cd,
struct luks2_hdr *hdr, struct volume_key *vk, int digest);
struct luks_phdr;
int LUKS2_luks1_to_luks2(struct crypt_device *cd,
struct luks_phdr *hdr1,
struct luks2_hdr *hdr2);
@@ -428,29 +589,20 @@ int LUKS2_reencrypt_locked_recovery_by_passphrase(struct crypt_device *cd,
uint32_t flags,
struct volume_key **vks);
void LUKS2_reencrypt_free(struct crypt_device *cd,
struct luks2_reencrypt *rh);
void LUKS2_reenc_context_free(struct crypt_device *cd, struct luks2_reenc_context *rh);
crypt_reencrypt_info LUKS2_reencrypt_status(struct luks2_hdr *hdr);
int LUKS2_assembly_multisegment_dmd(struct crypt_device *cd,
struct luks2_hdr *hdr,
struct volume_key *vks,
json_object *jobj_segments,
struct crypt_dm_active_device *dmd);
crypt_reencrypt_info LUKS2_reencrypt_get_params(struct luks2_hdr *hdr,
crypt_reencrypt_info LUKS2_reencrypt_status(struct crypt_device *cd,
struct crypt_params_reencrypt *params);
int LUKS2_reencrypt_lock(struct crypt_device *cd,
struct crypt_lock_handle **reencrypt_lock);
int crypt_reencrypt_lock(struct crypt_device *cd, const char *uuid, struct crypt_lock_handle **reencrypt_lock);
void crypt_reencrypt_unlock(struct crypt_device *cd, struct crypt_lock_handle *reencrypt_lock);
int LUKS2_reencrypt_lock_by_dm_uuid(struct crypt_device *cd,
const char *dm_uuid,
struct crypt_lock_handle **reencrypt_lock);
void LUKS2_reencrypt_unlock(struct crypt_device *cd,
struct crypt_lock_handle *reencrypt_lock);
int LUKS2_reencrypt_check_device_size(struct crypt_device *cd,
struct luks2_hdr *hdr,
uint64_t check_size,
uint64_t *dev_size,
bool activation,
bool dynamic);
int luks2_check_device_size(struct crypt_device *cd, struct luks2_hdr *hdr, uint64_t check_size, uint64_t *dev_size, bool activation, bool dynamic);
#endif

View File

@@ -1,8 +1,8 @@
/*
* LUKS - Linux Unified Key Setup v2, digest handling
*
* Copyright (C) 2015-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2021 Milan Broz
* Copyright (C) 2015-2019 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2019 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 @@ static const digest_handler *digest_handlers[LUKS2_DIGEST_MAX] = {
NULL
};
static const digest_handler *LUKS2_digest_handler_type(const char *type)
static const digest_handler *LUKS2_digest_handler_type(struct crypt_device *cd, const char *type)
{
int i;
@@ -57,10 +57,10 @@ static const digest_handler *LUKS2_digest_handler(struct crypt_device *cd, int d
if (!json_object_object_get_ex(jobj1, "type", &jobj2))
return NULL;
return LUKS2_digest_handler_type(json_object_get_string(jobj2));
return LUKS2_digest_handler_type(cd, json_object_get_string(jobj2));
}
static int LUKS2_digest_find_free(struct luks2_hdr *hdr)
static int LUKS2_digest_find_free(struct crypt_device *cd, struct luks2_hdr *hdr)
{
int digest = 0;
@@ -78,11 +78,11 @@ int LUKS2_digest_create(struct crypt_device *cd,
int digest;
const digest_handler *dh;
dh = LUKS2_digest_handler_type(type);
dh = LUKS2_digest_handler_type(cd, type);
if (!dh)
return -EINVAL;
digest = LUKS2_digest_find_free(hdr);
digest = LUKS2_digest_find_free(cd, hdr);
if (digest < 0)
return -EINVAL;
@@ -111,7 +111,7 @@ int LUKS2_digest_by_keyslot(struct luks2_hdr *hdr, int keyslot)
}
int LUKS2_digest_verify_by_digest(struct crypt_device *cd,
struct luks2_hdr *hdr __attribute__((unused)),
struct luks2_hdr *hdr,
int digest,
const struct volume_key *vk)
{
@@ -219,9 +219,7 @@ static int assign_one_digest(struct crypt_device *cd, struct luks2_hdr *hdr,
if (!jobj_digest_keyslots)
return -EINVAL;
if (snprintf(num, sizeof(num), "%d", keyslot) < 0)
return -EINVAL;
snprintf(num, sizeof(num), "%d", keyslot);
if (assign) {
jobj1 = LUKS2_array_jobj(jobj_digest_keyslots, num);
if (!jobj1)
@@ -256,11 +254,12 @@ int LUKS2_digest_assign(struct crypt_device *cd, struct luks2_hdr *hdr,
if (r < 0)
return r;
// FIXME: do not write header in nothing changed
return commit ? LUKS2_hdr_write(cd, hdr) : 0;
}
static int assign_all_segments(struct crypt_device *cd __attribute__((unused)),
struct luks2_hdr *hdr, int digest, int assign)
static int assign_all_segments(struct crypt_device *cd, struct luks2_hdr *hdr,
int digest, int assign)
{
json_object *jobj1, *jobj_digest, *jobj_digest_segments;
@@ -305,9 +304,7 @@ static int assign_one_segment(struct crypt_device *cd, struct luks2_hdr *hdr,
if (!jobj_digest_segments)
return -EINVAL;
if (snprintf(num, sizeof(num), "%d", segment) < 0)
return -EINVAL;
snprintf(num, sizeof(num), "%d", segment);
if (assign) {
jobj1 = LUKS2_array_jobj(jobj_digest_segments, num);
if (!jobj1)
@@ -352,6 +349,7 @@ int LUKS2_digest_segment_assign(struct crypt_device *cd, struct luks2_hdr *hdr,
if (r < 0)
return r;
// FIXME: do not write header in nothing changed
return commit ? LUKS2_hdr_write(cd, hdr) : 0;
}
@@ -443,7 +441,7 @@ int LUKS2_volume_key_load_in_keyring_by_keyslot(struct crypt_device *cd,
}
int LUKS2_volume_key_load_in_keyring_by_digest(struct crypt_device *cd,
struct luks2_hdr *hdr __attribute__((unused)), struct volume_key *vk, int digest)
struct luks2_hdr *hdr, struct volume_key *vk, int digest)
{
char *desc = get_key_description_by_digest(cd, digest);
int r;

View File

@@ -1,8 +1,8 @@
/*
* LUKS - Linux Unified Key Setup v2, PBKDF2 digest handler (LUKS1 compatible)
*
* Copyright (C) 2015-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2021 Milan Broz
* Copyright (C) 2015-2019 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2019 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License

View File

@@ -1,8 +1,8 @@
/*
* LUKS - Linux Unified Key Setup v2
*
* Copyright (C) 2015-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2021 Milan Broz
* Copyright (C) 2015-2019 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2019 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -175,13 +175,13 @@ static void hdr_to_disk(struct luks2_hdr *hdr,
hdr_disk->hdr_offset = cpu_to_be64(offset);
hdr_disk->seqid = cpu_to_be64(hdr->seqid);
memcpy(hdr_disk->label, hdr->label, MIN(strlen(hdr->label), LUKS2_LABEL_L));
strncpy(hdr_disk->label, hdr->label, LUKS2_LABEL_L);
hdr_disk->label[LUKS2_LABEL_L - 1] = '\0';
memcpy(hdr_disk->subsystem, hdr->subsystem, MIN(strlen(hdr->subsystem), LUKS2_LABEL_L));
strncpy(hdr_disk->subsystem, hdr->subsystem, LUKS2_LABEL_L);
hdr_disk->subsystem[LUKS2_LABEL_L - 1] = '\0';
memcpy(hdr_disk->checksum_alg, hdr->checksum_alg, MIN(strlen(hdr->checksum_alg), LUKS2_CHECKSUM_ALG_L));
strncpy(hdr_disk->checksum_alg, hdr->checksum_alg, LUKS2_CHECKSUM_ALG_L);
hdr_disk->checksum_alg[LUKS2_CHECKSUM_ALG_L - 1] = '\0';
memcpy(hdr_disk->uuid, hdr->uuid, MIN(strlen(hdr->uuid), LUKS2_UUID_L));
strncpy(hdr_disk->uuid, hdr->uuid, LUKS2_UUID_L);
hdr_disk->uuid[LUKS2_UUID_L - 1] = '\0';
memcpy(hdr_disk->salt, secondary ? hdr->salt2 : hdr->salt1, LUKS2_SALT_L);
@@ -210,7 +210,7 @@ static int hdr_disk_sanity_check_pre(struct crypt_device *cd,
}
if (secondary && (offset != be64_to_cpu(hdr->hdr_size))) {
log_dbg(cd, "LUKS2 offset 0x%04x in secondary header does not match size 0x%04x.",
log_dbg(cd, "LUKS2 offset 0x%04x in secondary header doesn't match size 0x%04x.",
(unsigned)offset, (unsigned)be64_to_cpu(hdr->hdr_size));
return -EINVAL;
}
@@ -301,6 +301,8 @@ static int hdr_write_disk(struct crypt_device *cd,
log_dbg(cd, "Trying to write LUKS2 header (%zu bytes) at offset %" PRIu64 ".",
hdr->hdr_size, offset);
/* FIXME: read-only device silent fail? */
devfd = device_open_locked(cd, device, O_RDWR);
if (devfd < 0)
return devfd == -1 ? -EINVAL : devfd;
@@ -383,7 +385,7 @@ int LUKS2_device_write_lock(struct crypt_device *cd, struct luks2_hdr *hdr, stru
}
/* run sequence id check only on first write lock (r == 1) and w/o LUKS2 reencryption in-progress */
if (r == 1 && !crypt_get_luks2_reencrypt(cd)) {
if (r == 1 && !crypt_get_reenc_context(cd)) {
log_dbg(cd, "Checking context sequence id matches value stored on disk.");
if (LUKS2_check_sequence_id(cd, hdr, device)) {
device_write_unlock(cd, device);
@@ -411,7 +413,7 @@ int LUKS2_disk_hdr_write(struct crypt_device *cd, struct luks2_hdr *hdr, struct
return -EINVAL;
}
r = device_check_size(cd, crypt_metadata_device(cd), LUKS2_hdr_and_areas_size(hdr), 1);
r = device_check_size(cd, crypt_metadata_device(cd), LUKS2_hdr_and_areas_size(hdr->jobj), 1);
if (r)
return r;
@@ -667,9 +669,9 @@ int LUKS2_disk_hdr_read(struct crypt_device *cd, struct luks2_hdr *hdr,
/* check header with keyslots to fit the device */
if (state_hdr1 == HDR_OK)
hdr_size = LUKS2_hdr_and_areas_size_jobj(jobj_hdr1);
hdr_size = LUKS2_hdr_and_areas_size(jobj_hdr1);
else if (state_hdr2 == HDR_OK)
hdr_size = LUKS2_hdr_and_areas_size_jobj(jobj_hdr2);
hdr_size = LUKS2_hdr_and_areas_size(jobj_hdr2);
else {
r = (state_hdr1 == HDR_FAIL_IO && state_hdr2 == HDR_FAIL_IO) ? -EIO : -EINVAL;
goto err;
@@ -786,11 +788,14 @@ int LUKS2_hdr_version_unlocked(struct crypt_device *cd, const char *backup_file)
flags |= O_DIRECT;
devfd = open(device_path(device), flags);
if (devfd != -1 && (read_lseek_blockwise(devfd, device_block_size(cd, device),
if (devfd < 0)
goto err;
if ((read_lseek_blockwise(devfd, device_block_size(cd, device),
device_alignment(device), &hdr, sizeof(hdr), 0) == sizeof(hdr)) &&
!memcmp(hdr.magic, LUKS2_MAGIC_1ST, LUKS2_MAGIC_L))
r = (int)be16_to_cpu(hdr.version);
err:
if (devfd != -1)
close(devfd);

View File

@@ -1,8 +1,8 @@
/*
* LUKS - Linux Unified Key Setup v2
*
* Copyright (C) 2015-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2021 Milan Broz
* Copyright (C) 2015-2019 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2019 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -23,6 +23,7 @@
#define _CRYPTSETUP_LUKS2_INTERNAL_H
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <json-c/json.h>
@@ -30,6 +31,8 @@
#include "base64.h"
#include "luks2.h"
#define UNUSED(x) (void)(x)
/* override useless forward slash escape when supported by json-c */
#ifndef JSON_C_TO_STRING_NOSLASHESCAPE
#define JSON_C_TO_STRING_NOSLASHESCAPE 0
@@ -42,8 +45,6 @@ int LUKS2_disk_hdr_read(struct crypt_device *cd, struct luks2_hdr *hdr,
struct device *device, int do_recovery, int do_blkprobe);
int LUKS2_disk_hdr_write(struct crypt_device *cd, struct luks2_hdr *hdr,
struct device *device, bool seqid_check);
int LUKS2_device_write_lock(struct crypt_device *cd,
struct luks2_hdr *hdr, struct device *device);
/*
* JSON struct access helpers
@@ -92,8 +93,8 @@ void LUKS2_keyslots_repair(struct crypt_device *cd, json_object *jobj_hdr);
/*
* JSON array helpers
*/
json_object *LUKS2_array_jobj(json_object *array, const char *num);
json_object *LUKS2_array_remove(json_object *array, const char *num);
struct json_object *LUKS2_array_jobj(struct json_object *array, const char *num);
struct json_object *LUKS2_array_remove(struct json_object *array, const char *num);
/*
* Plugins API
@@ -162,53 +163,28 @@ typedef struct {
digest_dump_func dump;
} digest_handler;
int keyring_open(struct crypt_device *cd,
int token,
char **buffer,
size_t *buffer_len,
void *usrptr);
void keyring_dump(struct crypt_device *cd, const char *json);
int keyring_validate(struct crypt_device *cd, const char *json);
struct crypt_token_handler_v2 {
const char *name;
crypt_token_open_func open;
crypt_token_buffer_free_func buffer_free;
crypt_token_validate_func validate;
crypt_token_dump_func dump;
/* here ends v1. Do not touch anything above */
crypt_token_open_pin_func open_pin;
crypt_token_version_func version;
void *dlhandle;
};
/*
* Initial sequence of structure members in union 'u' must be always
* identical. Version 4 must fully contain version 3 which must
* subsequently fully contain version 2, etc.
*
* See C standard, section 6.5.2.3, item 5.
/**
* LUKS2 token handlers (internal use only)
*/
struct crypt_token_handler_internal {
uint32_t version;
union {
crypt_token_handler v1; /* deprecated public structure */
struct crypt_token_handler_v2 v2; /* internal helper v2 structure */
} u;
};
typedef int (*builtin_token_get_func) (json_object *jobj_token, void *params);
typedef int (*builtin_token_set_func) (json_object **jobj_token, const void *params);
typedef struct {
/* internal only section used by builtin tokens */
builtin_token_get_func get;
builtin_token_set_func set;
/* public token handler */
const crypt_token_handler *h;
} token_handler;
int token_keyring_set(json_object **, const void *);
int token_keyring_get(json_object *, void *);
int LUKS2_find_area_gap(struct crypt_device *cd, struct luks2_hdr *hdr,
size_t keylength, uint64_t *area_offset, uint64_t *area_length);
int LUKS2_find_area_max_gap(struct crypt_device *cd, struct luks2_hdr *hdr,
uint64_t *area_offset, uint64_t *area_length);
uint64_t LUKS2_hdr_and_areas_size_jobj(json_object *jobj);
int LUKS2_check_cipher(struct crypt_device *cd,
size_t keylength,
const char *cipher,
@@ -225,119 +201,4 @@ static inline const char *crypt_reencrypt_mode_to_str(crypt_reencrypt_mode_info
return "<unknown>";
}
/*
* Generic LUKS2 keyslot
*/
int LUKS2_keyslot_reencrypt_store(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot,
const void *buffer,
size_t buffer_length);
int LUKS2_keyslot_reencrypt_create(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot,
const struct crypt_params_reencrypt *params);
int LUKS2_keyslot_dump(struct crypt_device *cd,
int keyslot);
/* JSON helpers */
uint64_t json_segment_get_offset(json_object *jobj_segment, unsigned blockwise);
const char *json_segment_type(json_object *jobj_segment);
uint64_t json_segment_get_iv_offset(json_object *jobj_segment);
uint64_t json_segment_get_size(json_object *jobj_segment, unsigned blockwise);
const char *json_segment_get_cipher(json_object *jobj_segment);
int json_segment_get_sector_size(json_object *jobj_segment);
bool json_segment_is_backup(json_object *jobj_segment);
json_object *json_segments_get_segment(json_object *jobj_segments, int segment);
unsigned json_segments_count(json_object *jobj_segments);
void json_segment_remove_flag(json_object *jobj_segment, const char *flag);
uint64_t json_segments_get_minimal_offset(json_object *jobj_segments, unsigned blockwise);
json_object *json_segment_create_linear(uint64_t offset, const uint64_t *length, unsigned reencryption);
json_object *json_segment_create_crypt(uint64_t offset, uint64_t iv_offset, const uint64_t *length, const char *cipher, uint32_t sector_size, unsigned reencryption);
int json_segments_segment_in_reencrypt(json_object *jobj_segments);
int LUKS2_assembly_multisegment_dmd(struct crypt_device *cd,
struct luks2_hdr *hdr,
struct volume_key *vks,
json_object *jobj_segments,
struct crypt_dm_active_device *dmd);
/*
* Generic LUKS2 segment
*/
int LUKS2_segments_count(struct luks2_hdr *hdr);
int LUKS2_segment_first_unused_id(struct luks2_hdr *hdr);
int LUKS2_segment_set_flag(json_object *jobj_segment, const char *flag);
json_object *LUKS2_get_segment_by_flag(struct luks2_hdr *hdr, const char *flag);
int LUKS2_get_segment_id_by_flag(struct luks2_hdr *hdr, const char *flag);
int LUKS2_segments_set(struct crypt_device *cd,
struct luks2_hdr *hdr,
json_object *jobj_segments,
int commit);
uint64_t LUKS2_segment_offset(struct luks2_hdr *hdr,
int segment,
unsigned blockwise);
uint64_t LUKS2_segment_size(struct luks2_hdr *hdr,
int segment,
unsigned blockwise);
int LUKS2_segment_is_type(struct luks2_hdr *hdr,
int segment,
const char *type);
int LUKS2_segment_by_type(struct luks2_hdr *hdr,
const char *type);
int LUKS2_last_segment_by_type(struct luks2_hdr *hdr,
const char *type);
int LUKS2_get_default_segment(struct luks2_hdr *hdr);
int LUKS2_reencrypt_digest_new(struct luks2_hdr *hdr);
int LUKS2_reencrypt_digest_old(struct luks2_hdr *hdr);
int LUKS2_reencrypt_data_offset(struct luks2_hdr *hdr, bool blockwise);
/*
* Generic LUKS2 digest
*/
int LUKS2_digest_verify_by_digest(struct crypt_device *cd,
struct luks2_hdr *hdr,
int digest,
const struct volume_key *vk);
void LUKS2_digests_erase_unused(struct crypt_device *cd,
struct luks2_hdr *hdr);
int LUKS2_digest_dump(struct crypt_device *cd,
int digest);
/*
* Generic LUKS2 token
*/
int LUKS2_tokens_count(struct luks2_hdr *hdr);
/*
* LUKS2 generic
*/
int LUKS2_reload(struct crypt_device *cd,
const char *name,
struct volume_key *vks,
uint64_t device_size,
uint32_t flags);
int LUKS2_keyslot_for_segment(struct luks2_hdr *hdr, int keyslot, int segment);
int LUKS2_find_keyslot(struct luks2_hdr *hdr, const char *type);
int LUKS2_set_keyslots_size(struct crypt_device *cd,
struct luks2_hdr *hdr,
uint64_t data_offset);
#endif

View File

@@ -1,8 +1,8 @@
/*
* LUKS - Linux Unified Key Setup v2, LUKS2 header format code
*
* Copyright (C) 2015-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2021 Milan Broz
* Copyright (C) 2015-2019 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2019 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -30,7 +30,7 @@ struct area {
static size_t get_area_size(size_t keylength)
{
/* for now it is AF_split_sectors */
//FIXME: calculate this properly, for now it is AF_split_sectors
return size_round_up(keylength * 4000, 4096);
}
@@ -41,7 +41,7 @@ static size_t get_min_offset(struct luks2_hdr *hdr)
static size_t get_max_offset(struct luks2_hdr *hdr)
{
return LUKS2_hdr_and_areas_size(hdr);
return LUKS2_hdr_and_areas_size(hdr->jobj);
}
int LUKS2_find_area_max_gap(struct crypt_device *cd, struct luks2_hdr *hdr,
@@ -177,11 +177,8 @@ int LUKS2_find_area_gap(struct crypt_device *cd, struct luks2_hdr *hdr,
log_dbg(cd, "Found area %zu -> %zu", offset, length + offset);
if (area_offset)
*area_offset = offset;
if (area_length)
*area_length = length;
*area_offset = offset;
*area_length = length;
return 0;
}
@@ -219,7 +216,7 @@ int LUKS2_generate_hdr(
struct json_object *jobj_segment, *jobj_integrity, *jobj_keyslots, *jobj_segments, *jobj_config;
char cipher[128];
uuid_t partitionUuid;
int r, digest;
int digest;
uint64_t mdev_size;
if (!metadata_size)
@@ -247,8 +244,7 @@ int LUKS2_generate_hdr(
/* Decrease keyslots_size due to metadata device being too small */
if (!device_size(crypt_metadata_device(cd), &mdev_size) &&
((keyslots_size + get_min_offset(hdr)) > mdev_size) &&
device_fallocate(crypt_metadata_device(cd), keyslots_size + get_min_offset(hdr)) &&
(get_min_offset(hdr) <= mdev_size))
device_fallocate(crypt_metadata_device(cd), keyslots_size + get_min_offset(hdr)))
keyslots_size = mdev_size - get_min_offset(hdr);
}
@@ -293,11 +289,9 @@ int LUKS2_generate_hdr(
uuid_unparse(partitionUuid, hdr->uuid);
if (*cipherMode != '\0')
r = snprintf(cipher, sizeof(cipher), "%s-%s", cipherName, cipherMode);
snprintf(cipher, sizeof(cipher), "%s-%s", cipherName, cipherMode);
else
r = snprintf(cipher, sizeof(cipher), "%s", cipherName);
if (r < 0 || (size_t)r >= sizeof(cipher))
return -EINVAL;
snprintf(cipher, sizeof(cipher), "%s", cipherName);
hdr->jobj = json_object_new_object();
@@ -343,7 +337,7 @@ err:
}
int LUKS2_wipe_header_areas(struct crypt_device *cd,
struct luks2_hdr *hdr, bool detached_header)
struct luks2_hdr *hdr)
{
int r;
uint64_t offset, length;
@@ -358,7 +352,7 @@ int LUKS2_wipe_header_areas(struct crypt_device *cd,
return -EINVAL;
/* On detached header wipe at least the first 4k */
if (detached_header) {
if (length == 0) {
length = 4096;
wipe_block = 4096;
}
@@ -374,7 +368,7 @@ int LUKS2_wipe_header_areas(struct crypt_device *cd,
/* Wipe keyslot area */
wipe_block = 1024 * 1024;
offset = get_min_offset(hdr);
length = LUKS2_keyslots_size(hdr);
length = LUKS2_keyslots_size(hdr->jobj);
log_dbg(cd, "Wiping keyslots area (0x%06" PRIx64 " - 0x%06" PRIx64") with random data.",
offset, length + offset);
@@ -383,7 +377,8 @@ int LUKS2_wipe_header_areas(struct crypt_device *cd,
offset, length, wipe_block, NULL, NULL);
}
int LUKS2_set_keyslots_size(struct crypt_device *cd __attribute__((unused)),
/* FIXME: what if user wanted to keep original keyslots size? */
int LUKS2_set_keyslots_size(struct crypt_device *cd,
struct luks2_hdr *hdr,
uint64_t data_offset)
{

View File

@@ -1,9 +1,9 @@
/*
* LUKS - Linux Unified Key Setup v2
*
* Copyright (C) 2015-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2021 Milan Broz
* Copyright (C) 2015-2021 Ondrej Kozina
* Copyright (C) 2015-2019 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2019 Milan Broz
* Copyright (C) 2015-2019 Ondrej Kozina
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -45,11 +45,11 @@ void hexprint_base64(struct crypt_device *cd, json_object *jobj,
&buf, &buf_len))
return;
for (i = 0; i < buf_len; i++) {
if (i && !(i % 16))
log_std(cd, "\n\t%s", line_sep);
for (i = 0; i < buf_len / 2; i++)
log_std(cd, "%02hhx%s", buf[i], sep);
log_std(cd, "\n\t%s", line_sep);
for (i = buf_len / 2; i < buf_len; i++)
log_std(cd, "%02hhx%s", buf[i], sep);
}
log_std(cd, "\n");
free(buf);
}
@@ -403,8 +403,7 @@ static json_bool validate_intervals(struct crypt_device *cd,
return 1;
}
static int LUKS2_keyslot_validate(struct crypt_device *cd, json_object *hdr_jobj __attribute__((unused)),
json_object *hdr_keyslot, const char *key)
static int LUKS2_keyslot_validate(struct crypt_device *cd, json_object *hdr_jobj, json_object *hdr_keyslot, const char *key)
{
json_object *jobj_key_size;
@@ -460,12 +459,12 @@ static int hdr_validate_json_size(struct crypt_device *cd, json_object *hdr_jobj
json_size = (uint64_t)strlen(json);
if (hdr_json_size != json_area_size) {
log_dbg(cd, "JSON area size does not match value in binary header.");
log_dbg(cd, "JSON area size doesn't match value in binary header.");
return 1;
}
if (json_size > json_area_size) {
log_dbg(cd, "JSON does not fit in the designated area.");
log_dbg(cd, "JSON doesn't fit in the designated area.");
return 1;
}
@@ -517,7 +516,7 @@ static int hdr_validate_tokens(struct crypt_device *cd, json_object *hdr_jobj)
static int hdr_validate_crypt_segment(struct crypt_device *cd,
json_object *jobj, const char *key, json_object *jobj_digests,
uint64_t offset __attribute__((unused)), uint64_t size)
uint64_t offset, uint64_t size)
{
json_object *jobj_ivoffset, *jobj_sector_size, *jobj_integrity;
uint32_t sector_size;
@@ -595,9 +594,9 @@ static bool validate_segment_intervals(struct crypt_device *cd,
static int hdr_validate_segments(struct crypt_device *cd, json_object *hdr_jobj)
{
json_object *jobj_segments, *jobj_digests, *jobj_offset, *jobj_size, *jobj_type, *jobj_flags, *jobj;
struct interval *intervals;
uint64_t offset, size;
int i, r, count, first_backup = -1;
struct interval *intervals = NULL;
if (!json_object_object_get_ex(hdr_jobj, "segments", &jobj_segments)) {
log_dbg(cd, "Missing segments section.");
@@ -677,18 +676,10 @@ static int hdr_validate_segments(struct crypt_device *cd, json_object *hdr_jobj)
return 1;
}
/* avoid needlessly large allocation when first backup segment is invalid */
if (first_backup >= count) {
log_dbg(cd, "Gap between last regular segment and backup segment at key %d.", first_backup);
return 1;
}
if (first_backup < 0)
first_backup = count;
if ((size_t)first_backup < SIZE_MAX / sizeof(*intervals))
intervals = malloc(first_backup * sizeof(*intervals));
intervals = malloc(first_backup * sizeof(*intervals));
if (!intervals) {
log_dbg(cd, "Not enough memory.");
return 1;
@@ -721,7 +712,7 @@ static int hdr_validate_segments(struct crypt_device *cd, json_object *hdr_jobj)
return 0;
}
static uint64_t LUKS2_metadata_size_jobj(json_object *jobj)
uint64_t LUKS2_metadata_size(json_object *jobj)
{
json_object *jobj1, *jobj2;
uint64_t json_size;
@@ -733,11 +724,6 @@ static uint64_t LUKS2_metadata_size_jobj(json_object *jobj)
return json_size + LUKS2_HDR_BIN_LEN;
}
uint64_t LUKS2_metadata_size(struct luks2_hdr *hdr)
{
return LUKS2_metadata_size_jobj(hdr->jobj);
}
static int hdr_validate_areas(struct crypt_device *cd, json_object *hdr_jobj)
{
struct interval *intervals;
@@ -753,7 +739,7 @@ static int hdr_validate_areas(struct crypt_device *cd, json_object *hdr_jobj)
return 1;
/* config is already validated */
metadata_size = LUKS2_metadata_size_jobj(hdr_jobj);
metadata_size = LUKS2_metadata_size(hdr_jobj);
length = json_object_object_length(jobj_keyslots);
@@ -799,7 +785,7 @@ static int hdr_validate_areas(struct crypt_device *cd, json_object *hdr_jobj)
return 1;
}
ret = validate_intervals(cd, length, intervals, metadata_size, LUKS2_hdr_and_areas_size_jobj(hdr_jobj)) ? 0 : 1;
ret = validate_intervals(cd, length, intervals, metadata_size, LUKS2_hdr_and_areas_size(hdr_jobj)) ? 0 : 1;
free(intervals);
@@ -984,16 +970,13 @@ int LUKS2_hdr_read(struct crypt_device *cd, struct luks2_hdr *hdr, int repair)
return r;
}
static int hdr_cleanup_and_validate(struct crypt_device *cd, struct luks2_hdr *hdr)
{
LUKS2_digests_erase_unused(cd, hdr);
return LUKS2_hdr_validate(cd, hdr->jobj, hdr->hdr_size - LUKS2_HDR_BIN_LEN);
}
int LUKS2_hdr_write_force(struct crypt_device *cd, struct luks2_hdr *hdr)
{
if (hdr_cleanup_and_validate(cd, hdr))
/* NOTE: is called before LUKS2 validation routines */
/* erase unused digests (no assigned keyslot or segment) */
LUKS2_digests_erase_unused(cd, hdr);
if (LUKS2_hdr_validate(cd, hdr->jobj, hdr->hdr_size - LUKS2_HDR_BIN_LEN))
return -EINVAL;
return LUKS2_disk_hdr_write(cd, hdr, crypt_metadata_device(cd), false);
@@ -1001,7 +984,11 @@ int LUKS2_hdr_write_force(struct crypt_device *cd, struct luks2_hdr *hdr)
int LUKS2_hdr_write(struct crypt_device *cd, struct luks2_hdr *hdr)
{
if (hdr_cleanup_and_validate(cd, hdr))
/* NOTE: is called before LUKS2 validation routines */
/* erase unused digests (no assigned keyslot or segment) */
LUKS2_digests_erase_unused(cd, hdr);
if (LUKS2_hdr_validate(cd, hdr->jobj, hdr->hdr_size - LUKS2_HDR_BIN_LEN))
return -EINVAL;
return LUKS2_disk_hdr_write(cd, hdr, crypt_metadata_device(cd), true);
@@ -1047,7 +1034,7 @@ void LUKS2_hdr_free(struct crypt_device *cd, struct luks2_hdr *hdr)
log_dbg(cd, "LUKS2 header still in use");
}
static uint64_t LUKS2_keyslots_size_jobj(json_object *jobj)
uint64_t LUKS2_keyslots_size(json_object *jobj)
{
json_object *jobj1, *jobj2;
uint64_t keyslots_size;
@@ -1059,19 +1046,9 @@ static uint64_t LUKS2_keyslots_size_jobj(json_object *jobj)
return keyslots_size;
}
uint64_t LUKS2_keyslots_size(struct luks2_hdr *hdr)
uint64_t LUKS2_hdr_and_areas_size(json_object *jobj)
{
return LUKS2_keyslots_size_jobj(hdr->jobj);
}
uint64_t LUKS2_hdr_and_areas_size_jobj(json_object *jobj)
{
return 2 * LUKS2_metadata_size_jobj(jobj) + LUKS2_keyslots_size_jobj(jobj);
}
uint64_t LUKS2_hdr_and_areas_size(struct luks2_hdr *hdr)
{
return LUKS2_hdr_and_areas_size_jobj(hdr->jobj);
return 2 * LUKS2_metadata_size(jobj) + LUKS2_keyslots_size(jobj);
}
int LUKS2_hdr_backup(struct crypt_device *cd, struct luks2_hdr *hdr,
@@ -1083,7 +1060,7 @@ int LUKS2_hdr_backup(struct crypt_device *cd, struct luks2_hdr *hdr,
ssize_t ret, buffer_size;
char *buffer = NULL;
hdr_size = LUKS2_hdr_and_areas_size(hdr);
hdr_size = LUKS2_hdr_and_areas_size(hdr->jobj);
buffer_size = size_round_up(hdr_size, crypt_getpagesize());
buffer = crypt_safe_alloc(buffer_size);
@@ -1182,7 +1159,7 @@ int LUKS2_hdr_restore(struct crypt_device *cd, struct luks2_hdr *hdr,
device_free(cd, backup_device);
if (r < 0) {
log_err(cd, _("Backup file does not contain valid LUKS header."));
log_err(cd, _("Backup file doesn't contain valid LUKS header."));
goto out;
}
@@ -1194,7 +1171,7 @@ int LUKS2_hdr_restore(struct crypt_device *cd, struct luks2_hdr *hdr,
goto out;
}
buffer_size = LUKS2_hdr_and_areas_size(&hdr_file);
buffer_size = LUKS2_hdr_and_areas_size(hdr_file.jobj);
buffer = crypt_safe_alloc(buffer_size);
if (!buffer) {
r = -ENOMEM;
@@ -1234,7 +1211,7 @@ int LUKS2_hdr_restore(struct crypt_device *cd, struct luks2_hdr *hdr,
goto out;
}
/* FIXME: what could go wrong? Erase if we're fine with consequences */
if (buffer_size != (ssize_t) LUKS2_hdr_and_areas_size(&tmp_hdr)) {
if (buffer_size != (ssize_t) LUKS2_hdr_and_areas_size(tmp_hdr.jobj)) {
log_err(cd, _("Binary header with keyslot areas size differ on device and backup, restore failed."));
r = -EINVAL;
goto out;
@@ -1293,8 +1270,8 @@ out:
LUKS2_hdr_free(cd, hdr);
LUKS2_hdr_free(cd, &hdr_file);
LUKS2_hdr_free(cd, &tmp_hdr);
crypt_safe_memzero(&hdr_file, sizeof(hdr_file));
crypt_safe_memzero(&tmp_hdr, sizeof(tmp_hdr));
crypt_memzero(&hdr_file, sizeof(hdr_file));
crypt_memzero(&tmp_hdr, sizeof(tmp_hdr));
crypt_safe_free(buffer);
device_sync(cd, device);
@@ -1313,8 +1290,6 @@ static const struct {
{ CRYPT_ACTIVATE_SAME_CPU_CRYPT, "same-cpu-crypt" },
{ CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS, "submit-from-crypt-cpus" },
{ CRYPT_ACTIVATE_NO_JOURNAL, "no-journal" },
{ CRYPT_ACTIVATE_NO_READ_WORKQUEUE, "no-read-workqueue" },
{ CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE, "no-write-workqueue" },
{ 0, NULL }
};
@@ -1636,7 +1611,7 @@ static void hdr_dump_tokens(struct crypt_device *cd, json_object *hdr_jobj)
json_object_object_get_ex(val, "keyslots", &jobj2);
for (i = 0; i < (int) json_object_array_length(jobj2); i++) {
jobj3 = json_object_array_get_idx(jobj2, i);
log_std(cd, "\tKeyslot: %s\n", json_object_get_string(jobj3));
log_std(cd, "\tKeyslot: %s\n", json_object_get_string(jobj3));
}
}
}
@@ -1730,8 +1705,8 @@ int LUKS2_hdr_dump(struct crypt_device *cd, struct luks2_hdr *hdr)
log_std(cd, "LUKS header information\n");
log_std(cd, "Version: \t%u\n", hdr->version);
log_std(cd, "Epoch: \t%" PRIu64 "\n", hdr->seqid);
log_std(cd, "Metadata area: \t%" PRIu64 " [bytes]\n", LUKS2_metadata_size(hdr));
log_std(cd, "Keyslots area: \t%" PRIu64 " [bytes]\n", LUKS2_keyslots_size(hdr));
log_std(cd, "Metadata area: \t%" PRIu64 " [bytes]\n", LUKS2_metadata_size(hdr->jobj));
log_std(cd, "Keyslots area: \t%" PRIu64 " [bytes]\n", LUKS2_keyslots_size(hdr->jobj));
log_std(cd, "UUID: \t%s\n", *hdr->uuid ? hdr->uuid : "(no UUID)");
log_std(cd, "Label: \t%s\n", *hdr->label ? hdr->label : "(no label)");
log_std(cd, "Subsystem: \t%s\n", *hdr->subsystem ? hdr->subsystem : "(no subsystem)");
@@ -1745,24 +1720,6 @@ int LUKS2_hdr_dump(struct crypt_device *cd, struct luks2_hdr *hdr)
return 0;
}
int LUKS2_hdr_dump_json(struct crypt_device *cd, struct luks2_hdr *hdr, const char **json)
{
const char *json_buf;
json_buf = json_object_to_json_string_ext(hdr->jobj,
JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_NOSLASHESCAPE);
if (!json_buf)
return -EINVAL;
if (json)
*json = json_buf;
else
crypt_log(cd, CRYPT_LOG_NORMAL, json_buf);
return 0;
}
int LUKS2_get_data_size(struct luks2_hdr *hdr, uint64_t *size, bool *dynamic)
{
int sector_size;
@@ -1808,7 +1765,7 @@ uint64_t LUKS2_get_data_offset(struct luks2_hdr *hdr)
crypt_reencrypt_info ri;
json_object *jobj;
ri = LUKS2_reencrypt_status(hdr);
ri = LUKS2_reenc_status(hdr);
if (ri == CRYPT_REENCRYPT_CLEAN || ri == CRYPT_REENCRYPT_CRASH) {
jobj = LUKS2_get_segment_by_flag(hdr, "backup-final");
if (jobj)
@@ -1836,7 +1793,7 @@ const char *LUKS2_get_cipher(struct luks2_hdr *hdr, int segment)
return json_segment_get_cipher(jobj_segment) ?: "null";
}
crypt_reencrypt_info LUKS2_reencrypt_status(struct luks2_hdr *hdr)
crypt_reencrypt_info LUKS2_reenc_status(struct luks2_hdr *hdr)
{
uint32_t reqs;
@@ -2200,12 +2157,7 @@ int LUKS2_activate(struct crypt_device *cd,
return -EINVAL;
}
if (dmd.flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) {
log_err(cd, _("Discard/TRIM is not supported."));
return -EINVAL;
}
r = INTEGRITY_create_dmd_device(cd, NULL, NULL, NULL, NULL, &dmdi, dmd.flags, 0);
r = INTEGRITY_create_dmd_device(cd, NULL, NULL, NULL, NULL, &dmdi, dmd.flags);
if (r)
return r;
@@ -2253,21 +2205,26 @@ int LUKS2_deactivate(struct crypt_device *cd, const char *name, struct luks2_hdr
struct dm_target *tgt;
crypt_status_info ci;
struct crypt_dm_active_device dmdc;
char **dep, deps_uuid_prefix[40], *deps[MAX_DM_DEPS+1] = { 0 };
char **dep, uuid[37], deps_uuid_prefix[40], *deps[MAX_DM_DEPS+1] = { 0 };
const char *namei = NULL;
struct crypt_lock_handle *reencrypt_lock = NULL;
if (!dmd || !dmd->uuid || strncmp(CRYPT_LUKS2, dmd->uuid, sizeof(CRYPT_LUKS2)-1))
return -EINVAL;
/* uuid mismatch with metadata (if available) */
if (hdr && crypt_uuid_cmp(dmd->uuid, hdr->uuid))
if (!dmd || !dmd->uuid)
return -EINVAL;
r = snprintf(deps_uuid_prefix, sizeof(deps_uuid_prefix), CRYPT_SUBDEV "-%.32s", dmd->uuid + 6);
if (r < 0 || (size_t)r != (sizeof(deps_uuid_prefix) - 1))
return -EINVAL;
r = snprintf(uuid, sizeof(uuid), "%.8s-%.4s-%.4s-%.4s-%.12s",
dmd->uuid + 6, dmd->uuid + 14, dmd->uuid + 18, dmd->uuid + 22, dmd->uuid + 26);
if (r < 0 || (size_t)r != (sizeof(uuid) - 1))
return -EINVAL;
/* uuid mismatch with metadata (if available) */
if (hdr && strcmp(hdr->uuid, uuid))
return -EINVAL;
tgt = &dmd->segment;
/* TODO: We have LUKS2 dependencies now */
@@ -2279,7 +2236,7 @@ int LUKS2_deactivate(struct crypt_device *cd, const char *name, struct luks2_hdr
goto out;
if (contains_reencryption_helper(deps)) {
r = LUKS2_reencrypt_lock_by_dm_uuid(cd, dmd->uuid, &reencrypt_lock);
r = crypt_reencrypt_lock(cd, uuid, &reencrypt_lock);
if (r) {
if (r == -EBUSY)
log_err(cd, _("Reencryption in-progress. Cannot deactivate device."));
@@ -2358,7 +2315,7 @@ int LUKS2_deactivate(struct crypt_device *cd, const char *name, struct luks2_hdr
}
out:
LUKS2_reencrypt_unlock(cd, reencrypt_lock);
crypt_reencrypt_unlock(cd, reencrypt_lock);
dep = deps;
while (*dep)
free(*dep++);
@@ -2388,9 +2345,9 @@ int LUKS2_unmet_requirements(struct crypt_device *cd, struct luks2_hdr *hdr, uin
reqs &= ~reqs_mask;
if (reqs_reencrypt(reqs) && !quiet)
log_err(cd, _("Operation incompatible with device marked for legacy reencryption. Aborting."));
log_err(cd, _("Offline reencryption in progress. Aborting."));
if (reqs_reencrypt_online(reqs) && !quiet)
log_err(cd, _("Operation incompatible with device marked for LUKS2 reencryption. Aborting."));
log_err(cd, _("Online reencryption in progress. Aborting."));
/* any remaining unmasked requirement fails the check */
return reqs ? -EINVAL : 0;
@@ -2443,7 +2400,7 @@ int json_object_object_add_by_uint(json_object *jobj, unsigned key, json_object
#endif
}
/* jobj_dst must contain pointer initialized to NULL (see json-c json_object_deep_copy API) */
/* jobj_dst must contain pointer initialised to NULL (see json-c json_object_deep_copy API) */
int json_object_copy(json_object *jobj_src, json_object **jobj_dst)
{
if (!jobj_src || !jobj_dst || *jobj_dst)

View File

@@ -1,8 +1,8 @@
/*
* LUKS - Linux Unified Key Setup v2, keyslot handling
*
* Copyright (C) 2015-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2021 Milan Broz
* Copyright (C) 2015-2019 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2019 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -27,12 +27,14 @@ extern const keyslot_handler reenc_keyslot;
static const keyslot_handler *keyslot_handlers[LUKS2_KEYSLOTS_MAX] = {
&luks2_keyslot,
#if USE_LUKS2_REENCRYPTION
&reenc_keyslot,
#endif
NULL
};
static const keyslot_handler
*LUKS2_keyslot_handler_type(struct crypt_device *cd __attribute__((unused)), const char *type)
*LUKS2_keyslot_handler_type(struct crypt_device *cd, const char *type)
{
int i;
@@ -65,39 +67,33 @@ static const keyslot_handler
return LUKS2_keyslot_handler_type(cd, json_object_get_string(jobj2));
}
int LUKS2_keyslot_find_empty(struct crypt_device *cd, struct luks2_hdr *hdr, size_t keylength)
int LUKS2_keyslot_find_empty(struct luks2_hdr *hdr)
{
int i;
for (i = 0; i < LUKS2_KEYSLOTS_MAX; i++)
if (!LUKS2_get_keyslot_jobj(hdr, i))
break;
return i;
if (i == LUKS2_KEYSLOTS_MAX)
return -EINVAL;
/* Check also there is a space for the key in keyslots area */
if (keylength && LUKS2_find_area_gap(cd, hdr, keylength, NULL, NULL) < 0)
return -ENOSPC;
return i;
return -EINVAL;
}
/* Check if a keyslot is assigned to specific segment */
static int _keyslot_for_segment(struct luks2_hdr *hdr, int keyslot, int segment)
{
int keyslot_digest, count = 0;
unsigned s;
int keyslot_digest, segment_digest, s, count = 0;
keyslot_digest = LUKS2_digest_by_keyslot(hdr, keyslot);
if (keyslot_digest < 0)
return keyslot_digest;
if (segment >= 0)
return keyslot_digest == LUKS2_digest_by_segment(hdr, segment);
for (s = 0; s < json_segments_count(LUKS2_get_segments_jobj(hdr)); s++) {
if (keyslot_digest == LUKS2_digest_by_segment(hdr, s))
if (segment >= 0) {
segment_digest = LUKS2_digest_by_segment(hdr, segment);
return segment_digest == keyslot_digest;
}
for (s = 0; s < 3; s++) {
segment_digest = LUKS2_digest_by_segment(hdr, s);
if (segment_digest == keyslot_digest)
count++;
}
@@ -155,7 +151,7 @@ int LUKS2_keyslot_cipher_incompatible(struct crypt_device *cd, const char *ciphe
{
char cipher[MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN];
if (!cipher_spec || crypt_is_cipher_null(cipher_spec))
if (!cipher_spec || !strcmp(cipher_spec, "null") || !strcmp(cipher_spec, "cipher_null"))
return 1;
if (crypt_parse_name_and_mode(cipher_spec, cipher, NULL, cipher_mode) < 0)
@@ -316,16 +312,28 @@ int LUKS2_keyslot_area(struct luks2_hdr *hdr,
return 0;
}
static int _open_and_verify(struct crypt_device *cd,
static int LUKS2_open_and_verify_by_digest(struct crypt_device *cd,
struct luks2_hdr *hdr,
const keyslot_handler *h,
int keyslot,
int digest,
const char *password,
size_t password_len,
struct volume_key **vk)
{
int r, key_size = LUKS2_get_keyslot_stored_key_size(hdr, keyslot);
const keyslot_handler *h;
int key_size, r;
if (!(h = LUKS2_keyslot_handler(cd, keyslot)))
return -ENOENT;
r = _keyslot_for_digest(hdr, keyslot, digest);
if (r) {
if (r == -ENOENT)
log_dbg(cd, "Keyslot %d unusable for digest %d.", keyslot, digest);
return r;
}
key_size = LUKS2_get_keyslot_stored_key_size(hdr, keyslot);
if (key_size < 0)
return -EINVAL;
@@ -344,41 +352,9 @@ static int _open_and_verify(struct crypt_device *cd,
*vk = NULL;
}
crypt_volume_key_set_id(*vk, r);
return r < 0 ? r : keyslot;
}
static int LUKS2_open_and_verify_by_digest(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot,
int digest,
const char *password,
size_t password_len,
struct volume_key **vk)
{
const keyslot_handler *h;
int r;
if (!(h = LUKS2_keyslot_handler(cd, keyslot)))
return -ENOENT;
r = h->validate(cd, LUKS2_get_keyslot_jobj(hdr, keyslot));
if (r) {
log_dbg(cd, "Keyslot %d validation failed.", keyslot);
return r;
}
r = _keyslot_for_digest(hdr, keyslot, digest);
if (r) {
if (r == -ENOENT)
log_dbg(cd, "Keyslot %d unusable for digest %d.", keyslot, digest);
return r;
}
return _open_and_verify(cd, hdr, h, keyslot, password, password_len, vk);
}
static int LUKS2_open_and_verify(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot,
@@ -388,7 +364,7 @@ static int LUKS2_open_and_verify(struct crypt_device *cd,
struct volume_key **vk)
{
const keyslot_handler *h;
int r;
int key_size, r;
if (!(h = LUKS2_keyslot_handler(cd, keyslot)))
return -ENOENT;
@@ -406,7 +382,29 @@ static int LUKS2_open_and_verify(struct crypt_device *cd,
return r;
}
return _open_and_verify(cd, hdr, h, keyslot, password, password_len, vk);
key_size = LUKS2_get_volume_key_size(hdr, segment);
if (key_size < 0)
key_size = LUKS2_get_keyslot_stored_key_size(hdr, keyslot);
if (key_size < 0)
return -EINVAL;
*vk = crypt_alloc_volume_key(key_size, NULL);
if (!*vk)
return -ENOMEM;
r = h->open(cd, keyslot, password, password_len, (*vk)->key, (*vk)->keylength);
if (r < 0)
log_dbg(cd, "Keyslot %d (%s) open failed with %d.", keyslot, h->name, r);
else
r = LUKS2_digest_verify(cd, hdr, *vk, keyslot);
if (r < 0) {
crypt_free_volume_key(*vk);
*vk = NULL;
} else
crypt_volume_key_set_id(*vk, r);
return r < 0 ? r : keyslot;
}
static int LUKS2_keyslot_open_priority_digest(struct crypt_device *cd,
@@ -524,7 +522,7 @@ int LUKS2_keyslot_open_all_segments(struct crypt_device *cd,
size_t password_len,
struct volume_key **vks)
{
struct volume_key *vk = NULL;
struct volume_key *vk;
int digest_old, digest_new, r = -EINVAL;
struct luks2_hdr *hdr = crypt_get_hdr(cd, CRYPT_LUKS2);
@@ -534,6 +532,7 @@ int LUKS2_keyslot_open_all_segments(struct crypt_device *cd,
r = LUKS2_keyslot_open_by_digest(cd, hdr, keyslot_old, digest_old, password, password_len, &vk);
if (r < 0)
goto out;
crypt_volume_key_set_id(vk, digest_old);
crypt_volume_key_add_next(vks, vk);
}
@@ -543,6 +542,7 @@ int LUKS2_keyslot_open_all_segments(struct crypt_device *cd,
r = LUKS2_keyslot_open_by_digest(cd, hdr, keyslot_new, digest_new, password, password_len, &vk);
if (r < 0)
goto out;
crypt_volume_key_set_id(vk, digest_new);
crypt_volume_key_add_next(vks, vk);
}
out:
@@ -552,7 +552,7 @@ out:
if (r == -ENOMEM)
log_err(cd, _("Not enough available memory to open a keyslot."));
else if (r != -EPERM && r != -ENOENT)
else if (r != -EPERM)
log_err(cd, _("Keyslot open failed."));
}
return r;
@@ -589,7 +589,7 @@ int LUKS2_keyslot_open(struct crypt_device *cd,
if (r < 0) {
if (r == -ENOMEM)
log_err(cd, _("Not enough available memory to open a keyslot."));
else if (r != -EPERM && r != -ENOENT)
else if (r != -EPERM)
log_err(cd, _("Keyslot open failed."));
}
@@ -607,6 +607,7 @@ int LUKS2_keyslot_reencrypt_create(struct crypt_device *cd,
if (keyslot == CRYPT_ANY_SLOT)
return -EINVAL;
/* FIXME: find keyslot by type */
h = LUKS2_keyslot_handler_type(cd, "reencrypt");
if (!h)
return -EINVAL;
@@ -775,7 +776,7 @@ int LUKS2_keyslot_dump(struct crypt_device *cd, int keyslot)
return h->dump(cd, keyslot);
}
crypt_keyslot_priority LUKS2_keyslot_priority_get(struct crypt_device *cd __attribute__((unused)),
crypt_keyslot_priority LUKS2_keyslot_priority_get(struct crypt_device *cd,
struct luks2_hdr *hdr, int keyslot)
{
json_object *jobj_keyslot, *jobj_priority;
@@ -811,7 +812,7 @@ int placeholder_keyslot_alloc(struct crypt_device *cd,
int keyslot,
uint64_t area_offset,
uint64_t area_length,
size_t volume_key_len __attribute__((unused)))
size_t volume_key_len)
{
struct luks2_hdr *hdr;
json_object *jobj_keyslots, *jobj_keyslot, *jobj_area;
@@ -941,40 +942,3 @@ int LUKS2_find_keyslot(struct luks2_hdr *hdr, const char *type)
return -ENOENT;
}
/* assumes valid header, it does not move references in tokens/digests etc! */
int LUKS2_keyslot_swap(struct crypt_device *cd, struct luks2_hdr *hdr,
int keyslot, int keyslot2)
{
json_object *jobj_keyslots, *jobj_keyslot, *jobj_keyslot2;
int r;
if (!json_object_object_get_ex(hdr->jobj, "keyslots", &jobj_keyslots))
return -EINVAL;
jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot);
if (!jobj_keyslot)
return -EINVAL;
jobj_keyslot2 = LUKS2_get_keyslot_jobj(hdr, keyslot2);
if (!jobj_keyslot2)
return -EINVAL;
/* This transfer owner of object, no need for json_object_put */
json_object_get(jobj_keyslot);
json_object_get(jobj_keyslot2);
json_object_object_del_by_uint(jobj_keyslots, keyslot);
r = json_object_object_add_by_uint(jobj_keyslots, keyslot, jobj_keyslot2);
if (r < 0) {
log_dbg(cd, "Failed to swap keyslot %d.", keyslot);
return r;
}
json_object_object_del_by_uint(jobj_keyslots, keyslot2);
r = json_object_object_add_by_uint(jobj_keyslots, keyslot2, jobj_keyslot);
if (r < 0)
log_dbg(cd, "Failed to swap keyslot2 %d.", keyslot2);
return r;
}

View File

@@ -1,8 +1,8 @@
/*
* LUKS - Linux Unified Key Setup v2, LUKS2 type keyslot handler
*
* Copyright (C) 2015-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2021 Milan Broz
* Copyright (C) 2015-2019 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2019 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -48,7 +48,7 @@ static int luks2_encrypt_to_storage(char *src, size_t srcLength,
return -EINVAL;
/* Encrypt buffer */
r = crypt_storage_init(&s, SECTOR_SIZE, cipher, cipher_mode, vk->key, vk->keylength, false);
r = crypt_storage_init(&s, SECTOR_SIZE, cipher, cipher_mode, vk->key, vk->keylength);
if (r) {
log_err(cd, _("Cannot use %s-%s cipher for keyslot encryption."), cipher, cipher_mode);
return r;
@@ -103,7 +103,7 @@ static int luks2_decrypt_from_storage(char *dst, size_t dstLength,
if (MISALIGNED_512(dstLength))
return -EINVAL;
r = crypt_storage_init(&s, SECTOR_SIZE, cipher, cipher_mode, vk->key, vk->keylength, false);
r = crypt_storage_init(&s, SECTOR_SIZE, cipher, cipher_mode, vk->key, vk->keylength);
if (r) {
log_err(cd, _("Cannot use %s-%s cipher for keyslot encryption."), cipher, cipher_mode);
return r;
@@ -325,6 +325,13 @@ static int luks2_keyslot_get_key(struct crypt_device *cd,
return -EINVAL;
keyslot_key_len = json_object_get_int(jobj2);
/*
* If requested, serialize unlocking for memory-hard KDF. Usually NOOP.
*/
if (pbkdf.max_memory_kb > MIN_MEMORY_FOR_SERIALIZE_LOCK_KB)
try_serialize_lock = true;
if (try_serialize_lock && crypt_serialize_lock(cd))
return -EINVAL;
/*
* Allocate derived key storage space.
*/
@@ -335,18 +342,9 @@ static int luks2_keyslot_get_key(struct crypt_device *cd,
AFEKSize = AF_split_sectors(volume_key_len, LUKS_STRIPES) * SECTOR_SIZE;
AfKey = crypt_safe_alloc(AFEKSize);
if (!AfKey) {
r = -ENOMEM;
goto out;
crypt_free_volume_key(derived_key);
return -ENOMEM;
}
/*
* If requested, serialize unlocking for memory-hard KDF. Usually NOOP.
*/
if (pbkdf.max_memory_kb > MIN_MEMORY_FOR_SERIALIZE_LOCK_KB)
try_serialize_lock = true;
if (try_serialize_lock && (r = crypt_serialize_lock(cd)))
goto out;
/*
* Calculate derived key, decrypt keyslot content and merge it.
*/
@@ -369,7 +367,6 @@ static int luks2_keyslot_get_key(struct crypt_device *cd,
if (r == 0)
r = AF_merge(cd, AfKey, volume_key, volume_key_len, LUKS_STRIPES, af_hash);
out:
crypt_free_volume_key(derived_key);
crypt_safe_free(AfKey);
@@ -465,7 +462,7 @@ static int luks2_keyslot_alloc(struct crypt_device *cd,
return -EINVAL;
if (keyslot == CRYPT_ANY_SLOT)
keyslot = LUKS2_keyslot_find_empty(cd, hdr, 0);
keyslot = LUKS2_keyslot_find_empty(hdr);
if (keyslot < 0 || keyslot >= LUKS2_KEYSLOTS_MAX)
return -ENOMEM;
@@ -738,7 +735,7 @@ static int luks2_keyslot_update(struct crypt_device *cd,
return r;
}
static void luks2_keyslot_repair(struct crypt_device *cd __attribute__((unused)), json_object *jobj_keyslot)
static void luks2_keyslot_repair(struct crypt_device *cd, json_object *jobj_keyslot)
{
const char *type;
json_object *jobj_kdf, *jobj_type;

View File

@@ -1,8 +1,8 @@
/*
* LUKS - Linux Unified Key Setup v2, reencryption keyslot handler
*
* Copyright (C) 2016-2021, Red Hat, Inc. All rights reserved.
* Copyright (C) 2016-2021, Ondrej Kozina
* Copyright (C) 2016-2018, Red Hat, Inc. All rights reserved.
* Copyright (C) 2016-2018, Ondrej Kozina
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -21,12 +21,12 @@
#include "luks2_internal.h"
static int reenc_keyslot_open(struct crypt_device *cd __attribute__((unused)),
int keyslot __attribute__((unused)),
const char *password __attribute__((unused)),
size_t password_len __attribute__((unused)),
char *volume_key __attribute__((unused)),
size_t volume_key_len __attribute__((unused)))
static int reenc_keyslot_open(struct crypt_device *cd,
int keyslot,
const char *password,
size_t password_len,
char *volume_key,
size_t volume_key_len)
{
return -ENOENT;
}
@@ -176,8 +176,42 @@ static int reenc_keyslot_store(struct crypt_device *cd,
return r < 0 ? r : keyslot;
}
static int reenc_keyslot_wipe(struct crypt_device *cd __attribute__((unused)),
int keyslot __attribute__((unused)))
int reenc_keyslot_update(struct crypt_device *cd,
const struct luks2_reenc_context *rh)
{
json_object *jobj_keyslot, *jobj_area, *jobj_area_type;
struct luks2_hdr *hdr;
if (!(hdr = crypt_get_hdr(cd, CRYPT_LUKS2)))
return -EINVAL;
jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, rh->reenc_keyslot);
if (!jobj_keyslot)
return -EINVAL;
json_object_object_get_ex(jobj_keyslot, "area", &jobj_area);
json_object_object_get_ex(jobj_area, "type", &jobj_area_type);
if (rh->rp.type == REENC_PROTECTION_CHECKSUM) {
log_dbg(cd, "Updating reencrypt keyslot for checksum protection.");
json_object_object_add(jobj_area, "type", json_object_new_string("checksum"));
json_object_object_add(jobj_area, "hash", json_object_new_string(rh->rp.p.csum.hash));
json_object_object_add(jobj_area, "sector_size", json_object_new_int64(rh->alignment));
} else if (rh->rp.type == REENC_PROTECTION_NONE) {
log_dbg(cd, "Updating reencrypt keyslot for none protection.");
json_object_object_add(jobj_area, "type", json_object_new_string("none"));
json_object_object_del(jobj_area, "hash");
} else if (rh->rp.type == REENC_PROTECTION_JOURNAL) {
log_dbg(cd, "Updating reencrypt keyslot for journal protection.");
json_object_object_add(jobj_area, "type", json_object_new_string("journal"));
json_object_object_del(jobj_area, "hash");
} else
log_dbg(cd, "No update of reencrypt keyslot needed.");
return 0;
}
static int reenc_keyslot_wipe(struct crypt_device *cd, int keyslot)
{
return 0;
}

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,8 @@
/*
* LUKS - Linux Unified Key Setup v2, internal segment handling
*
* Copyright (C) 2018-2021, Red Hat, Inc. All rights reserved.
* Copyright (C) 2018-2021, Ondrej Kozina
* Copyright (C) 2018-2019, Red Hat, Inc. All rights reserved.
* Copyright (C) 2018-2019, Ondrej Kozina
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License

View File

@@ -1,8 +1,8 @@
/*
* LUKS - Linux Unified Key Setup v2, token handling
*
* Copyright (C) 2016-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2016-2021 Milan Broz
* Copyright (C) 2016-2019 Red Hat, Inc. All rights reserved.
* Copyright (C) 2016-2019 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -19,197 +19,39 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <ctype.h>
#include <dlfcn.h>
#include <assert.h>
#include "luks2_internal.h"
#if USE_EXTERNAL_TOKENS
static bool external_tokens_enabled = true;
#else
static bool external_tokens_enabled = false;
#endif
/* Builtin tokens */
extern const crypt_token_handler keyring_handler;
static struct crypt_token_handler_internal token_handlers[LUKS2_TOKENS_MAX] = {
static token_handler token_handlers[LUKS2_TOKENS_MAX] = {
/* keyring builtin token */
{
.version = 1,
.u = {
.v1 = { .name = LUKS2_TOKEN_KEYRING,
.open = keyring_open,
.validate = keyring_validate,
.dump = keyring_dump }
}
}
.get = token_keyring_get,
.set = token_keyring_set,
.h = &keyring_handler
},
};
void crypt_token_external_disable(void)
{
external_tokens_enabled = false;
}
const char *crypt_token_external_path(void)
{
return external_tokens_enabled ? EXTERNAL_LUKS2_TOKENS_PATH : NULL;
}
#if USE_EXTERNAL_TOKENS
static void *token_dlvsym(struct crypt_device *cd,
void *handle,
const char *symbol,
const char *version)
{
char *error;
void *sym;
log_dbg(cd, "Loading symbol %s@%s.", symbol, version);
sym = dlvsym(handle, symbol, version);
error = dlerror();
if (error)
log_dbg(cd, "%s", error);
return sym;
}
#endif
static bool token_validate_v1(struct crypt_device *cd, const crypt_token_handler *h)
{
if (!h)
return false;
if (!h->name) {
log_dbg(cd, "Error: token handler does not provide name attribute.");
return false;
}
if (!h->open) {
log_dbg(cd, "Error: token handler does not provide open function.");
return false;
}
return true;
}
#if USE_EXTERNAL_TOKENS
static bool token_validate_v2(struct crypt_device *cd, const struct crypt_token_handler_internal *h)
{
if (!h)
return false;
if (!token_validate_v1(cd, &h->u.v1))
return false;
if (!h->u.v2.version) {
log_dbg(cd, "Error: token handler does not provide " CRYPT_TOKEN_ABI_VERSION " function.");
return false;
}
return true;
}
static bool external_token_name_valid(const char *name)
{
if (!*name || strlen(name) > LUKS2_TOKEN_NAME_MAX)
return false;
while (*name) {
if (!isalnum(*name) && *name != '-' && *name != '_')
return false;
name++;
}
return true;
}
#endif
static int
crypt_token_load_external(struct crypt_device *cd, const char *name, struct crypt_token_handler_internal *ret)
{
#if USE_EXTERNAL_TOKENS
struct crypt_token_handler_v2 *token;
void *h;
char buf[PATH_MAX];
int r;
if (!external_tokens_enabled)
return -ENOTSUP;
if (!ret || !name)
return -EINVAL;
if (!external_token_name_valid(name)) {
log_dbg(cd, "External token name (%.*s) invalid.", LUKS2_TOKEN_NAME_MAX, name);
return -EINVAL;
}
token = &ret->u.v2;
r = snprintf(buf, sizeof(buf), "%s/libcryptsetup-token-%s.so", crypt_token_external_path(), name);
if (r < 0 || (size_t)r >= sizeof(buf))
return -EINVAL;
assert(*buf == '/');
log_dbg(cd, "Trying to load %s.", buf);
h = dlopen(buf, RTLD_LAZY);
if (!h) {
log_dbg(cd, "%s", dlerror());
return -EINVAL;
}
dlerror();
token->name = strdup(name);
token->open = token_dlvsym(cd, h, CRYPT_TOKEN_ABI_OPEN, CRYPT_TOKEN_ABI_VERSION1);
token->buffer_free = token_dlvsym(cd, h, CRYPT_TOKEN_ABI_BUFFER_FREE, CRYPT_TOKEN_ABI_VERSION1);
token->validate = token_dlvsym(cd, h, CRYPT_TOKEN_ABI_VALIDATE, CRYPT_TOKEN_ABI_VERSION1);
token->dump = token_dlvsym(cd, h, CRYPT_TOKEN_ABI_DUMP, CRYPT_TOKEN_ABI_VERSION1);
token->open_pin = token_dlvsym(cd, h, CRYPT_TOKEN_ABI_OPEN_PIN, CRYPT_TOKEN_ABI_VERSION1);
token->version = token_dlvsym(cd, h, CRYPT_TOKEN_ABI_VERSION, CRYPT_TOKEN_ABI_VERSION1);
if (!token_validate_v2(cd, ret)) {
free(CONST_CAST(void *)token->name);
dlclose(h);
memset(token, 0, sizeof(*token));
return -EINVAL;
}
/* Token loaded, possible error here means only debug message fail and can be ignored */
r = snprintf(buf, sizeof(buf), "%s", token->version() ?: "");
if (r < 0 || (size_t)r >= sizeof(buf))
*buf = '\0';
log_dbg(cd, "Token handler %s-%s loaded sucessfuly.", token->name, buf);
token->dlhandle = h;
ret->version = 2;
return 0;
#else
return -ENOTSUP;
#endif
}
static int is_builtin_candidate(const char *type)
{
return !strncmp(type, LUKS2_BUILTIN_TOKEN_PREFIX, LUKS2_BUILTIN_TOKEN_PREFIX_LEN);
}
static int crypt_token_find_free(struct crypt_device *cd, const char *name, int *index)
int crypt_token_register(const crypt_token_handler *handler)
{
int i;
if (is_builtin_candidate(name)) {
log_dbg(cd, "'" LUKS2_BUILTIN_TOKEN_PREFIX "' is reserved prefix for builtin tokens.");
if (is_builtin_candidate(handler->name)) {
log_dbg(NULL, "'" LUKS2_BUILTIN_TOKEN_PREFIX "' is reserved prefix for builtin tokens.");
return -EINVAL;
}
for (i = 0; i < LUKS2_TOKENS_MAX && token_handlers[i].u.v1.name; i++) {
if (!strcmp(token_handlers[i].u.v1.name, name)) {
log_dbg(cd, "Keyslot handler %s is already registered.", name);
for (i = 0; i < LUKS2_TOKENS_MAX && token_handlers[i].h; i++) {
if (!strcmp(token_handlers[i].h->name, handler->name)) {
log_dbg(NULL, "Keyslot handler %s is already registered.", handler->name);
return -EINVAL;
}
}
@@ -217,68 +59,32 @@ static int crypt_token_find_free(struct crypt_device *cd, const char *name, int
if (i == LUKS2_TOKENS_MAX)
return -EINVAL;
if (index)
*index = i;
token_handlers[i].h = handler;
return 0;
}
int crypt_token_register(const crypt_token_handler *handler)
{
int i, r;
if (!token_validate_v1(NULL, handler))
return -EINVAL;
r = crypt_token_find_free(NULL, handler->name, &i);
if (r < 0)
return r;
token_handlers[i].version = 1;
token_handlers[i].u.v1 = *handler;
return 0;
}
void crypt_token_unload_external_all(struct crypt_device *cd)
static const token_handler
*LUKS2_token_handler_type_internal(struct crypt_device *cd, const char *type)
{
int i;
for (i = LUKS2_TOKENS_MAX - 1; i >= 0; i--) {
if (token_handlers[i].version < 2)
continue;
for (i = 0; i < LUKS2_TOKENS_MAX && token_handlers[i].h; i++)
if (!strcmp(token_handlers[i].h->name, type))
return token_handlers + i;
log_dbg(cd, "Unloading %s token handler.", token_handlers[i].u.v2.name);
free(CONST_CAST(void *)token_handlers[i].u.v2.name);
if (dlclose(CONST_CAST(void *)token_handlers[i].u.v2.dlhandle))
log_dbg(cd, "%s", dlerror());
}
return NULL;
}
static const void
static const crypt_token_handler
*LUKS2_token_handler_type(struct crypt_device *cd, const char *type)
{
int i;
const token_handler *th = LUKS2_token_handler_type_internal(cd, type);
for (i = 0; i < LUKS2_TOKENS_MAX && token_handlers[i].u.v1.name; i++)
if (!strcmp(token_handlers[i].u.v1.name, type))
return &token_handlers[i].u;
if (i >= LUKS2_TOKENS_MAX)
return NULL;
if (is_builtin_candidate(type))
return NULL;
if (crypt_token_load_external(cd, type, &token_handlers[i]))
return NULL;
return &token_handlers[i].u;
return th ? th->h : NULL;
}
static const void
*LUKS2_token_handler(struct crypt_device *cd, int token)
static const token_handler
*LUKS2_token_handler_internal(struct crypt_device *cd, int token)
{
struct luks2_hdr *hdr;
json_object *jobj1, *jobj2;
@@ -295,7 +101,15 @@ static const void
if (!json_object_object_get_ex(jobj1, "type", &jobj2))
return NULL;
return LUKS2_token_handler_type(cd, json_object_get_string(jobj2));
return LUKS2_token_handler_type_internal(cd, json_object_get_string(jobj2));
}
static const crypt_token_handler
*LUKS2_token_handler(struct crypt_device *cd, int token)
{
const token_handler *th = LUKS2_token_handler_internal(cd, token);
return th ? th->h : NULL;
}
static int LUKS2_token_find_free(struct luks2_hdr *hdr)
@@ -316,6 +130,7 @@ int LUKS2_token_create(struct crypt_device *cd,
int commit)
{
const crypt_token_handler *h;
const token_handler *th;
json_object *jobj_tokens, *jobj_type, *jobj;
enum json_tokener_error jerr;
char num[16];
@@ -332,8 +147,7 @@ int LUKS2_token_create(struct crypt_device *cd,
if (!json_object_object_get_ex(hdr->jobj, "tokens", &jobj_tokens))
return -EINVAL;
if (snprintf(num, sizeof(num), "%d", token) < 0)
return -EINVAL;
snprintf(num, sizeof(num), "%d", token);
/* Remove token */
if (!json)
@@ -352,14 +166,16 @@ int LUKS2_token_create(struct crypt_device *cd,
}
json_object_object_get_ex(jobj, "type", &jobj_type);
h = LUKS2_token_handler_type(cd, json_object_get_string(jobj_type));
if (is_builtin_candidate(json_object_get_string(jobj_type)) && !h) {
log_dbg(cd, "%s is builtin token candidate with missing handler",
json_object_get_string(jobj_type));
json_object_put(jobj);
return -EINVAL;
}
if (is_builtin_candidate(json_object_get_string(jobj_type))) {
th = LUKS2_token_handler_type_internal(cd, json_object_get_string(jobj_type));
if (!th || !th->set) {
log_dbg(cd, "%s is builtin token candidate with missing handler", json_object_get_string(jobj_type));
json_object_put(jobj);
return -EINVAL;
}
h = th->h;
} else
h = LUKS2_token_handler_type(cd, json_object_get_string(jobj_type));
if (h && h->validate && h->validate(cd, json)) {
json_object_put(jobj);
@@ -387,7 +203,7 @@ crypt_token_info LUKS2_token_status(struct crypt_device *cd,
const char **type)
{
const char *tmp;
const crypt_token_handler *th;
const token_handler *th;
json_object *jobj_type, *jobj_token;
if (token < 0 || token >= LUKS2_TOKENS_MAX)
@@ -399,10 +215,10 @@ crypt_token_info LUKS2_token_status(struct crypt_device *cd,
json_object_object_get_ex(jobj_token, "type", &jobj_type);
tmp = json_object_get_string(jobj_type);
if ((th = LUKS2_token_handler_type(cd, tmp))) {
if ((th = LUKS2_token_handler_type_internal(cd, tmp))) {
if (type)
*type = th->name;
return is_builtin_candidate(tmp) ? CRYPT_TOKEN_INTERNAL : CRYPT_TOKEN_EXTERNAL;
*type = th->h->name;
return th->set ? CRYPT_TOKEN_INTERNAL : CRYPT_TOKEN_EXTERNAL;
}
if (type)
@@ -411,109 +227,95 @@ crypt_token_info LUKS2_token_status(struct crypt_device *cd,
return is_builtin_candidate(tmp) ? CRYPT_TOKEN_INTERNAL_UNKNOWN : CRYPT_TOKEN_EXTERNAL_UNKNOWN;
}
static const char *token_json_to_string(json_object *jobj_token)
int LUKS2_builtin_token_get(struct crypt_device *cd,
struct luks2_hdr *hdr,
int token,
const char *type,
void *params)
{
return json_object_to_json_string_ext(jobj_token,
JSON_C_TO_STRING_PLAIN | JSON_C_TO_STRING_NOSLASHESCAPE);
const token_handler *th = LUKS2_token_handler_type_internal(cd, type);
// internal error
assert(th && th->get);
return th->get(LUKS2_get_token_jobj(hdr, token), params) ?: token;
}
static int token_is_usable(struct luks2_hdr *hdr, json_object *jobj_token, int segment, crypt_keyslot_priority minimal_priority)
int LUKS2_builtin_token_create(struct crypt_device *cd,
struct luks2_hdr *hdr,
int token,
const char *type,
const void *params,
int commit)
{
crypt_keyslot_priority keyslot_priority;
json_object *jobj_array;
int i, keyslot, len, r = -ENOENT;
const token_handler *th;
int r;
json_object *jobj_token, *jobj_tokens;
if (!jobj_token)
th = LUKS2_token_handler_type_internal(cd, type);
// at this point all builtin handlers must exist and have validate fn defined
assert(th && th->set && th->h->validate);
if (token == CRYPT_ANY_TOKEN) {
if ((token = LUKS2_token_find_free(hdr)) < 0)
log_err(cd, _("No free token slot."));
}
if (token < 0 || token >= LUKS2_TOKENS_MAX)
return -EINVAL;
if (!json_object_object_get_ex(jobj_token, "keyslots", &jobj_array))
return -EINVAL;
if (segment < 0 && segment != CRYPT_ANY_SEGMENT)
return -EINVAL;
/* no assigned keyslot returns -ENOENT even for CRYPT_ANY_SEGMENT */
len = json_object_array_length(jobj_array);
if (len <= 0)
return -ENOENT;
for (i = 0; i < len; i++) {
keyslot = atoi(json_object_get_string(json_object_array_get_idx(jobj_array, i)));
keyslot_priority = LUKS2_keyslot_priority_get(NULL, hdr, keyslot);
if (keyslot_priority == CRYPT_SLOT_PRIORITY_INVALID)
return -EINVAL;
if (keyslot_priority < minimal_priority)
continue;
r = LUKS2_keyslot_for_segment(hdr, keyslot, segment);
if (r != -ENOENT)
return r;
r = th->set(&jobj_token, params);
if (r) {
log_err(cd, _("Failed to create builtin token %s."), type);
return r;
}
return r;
}
// builtin tokens must produce valid json
r = LUKS2_token_validate(cd, hdr->jobj, jobj_token, "new");
assert(!r);
r = th->h->validate(cd, json_object_to_json_string_ext(jobj_token,
JSON_C_TO_STRING_PLAIN | JSON_C_TO_STRING_NOSLASHESCAPE));
assert(!r);
static int translate_errno(struct crypt_device *cd, int ret_val, const char *type)
{
if ((ret_val > 0 || ret_val == -EINVAL || ret_val == -EPERM) && !is_builtin_candidate(type)) {
log_dbg(cd, "%s token handler returned %d. Changing to %d.", type, ret_val, -ENOENT);
ret_val = -ENOENT;
json_object_object_get_ex(hdr->jobj, "tokens", &jobj_tokens);
json_object_object_add_by_uint(jobj_tokens, token, jobj_token);
if (LUKS2_check_json_size(cd, hdr)) {
log_dbg(cd, "Not enough space in header json area for new %s token.", type);
json_object_object_del_by_uint(jobj_tokens, token);
return -ENOSPC;
}
return ret_val;
if (commit)
return LUKS2_hdr_write(cd, hdr) ?: token;
return token;
}
static int LUKS2_token_open(struct crypt_device *cd,
struct luks2_hdr *hdr,
int token,
json_object *jobj_token,
const char *type,
int segment,
crypt_keyslot_priority priority,
const char *pin,
size_t pin_size,
char **buffer,
size_t *buffer_len,
void *usrptr)
{
const struct crypt_token_handler_v2 *h;
json_object *jobj_type;
const char *json;
const crypt_token_handler *h;
int r;
assert(token >= 0);
assert(jobj_token);
assert(priority >= 0);
if (type) {
if (!json_object_object_get_ex(jobj_token, "type", &jobj_type))
return -EINVAL;
if (strcmp(type, json_object_get_string(jobj_type)))
return -ENOENT;
}
r = token_is_usable(hdr, jobj_token, segment, priority);
if (r < 0) {
if (r == -ENOENT)
log_dbg(cd, "Token %d unusable for segment %d with desired keyslot priority %d.", token, segment, priority);
return r;
}
if (!(h = LUKS2_token_handler(cd, token)))
return -ENOENT;
if (h->validate && h->validate(cd, token_json_to_string(jobj_token))) {
log_dbg(cd, "Token %d (%s) validation failed.", token, h->name);
return -ENOENT;
if (h->validate) {
if (LUKS2_token_json_get(cd, hdr, token, &json))
return -EINVAL;
if (h->validate(cd, json)) {
log_dbg(cd, "Token %d (%s) validation failed.", token, h->name);
return -EINVAL;
}
}
if (pin && !h->open_pin)
r = -ENOENT;
else if (pin)
r = translate_errno(cd, h->open_pin(cd, token, pin, pin_size, buffer, buffer_len, usrptr), h->name);
else
r = translate_errno(cd, h->open(cd, token, buffer, buffer_len, usrptr), h->name);
r = h->open(cd, token, buffer, buffer_len, usrptr);
if (r < 0)
log_dbg(cd, "Token %d (%s) open failed with %d.", token, h->name, r);
@@ -527,224 +329,129 @@ static void LUKS2_token_buffer_free(struct crypt_device *cd,
{
const crypt_token_handler *h = LUKS2_token_handler(cd, token);
if (h && h->buffer_free)
if (h->buffer_free)
h->buffer_free(buffer, buffer_len);
else {
crypt_safe_memzero(buffer, buffer_len);
crypt_memzero(buffer, buffer_len);
free(buffer);
}
}
static bool break_loop_retval(int r)
{
if (r == -ENOENT || r == -EPERM || r == -EAGAIN || r == -ENOANO)
return false;
return true;
}
static void update_return_errno(int r, int *stored)
{
if (*stored == -ENOANO)
return;
else if (r == -ENOANO)
*stored = r;
else if (r == -EAGAIN && *stored != -ENOANO)
*stored = r;
else if (r == -EPERM && (*stored != -ENOANO && *stored != -EAGAIN))
*stored = r;
}
static int LUKS2_keyslot_open_by_token(struct crypt_device *cd,
struct luks2_hdr *hdr,
int token,
int segment,
crypt_keyslot_priority priority,
const char *buffer,
size_t buffer_len,
struct volume_key **vk)
{
crypt_keyslot_priority keyslot_priority;
json_object *jobj_token, *jobj_token_keyslots, *jobj_type, *jobj;
const crypt_token_handler *h;
json_object *jobj_token, *jobj_token_keyslots, *jobj;
unsigned int num = 0;
int i, r = -ENOENT, stored_retval = -ENOENT;
int i, r;
if (!(h = LUKS2_token_handler(cd, token)))
return -ENOENT;
jobj_token = LUKS2_get_token_jobj(hdr, token);
if (!jobj_token)
return -EINVAL;
if (!json_object_object_get_ex(jobj_token, "type", &jobj_type))
return -EINVAL;
json_object_object_get_ex(jobj_token, "keyslots", &jobj_token_keyslots);
if (!jobj_token_keyslots)
return -EINVAL;
/* Try to open keyslot referenced in token */
r = -EINVAL;
for (i = 0; i < (int) json_object_array_length(jobj_token_keyslots) && r < 0; i++) {
jobj = json_object_array_get_idx(jobj_token_keyslots, i);
num = atoi(json_object_get_string(jobj));
keyslot_priority = LUKS2_keyslot_priority_get(NULL, hdr, num);
if (keyslot_priority == CRYPT_SLOT_PRIORITY_INVALID)
return -EINVAL;
if (keyslot_priority < priority)
continue;
log_dbg(cd, "Trying to open keyslot %u with token %d (type %s).", num, token, json_object_get_string(jobj_type));
log_dbg(cd, "Trying to open keyslot %u with token %d (type %s).", num, token, h->name);
r = LUKS2_keyslot_open(cd, num, segment, buffer, buffer_len, vk);
/* short circuit on fatal error */
if (r < 0 && r != -EPERM && r != -ENOENT)
return r;
/* save -EPERM in case no other keyslot is usable */
if (r == -EPERM)
stored_retval = r;
}
if (r < 0)
return stored_retval;
return r;
return num;
}
static bool token_is_blocked(int token, uint32_t *block_list)
{
/* it is safe now, but have assert in case LUKS2_TOKENS_MAX grows */
assert(token >= 0 && (size_t)token < BITFIELD_SIZE(block_list));
return (*block_list & (1 << token));
}
static void token_block(int token, uint32_t *block_list)
{
/* it is safe now, but have assert in case LUKS2_TOKENS_MAX grows */
assert(token >= 0 && (size_t)token < BITFIELD_SIZE(block_list));
*block_list |= (1 << token);
}
static int token_open_priority(struct crypt_device *cd,
struct luks2_hdr *hdr,
json_object *jobj_tokens,
const char *type,
int segment,
crypt_keyslot_priority priority,
const char *pin,
size_t pin_size,
void *usrptr,
int *stored_retval,
uint32_t *block_list,
struct volume_key **vk)
{
char *buffer;
size_t buffer_size;
int token, r;
assert(stored_retval);
assert(block_list);
json_object_object_foreach(jobj_tokens, slot, val) {
token = atoi(slot);
if (token_is_blocked(token, block_list))
continue;
r = LUKS2_token_open(cd, hdr, token, val, type, segment, priority, pin, pin_size, &buffer, &buffer_size, usrptr);
if (!r) {
r = LUKS2_keyslot_open_by_token(cd, hdr, token, segment, priority,
buffer, buffer_size, vk);
LUKS2_token_buffer_free(cd, token, buffer, buffer_size);
}
if (r == -ENOANO)
token_block(token, block_list);
if (break_loop_retval(r))
return r;
update_return_errno(r, stored_retval);
}
return *stored_retval;
}
static int token_open_any(struct crypt_device *cd, struct luks2_hdr *hdr, const char *type, int segment, const char *pin, size_t pin_size, void *usrptr, struct volume_key **vk)
{
json_object *jobj_tokens;
int r, retval = -ENOENT;
uint32_t blocked = 0; /* bitmap with tokens blocked from loop by returning -ENOANO (wrong/missing pin) */
json_object_object_get_ex(hdr->jobj, "tokens", &jobj_tokens);
/* passing usrptr for CRYPT_ANY_TOKEN does not make sense without specific type */
if (!type)
usrptr = NULL;
r = token_open_priority(cd, hdr, jobj_tokens, type, segment, CRYPT_SLOT_PRIORITY_PREFER, pin, pin_size, usrptr, &retval, &blocked, vk);
if (break_loop_retval(r))
return r;
return token_open_priority(cd, hdr, jobj_tokens, type, segment, CRYPT_SLOT_PRIORITY_NORMAL, pin, pin_size, usrptr, &retval, &blocked, vk);
}
int LUKS2_token_open_and_activate(struct crypt_device *cd,
struct luks2_hdr *hdr,
int token,
const char *name,
const char *type,
const char *pin,
size_t pin_size,
uint32_t flags,
void *usrptr)
struct luks2_hdr *hdr,
int token,
const char *name,
uint32_t flags,
void *usrptr)
{
bool use_keyring;
int keyslot, r;
char *buffer;
size_t buffer_size;
json_object *jobj_token;
int keyslot, segment, r = -ENOENT;
size_t buffer_len;
struct volume_key *vk = NULL;
if (flags & CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY)
segment = CRYPT_ANY_SEGMENT;
else {
segment = LUKS2_get_default_segment(hdr);
if (segment < 0)
return -EINVAL;
}
r = LUKS2_token_open(cd, hdr, token, &buffer, &buffer_len, usrptr);
if (r < 0)
return r;
if (token >= 0 && token < LUKS2_TOKENS_MAX) {
if ((jobj_token = LUKS2_get_token_jobj(hdr, token))) {
r = LUKS2_token_open(cd, hdr, token, jobj_token, type, segment, CRYPT_SLOT_PRIORITY_IGNORE, pin, pin_size, &buffer, &buffer_size, usrptr);
if (!r) {
r = LUKS2_keyslot_open_by_token(cd, hdr, token, segment, CRYPT_SLOT_PRIORITY_IGNORE,
buffer, buffer_size, &vk);
LUKS2_token_buffer_free(cd, token, buffer, buffer_size);
}
}
} else if (token == CRYPT_ANY_TOKEN)
/*
* return priorities (ordered form least to most significant):
* ENOENT - unusable for activation (no token handler, invalid token metadata, not assigned to volume segment, etc)
* EPERM - usable but token provided passphrase did not not unlock any assigned keyslot
* EAGAIN - usable but not ready (token HW is missing)
* ENOANO - ready, but token pin is wrong or missing
*
* success (>= 0) or any other negative errno short-circuits token activation loop
* immediately
*/
r = token_open_any(cd, hdr, type, segment, pin, pin_size, usrptr, &vk);
else
return -EINVAL;
r = LUKS2_keyslot_open_by_token(cd, hdr, token,
(flags & CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY) ?
CRYPT_ANY_SEGMENT : CRYPT_DEFAULT_SEGMENT,
buffer, buffer_len, &vk);
LUKS2_token_buffer_free(cd, token, buffer, buffer_len);
if (r < 0)
return r;
assert(vk);
keyslot = r;
if ((name || (flags & CRYPT_ACTIVATE_KEYRING_KEY)) && crypt_use_keyring_for_vk(cd)) {
if (!(r = LUKS2_volume_key_load_in_keyring_by_keyslot(cd, hdr, vk, keyslot)))
flags |= CRYPT_ACTIVATE_KEYRING_KEY;
}
if (r >= 0 && name)
r = LUKS2_activate(cd, name, vk, flags);
if (r < 0)
crypt_drop_keyring_key(cd, vk);
crypt_free_volume_key(vk);
return r < 0 ? r : keyslot;
}
int LUKS2_token_open_and_activate_any(struct crypt_device *cd,
struct luks2_hdr *hdr,
const char *name,
uint32_t flags)
{
char *buffer;
json_object *tokens_jobj;
size_t buffer_len;
int keyslot, token, r = -EINVAL;
struct volume_key *vk = NULL;
json_object_object_get_ex(hdr->jobj, "tokens", &tokens_jobj);
json_object_object_foreach(tokens_jobj, slot, val) {
UNUSED(val);
token = atoi(slot);
r = LUKS2_token_open(cd, hdr, token, &buffer, &buffer_len, NULL);
if (r < 0)
continue;
r = LUKS2_keyslot_open_by_token(cd, hdr, token,
(flags & CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY) ?
CRYPT_ANY_SEGMENT : CRYPT_DEFAULT_SEGMENT,
buffer, buffer_len, &vk);
LUKS2_token_buffer_free(cd, token, buffer, buffer_len);
if (r >= 0)
break;
}
keyslot = r;
if (!crypt_use_keyring_for_vk(cd))
use_keyring = false;
else
use_keyring = ((name && !crypt_is_cipher_null(crypt_get_cipher(cd))) ||
(flags & CRYPT_ACTIVATE_KEYRING_KEY));
if (use_keyring) {
if (r >= 0 && (name || (flags & CRYPT_ACTIVATE_KEYRING_KEY)) && crypt_use_keyring_for_vk(cd)) {
if (!(r = LUKS2_volume_key_load_in_keyring_by_keyslot(cd, hdr, vk, keyslot)))
flags |= CRYPT_ACTIVATE_KEYRING_KEY;
}
@@ -773,7 +480,7 @@ void LUKS2_token_dump(struct crypt_device *cd, int token)
}
}
int LUKS2_token_json_get(struct crypt_device *cd __attribute__((unused)), struct luks2_hdr *hdr,
int LUKS2_token_json_get(struct crypt_device *cd, struct luks2_hdr *hdr,
int token, const char **json)
{
json_object *jobj_token;
@@ -782,7 +489,8 @@ int LUKS2_token_json_get(struct crypt_device *cd __attribute__((unused)), struct
if (!jobj_token)
return -EINVAL;
*json = token_json_to_string(jobj_token);
*json = json_object_to_json_string_ext(jobj_token,
JSON_C_TO_STRING_PLAIN | JSON_C_TO_STRING_NOSLASHESCAPE);
return 0;
}
@@ -802,9 +510,7 @@ static int assign_one_keyslot(struct crypt_device *cd, struct luks2_hdr *hdr,
if (!jobj_token_keyslots)
return -EINVAL;
if (snprintf(num, sizeof(num), "%d", keyslot) < 0)
return -EINVAL;
snprintf(num, sizeof(num), "%d", keyslot);
if (assign) {
jobj1 = LUKS2_array_jobj(jobj_token_keyslots, num);
if (!jobj1)
@@ -863,18 +569,23 @@ int LUKS2_token_assign(struct crypt_device *cd, struct luks2_hdr *hdr,
if (r < 0)
return r;
// FIXME: do not write header in nothing changed
if (commit)
return LUKS2_hdr_write(cd, hdr) ?: token;
return token;
}
static int token_is_assigned(struct luks2_hdr *hdr, int keyslot, int token)
int LUKS2_token_is_assigned(struct crypt_device *cd, struct luks2_hdr *hdr,
int keyslot, int token)
{
int i;
json_object *jobj, *jobj_token_keyslots,
*jobj_token = LUKS2_get_token_jobj(hdr, token);
json_object *jobj_token, *jobj_token_keyslots, *jobj;
if (keyslot < 0 || keyslot >= LUKS2_KEYSLOTS_MAX || token < 0 || token >= LUKS2_TOKENS_MAX)
return -EINVAL;
jobj_token = LUKS2_get_token_jobj(hdr, token);
if (!jobj_token)
return -ENOENT;
@@ -889,15 +600,6 @@ static int token_is_assigned(struct luks2_hdr *hdr, int keyslot, int token)
return -ENOENT;
}
int LUKS2_token_is_assigned(struct crypt_device *cd __attribute__((unused)), struct luks2_hdr *hdr,
int keyslot, int token)
{
if (keyslot < 0 || keyslot >= LUKS2_KEYSLOTS_MAX || token < 0 || token >= LUKS2_TOKENS_MAX)
return -EINVAL;
return token_is_assigned(hdr, keyslot, token);
}
int LUKS2_tokens_count(struct luks2_hdr *hdr)
{
json_object *jobj_tokens = LUKS2_get_tokens_jobj(hdr);
@@ -906,28 +608,3 @@ int LUKS2_tokens_count(struct luks2_hdr *hdr)
return json_object_object_length(jobj_tokens);
}
int LUKS2_token_assignment_copy(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot_from,
int keyslot_to,
int commit)
{
int i, r;
if (keyslot_from < 0 || keyslot_from >= LUKS2_KEYSLOTS_MAX || keyslot_to < 0 || keyslot_to >= LUKS2_KEYSLOTS_MAX)
return -EINVAL;
r = LUKS2_tokens_count(hdr);
if (r <= 0)
return r;
for (i = 0; i < LUKS2_TOKENS_MAX; i++) {
if (!token_is_assigned(hdr, keyslot_from, i)) {
if ((r = assign_one_token(cd, hdr, keyslot_to, i, 1)))
return r;
}
}
return commit ? LUKS2_hdr_write(cd, hdr) : 0;
}

View File

@@ -1,8 +1,8 @@
/*
* LUKS - Linux Unified Key Setup v2, kernel keyring token
*
* Copyright (C) 2016-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2016-2021 Ondrej Kozina
* Copyright (C) 2016-2019 Red Hat, Inc. All rights reserved.
* Copyright (C) 2016-2019 Ondrej Kozina
*
* 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 @@
#include "luks2_internal.h"
int keyring_open(struct crypt_device *cd,
static int keyring_open(struct crypt_device *cd,
int token,
char **buffer,
size_t *buffer_len,
@@ -45,16 +45,16 @@ int keyring_open(struct crypt_device *cd,
r = keyring_get_passphrase(json_object_get_string(jobj_key), buffer, buffer_len);
if (r == -ENOTSUP) {
log_dbg(cd, "Kernel keyring features disabled.");
return -ENOENT;
return -EINVAL;
} else if (r < 0) {
log_dbg(cd, "keyring_get_passphrase failed (error %d)", r);
return -EPERM;
return -EINVAL;
}
return 0;
}
int keyring_validate(struct crypt_device *cd __attribute__((unused)),
static int keyring_validate(struct crypt_device *cd __attribute__((unused)),
const char *json)
{
enum json_tokener_error jerr;
@@ -92,7 +92,7 @@ out:
return r;
}
void keyring_dump(struct crypt_device *cd, const char *json)
static void keyring_dump(struct crypt_device *cd, const char *json)
{
enum json_tokener_error jerr;
json_object *jobj_token, *jobj_key;
@@ -111,25 +111,47 @@ void keyring_dump(struct crypt_device *cd, const char *json)
json_object_put(jobj_token);
}
int LUKS2_token_keyring_json(char *buffer, size_t buffer_size,
const struct crypt_token_params_luks2_keyring *keyring_params)
int token_keyring_set(json_object **jobj_builtin_token,
const void *params)
{
int r;
json_object *jobj_token, *jobj;
const struct crypt_token_params_luks2_keyring *keyring_params = (const struct crypt_token_params_luks2_keyring *) params;
r = snprintf(buffer, buffer_size, "{ \"type\": \"%s\", \"keyslots\":[],\"key_description\":\"%s\"}",
LUKS2_TOKEN_KEYRING, keyring_params->key_description);
if (r < 0 || (size_t)r >= buffer_size)
return -EINVAL;
jobj_token = json_object_new_object();
if (!jobj_token)
return -ENOMEM;
jobj = json_object_new_string(LUKS2_TOKEN_KEYRING);
if (!jobj) {
json_object_put(jobj_token);
return -ENOMEM;
}
json_object_object_add(jobj_token, "type", jobj);
jobj = json_object_new_array();
if (!jobj) {
json_object_put(jobj_token);
return -ENOMEM;
}
json_object_object_add(jobj_token, "keyslots", jobj);
jobj = json_object_new_string(keyring_params->key_description);
if (!jobj) {
json_object_put(jobj_token);
return -ENOMEM;
}
json_object_object_add(jobj_token, "key_description", jobj);
*jobj_builtin_token = jobj_token;
return 0;
}
int LUKS2_token_keyring_get(struct crypt_device *cd __attribute__((unused)), struct luks2_hdr *hdr,
int token, struct crypt_token_params_luks2_keyring *keyring_params)
int token_keyring_get(json_object *jobj_token,
void *params)
{
json_object *jobj_token, *jobj;
json_object *jobj;
struct crypt_token_params_luks2_keyring *keyring_params = (struct crypt_token_params_luks2_keyring *) params;
jobj_token = LUKS2_get_token_jobj(hdr, token);
json_object_object_get_ex(jobj_token, "type", &jobj);
assert(!strcmp(json_object_get_string(jobj), LUKS2_TOKEN_KEYRING));
@@ -137,5 +159,12 @@ int LUKS2_token_keyring_get(struct crypt_device *cd __attribute__((unused)), str
keyring_params->key_description = json_object_get_string(jobj);
return token;
return 0;
}
const crypt_token_handler keyring_handler = {
.name = LUKS2_TOKEN_KEYRING,
.open = keyring_open,
.validate = keyring_validate,
.dump = keyring_dump
};

View File

@@ -1,7 +1,7 @@
/*
* cryptsetup kernel RNG access functions
*
* Copyright (C) 2010-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2019 Red Hat, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -20,6 +20,7 @@
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <assert.h>
#include <sys/select.h>
@@ -27,6 +28,10 @@
#include "libcryptsetup.h"
#include "internal.h"
#ifndef O_CLOEXEC
#define O_CLOEXEC 0
#endif
static int random_initialised = 0;
#define URANDOM_DEVICE "/dev/urandom"
@@ -153,20 +158,20 @@ int crypt_random_init(struct crypt_device *ctx)
if(urandom_fd == -1)
urandom_fd = open(URANDOM_DEVICE, O_RDONLY | O_CLOEXEC);
if(urandom_fd == -1)
goto err;
goto fail;
/* Used for CRYPT_RND_KEY */
if(random_fd == -1)
random_fd = open(RANDOM_DEVICE, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
if(random_fd == -1)
goto err;
goto fail;
if (crypt_fips_mode())
log_verbose(ctx, _("Running in FIPS mode."));
random_initialised = 1;
return 0;
err:
fail:
crypt_random_exit();
log_err(ctx, _("Fatal error during RNG initialisation."));
return -ENOSYS;

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,8 @@
/*
* TCRYPT (TrueCrypt-compatible) and VeraCrypt volume handling
*
* Copyright (C) 2012-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2021 Milan Broz
* Copyright (C) 2012-2019 Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2019 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -23,6 +23,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <assert.h>
#include "libcryptsetup.h"
@@ -274,11 +275,11 @@ static int decrypt_blowfish_le_cbc(struct tcrypt_alg *alg,
const char *key, char *buf)
{
int bs = alg->iv_size;
char iv[8], iv_old[8];
char iv[bs], iv_old[bs];
struct crypt_cipher *cipher = NULL;
int i, j, r;
assert(bs == 8);
assert(bs == 2*sizeof(uint32_t));
r = crypt_cipher_init(&cipher, "blowfish", "ecb",
&key[alg->key_offset], alg->key_size);
@@ -300,8 +301,8 @@ static int decrypt_blowfish_le_cbc(struct tcrypt_alg *alg,
}
crypt_cipher_destroy(cipher);
crypt_safe_memzero(iv, bs);
crypt_safe_memzero(iv_old, bs);
crypt_memzero(iv, bs);
crypt_memzero(iv_old, bs);
return r;
}
@@ -368,8 +369,8 @@ static int TCRYPT_decrypt_hdr_one(struct tcrypt_alg *alg, const char *mode,
crypt_cipher_destroy(cipher);
}
crypt_safe_memzero(backend_key, sizeof(backend_key));
crypt_safe_memzero(iv, TCRYPT_HDR_IV_LEN);
crypt_memzero(backend_key, sizeof(backend_key));
crypt_memzero(iv, TCRYPT_HDR_IV_LEN);
return r;
}
@@ -380,15 +381,12 @@ static int TCRYPT_decrypt_hdr_one(struct tcrypt_alg *alg, const char *mode,
static int TCRYPT_decrypt_cbci(struct tcrypt_algs *ciphers,
const char *key, struct tcrypt_phdr *hdr)
{
struct crypt_cipher *cipher[3];
struct crypt_cipher *cipher[ciphers->chain_count];
unsigned int bs = ciphers->cipher[0].iv_size;
char *buf = (char*)&hdr->e, iv[16], iv_old[16];
char *buf = (char*)&hdr->e, iv[bs], iv_old[bs];
unsigned int i, j;
int r = -EINVAL;
assert(ciphers->chain_count <= 3);
assert(bs <= 16);
TCRYPT_remove_whitening(buf, &key[8]);
memcpy(iv, &key[ciphers->cipher[0].iv_offset], bs);
@@ -422,21 +420,19 @@ out:
if (cipher[j])
crypt_cipher_destroy(cipher[j]);
crypt_safe_memzero(iv, bs);
crypt_safe_memzero(iv_old, 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, struct crypt_params_tcrypt *params)
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 (params->cipher && !strstr(tcrypt_cipher[i].long_name, params->cipher))
continue;
if (!(params->flags & CRYPT_TCRYPT_LEGACY_MODES) && tcrypt_cipher[i].legacy)
if (!(flags & CRYPT_TCRYPT_LEGACY_MODES) && tcrypt_cipher[i].legacy)
continue;
log_dbg(cd, "TCRYPT: trying cipher %s-%s",
tcrypt_cipher[i].long_name, tcrypt_cipher[i].mode);
@@ -468,7 +464,7 @@ static int TCRYPT_decrypt_hdr(struct crypt_device *cd, struct tcrypt_phdr *hdr,
r = i;
break;
}
if ((params->flags & CRYPT_TCRYPT_VERA_MODES) &&
if ((flags & CRYPT_TCRYPT_VERA_MODES) &&
!strncmp(hdr2.d.magic, VCRYPT_HDR_MAGIC, TCRYPT_HDR_MAGIC_LEN)) {
log_dbg(cd, "TCRYPT: Signature magic detected (Veracrypt).");
memcpy(&hdr->e, &hdr2.e, TCRYPT_HDR_LEN);
@@ -478,13 +474,13 @@ static int TCRYPT_decrypt_hdr(struct crypt_device *cd, struct tcrypt_phdr *hdr,
r = -EPERM;
}
crypt_safe_memzero(&hdr2, sizeof(hdr2));
crypt_memzero(&hdr2, sizeof(hdr2));
return r;
}
static int TCRYPT_pool_keyfile(struct crypt_device *cd,
unsigned char pool[VCRYPT_KEY_POOL_LEN],
const char *keyfile, int keyfiles_pool_length)
unsigned char pool[TCRYPT_KEY_POOL_LEN],
const char *keyfile)
{
unsigned char *data;
int i, j, fd, data_size, r = -EIO;
@@ -516,12 +512,12 @@ static int TCRYPT_pool_keyfile(struct crypt_device *cd,
pool[j++] += (unsigned char)(crc >> 16);
pool[j++] += (unsigned char)(crc >> 8);
pool[j++] += (unsigned char)(crc);
j %= keyfiles_pool_length;
j %= TCRYPT_KEY_POOL_LEN;
}
r = 0;
out:
crypt_safe_memzero(&crc, sizeof(crc));
crypt_safe_memzero(data, TCRYPT_KEYFILE_LEN);
crypt_memzero(&crc, sizeof(crc));
crypt_memzero(data, TCRYPT_KEYFILE_LEN);
free(data);
return r;
@@ -531,39 +527,29 @@ static int TCRYPT_init_hdr(struct crypt_device *cd,
struct tcrypt_phdr *hdr,
struct crypt_params_tcrypt *params)
{
unsigned char pwd[VCRYPT_KEY_POOL_LEN] = {};
size_t passphrase_size, max_passphrase_size;
unsigned char pwd[TCRYPT_KEY_POOL_LEN] = {};
size_t passphrase_size;
char *key;
unsigned int i, skipped = 0, iterations;
int r = -EPERM, keyfiles_pool_length;
int r = -EPERM;
if (posix_memalign((void*)&key, crypt_getpagesize(), TCRYPT_HDR_KEY_LEN))
return -ENOMEM;
if (params->flags & CRYPT_TCRYPT_VERA_MODES &&
params->passphrase_size > TCRYPT_KEY_POOL_LEN) {
/* Really. Keyfile pool length depends on passphrase size in Veracrypt. */
max_passphrase_size = VCRYPT_KEY_POOL_LEN;
keyfiles_pool_length = VCRYPT_KEY_POOL_LEN;
} else {
max_passphrase_size = TCRYPT_KEY_POOL_LEN;
keyfiles_pool_length = TCRYPT_KEY_POOL_LEN;
}
if (params->keyfiles_count)
passphrase_size = max_passphrase_size;
passphrase_size = TCRYPT_KEY_POOL_LEN;
else
passphrase_size = params->passphrase_size;
if (params->passphrase_size > max_passphrase_size) {
log_err(cd, _("Maximum TCRYPT passphrase length (%zu) exceeded."),
max_passphrase_size);
if (params->passphrase_size > TCRYPT_KEY_POOL_LEN) {
log_err(cd, _("Maximum TCRYPT passphrase length (%d) exceeded."),
TCRYPT_KEY_POOL_LEN);
goto out;
}
/* Calculate pool content from keyfiles */
for (i = 0; i < params->keyfiles_count; i++) {
r = TCRYPT_pool_keyfile(cd, pwd, params->keyfiles[i], keyfiles_pool_length);
r = TCRYPT_pool_keyfile(cd, pwd, params->keyfiles[i]);
if (r < 0)
goto out;
}
@@ -573,8 +559,6 @@ static int TCRYPT_init_hdr(struct crypt_device *cd,
pwd[i] += params->passphrase[i];
for (i = 0; tcrypt_kdf[i].name; i++) {
if (params->hash_name && strcmp(params->hash_name, tcrypt_kdf[i].hash))
continue;
if (!(params->flags & CRYPT_TCRYPT_LEGACY_MODES) && tcrypt_kdf[i].legacy)
continue;
if (!(params->flags & CRYPT_TCRYPT_VERA_MODES) && tcrypt_kdf[i].veracrypt)
@@ -605,7 +589,7 @@ static int TCRYPT_init_hdr(struct crypt_device *cd,
}
/* Decrypt header */
r = TCRYPT_decrypt_hdr(cd, hdr, key, params);
r = TCRYPT_decrypt_hdr(cd, hdr, key, params->flags);
if (r == -ENOENT) {
skipped++;
r = -EPERM;
@@ -635,9 +619,9 @@ static int TCRYPT_init_hdr(struct crypt_device *cd,
params->cipher, params->mode, params->key_size);
}
out:
crypt_safe_memzero(pwd, TCRYPT_KEY_POOL_LEN);
crypt_memzero(pwd, TCRYPT_KEY_POOL_LEN);
if (key)
crypt_safe_memzero(key, TCRYPT_HDR_KEY_LEN);
crypt_memzero(key, TCRYPT_HDR_KEY_LEN);
free(key);
return r;
}
@@ -756,14 +740,14 @@ int TCRYPT_activate(struct crypt_device *cd,
return -ENOTSUP;
}
if (hdr->d.sector_size % SECTOR_SIZE) {
if (hdr->d.sector_size && hdr->d.sector_size != SECTOR_SIZE) {
log_err(cd, _("Activation is not supported for %d sector size."),
hdr->d.sector_size);
return -ENOTSUP;
}
if (strstr(params->mode, "-tcrypt")) {
log_err(cd, _("Kernel does not support activation for this TCRYPT legacy mode."));
log_err(cd, _("Kernel doesn't support activation for this TCRYPT legacy mode."));
return -ENOTSUP;
}
@@ -776,12 +760,15 @@ int TCRYPT_activate(struct crypt_device *cd,
if (!algs)
return -EINVAL;
if (hdr->d.sector_size == 0)
return -EINVAL;
if (params->flags & CRYPT_TCRYPT_SYSTEM_HEADER)
dmd.size = 0;
else if (params->flags & CRYPT_TCRYPT_HIDDEN_HEADER)
dmd.size = hdr->d.hidden_volume_size / SECTOR_SIZE;
dmd.size = hdr->d.hidden_volume_size / hdr->d.sector_size;
else
dmd.size = hdr->d.volume_size / SECTOR_SIZE;
dmd.size = hdr->d.volume_size / hdr->d.sector_size;
if (dmd.flags & CRYPT_ACTIVATE_SHARED)
device_check = DEV_OK;
@@ -872,7 +859,7 @@ int TCRYPT_activate(struct crypt_device *cd,
if (r < 0 &&
(dm_flags(cd, DM_CRYPT, &dmc_flags) || ((dmc_flags & req_flags) != req_flags))) {
log_err(cd, _("Kernel does not support TCRYPT compatible mapping."));
log_err(cd, _("Kernel doesn't support TCRYPT compatible mapping."));
r = -ENOTSUP;
}
@@ -1029,32 +1016,41 @@ uint64_t TCRYPT_get_data_offset(struct crypt_device *cd,
{
uint64_t size;
if (!hdr->d.version) {
/* No real header loaded, initialized by active device, use default mk_offset */
} else if (params->flags & CRYPT_TCRYPT_SYSTEM_HEADER) {
/* Mapping through whole device, not partition! */
if (crypt_dev_is_partition(device_path(crypt_data_device(cd))))
/* No real header loaded, initialized by active device */
if (!hdr->d.version)
goto hdr_offset;
/* Mapping through whole device, not partition! */
if (params->flags & CRYPT_TCRYPT_SYSTEM_HEADER) {
if (crypt_dev_is_partition(device_path(crypt_metadata_device(cd))))
return 0;
} else if (params->mode && !strncmp(params->mode, "xts", 3)) {
goto hdr_offset;
}
if (params->mode && !strncmp(params->mode, "xts", 3)) {
if (hdr->d.version < 3)
return 1;
if (params->flags & CRYPT_TCRYPT_HIDDEN_HEADER) {
if (hdr->d.version > 3)
return (hdr->d.mk_offset / SECTOR_SIZE);
return (hdr->d.mk_offset / hdr->d.sector_size);
if (device_size(crypt_metadata_device(cd), &size) < 0)
return 0;
return (size - hdr->d.hidden_volume_size +
(TCRYPT_HDR_HIDDEN_OFFSET_OLD)) / SECTOR_SIZE;
(TCRYPT_HDR_HIDDEN_OFFSET_OLD)) / hdr->d.sector_size;
}
} else if (params->flags & CRYPT_TCRYPT_HIDDEN_HEADER) {
goto hdr_offset;
}
if (params->flags & CRYPT_TCRYPT_HIDDEN_HEADER) {
if (device_size(crypt_metadata_device(cd), &size) < 0)
return 0;
return (size - hdr->d.hidden_volume_size +
(TCRYPT_HDR_HIDDEN_OFFSET_OLD)) / SECTOR_SIZE;
(TCRYPT_HDR_HIDDEN_OFFSET_OLD)) / hdr->d.sector_size;
}
return hdr->d.mk_offset / SECTOR_SIZE;
hdr_offset:
return hdr->d.mk_offset / hdr->d.sector_size;
}
uint64_t TCRYPT_get_iv_offset(struct crypt_device *cd,
@@ -1068,10 +1064,10 @@ uint64_t TCRYPT_get_iv_offset(struct crypt_device *cd,
else if (params->mode && !strncmp(params->mode, "lrw", 3))
iv_offset = 0;
else
iv_offset = hdr->d.mk_offset / SECTOR_SIZE;
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_data_device(cd)));
iv_offset += crypt_dev_partition_offset(device_path(crypt_metadata_device(cd)));
return iv_offset;
}

View File

@@ -1,8 +1,8 @@
/*
* TCRYPT (TrueCrypt-compatible) header definition
*
* Copyright (C) 2012-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2021 Milan Broz
* Copyright (C) 2012-2019 Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2019 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -42,7 +42,6 @@
#define TCRYPT_LRW_IKEY_LEN 16
#define TCRYPT_KEY_POOL_LEN 64
#define VCRYPT_KEY_POOL_LEN 128
#define TCRYPT_KEYFILE_LEN 1048576
#define TCRYPT_HDR_FLAG_SYSTEM (1 << 0)
@@ -75,6 +74,7 @@ struct tcrypt_phdr {
struct crypt_device;
struct crypt_params_tcrypt;
struct crypt_dm_active_device;
struct dm_target;
struct volume_key;
struct device;

View File

@@ -3,8 +3,8 @@
*
* Copyright (C) 2004 Jana Saout <jana@saout.de>
* Copyright (C) 2004-2007 Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2021 Milan Broz
* Copyright (C) 2009-2019 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2019 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -23,6 +23,7 @@
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/resource.h>
#include <sys/stat.h>
@@ -129,7 +130,7 @@ static int keyfile_seek(int fd, uint64_t bytes)
if (errno == EINTR)
continue;
crypt_safe_memzero(tmp, sizeof(tmp));
crypt_memzero(tmp, sizeof(tmp));
/* read error */
return -1;
}
@@ -141,7 +142,7 @@ static int keyfile_seek(int fd, uint64_t bytes)
bytes -= bytes_r;
}
crypt_safe_memzero(tmp, sizeof(tmp));
crypt_memzero(tmp, sizeof(tmp));
return bytes == 0 ? 0 : -1;
}
@@ -171,7 +172,8 @@ int crypt_keyfile_device_read(struct crypt_device *cd, const char *keyfile,
if (isatty(fd)) {
log_err(cd, _("Cannot read keyfile from a terminal."));
goto out;
r = -EINVAL;
goto out_err;
}
/* If not requested otherwise, we limit input to prevent memory exhaustion */
@@ -179,7 +181,7 @@ int crypt_keyfile_device_read(struct crypt_device *cd, const char *keyfile,
key_size = DEFAULT_KEYFILE_SIZE_MAXKB * 1024 + 1;
unlimited_read = 1;
/* use 4k for buffer (page divisor but avoid huge pages) */
buflen = 4096 - sizeof(size_t); // sizeof(struct safe_allocation);
buflen = 4096 - sizeof(struct safe_allocation);
} else
buflen = key_size;
@@ -187,7 +189,7 @@ int crypt_keyfile_device_read(struct crypt_device *cd, const char *keyfile,
if (keyfile) {
if (stat(keyfile, &st) < 0) {
log_err(cd, _("Failed to stat key file."));
goto out;
goto out_err;
}
if (S_ISREG(st.st_mode)) {
regular_file = 1;
@@ -195,7 +197,7 @@ int crypt_keyfile_device_read(struct crypt_device *cd, const char *keyfile,
if (keyfile_offset > file_read_size) {
log_err(cd, _("Cannot seek to requested keyfile offset."));
goto out;
goto out_err;
}
file_read_size -= keyfile_offset;
@@ -210,13 +212,13 @@ int crypt_keyfile_device_read(struct crypt_device *cd, const char *keyfile,
pass = crypt_safe_alloc(buflen);
if (!pass) {
log_err(cd, _("Out of memory while reading passphrase."));
goto out;
goto out_err;
}
/* Discard keyfile_offset bytes on input */
if (keyfile_offset && keyfile_seek(fd, keyfile_offset) < 0) {
log_err(cd, _("Cannot seek to requested keyfile offset."));
goto out;
goto out_err;
}
for (i = 0, newline = 0; i < key_size; i += char_read) {
@@ -226,7 +228,7 @@ int crypt_keyfile_device_read(struct crypt_device *cd, const char *keyfile,
if (!pass) {
log_err(cd, _("Out of memory while reading passphrase."));
r = -ENOMEM;
goto out;
goto out_err;
}
}
@@ -246,7 +248,7 @@ int crypt_keyfile_device_read(struct crypt_device *cd, const char *keyfile,
if (char_read < 0) {
log_err(cd, _("Error reading passphrase."));
r = -EPIPE;
goto out;
goto out_err;
}
if (char_read == 0)
@@ -263,24 +265,24 @@ int crypt_keyfile_device_read(struct crypt_device *cd, const char *keyfile,
if (!i && !regular_file && !newline) {
log_err(cd, _("Nothing to read on input."));
r = -EPIPE;
goto out;
goto out_err;
}
/* Fail if we exceeded internal default (no specified size) */
if (unlimited_read && i == key_size) {
log_err(cd, _("Maximum keyfile size exceeded."));
goto out;
goto out_err;
}
if (!unlimited_read && i != key_size) {
log_err(cd, _("Cannot read requested amount of data."));
goto out;
goto out_err;
}
*key = pass;
*key_size_read = i;
r = 0;
out:
out_err:
if (fd != STDIN_FILENO)
close(fd);
@@ -317,7 +319,7 @@ int kernel_version(uint64_t *kversion)
}
if (!r)
*kversion = compact_version(maj, min, patch, rel);
*kversion = version(maj, min, patch, rel);
return r;
}

View File

@@ -1,8 +1,8 @@
/*
* libcryptsetup - cryptsetup library, cipher benchmark
*
* Copyright (C) 2012-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2021 Milan Broz
* Copyright (C) 2012-2019 Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2019 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -48,12 +48,6 @@ int crypt_benchmark(struct crypt_device *cd,
if (posix_memalign(&buffer, crypt_getpagesize(), buffer_size))
goto out;
r = crypt_cipher_ivsize(cipher, cipher_mode);
if (r >= 0 && iv_size != (size_t)r) {
log_dbg(cd, "IV length for benchmark adjusted to %i bytes (requested %zu).", r, iv_size);
iv_size = r;
}
if (iv_size) {
iv = malloc(iv_size);
if (!iv)
@@ -77,9 +71,9 @@ int crypt_benchmark(struct crypt_device *cd,
if (r == -ERANGE)
log_dbg(cd, "Measured cipher runtime is too low.");
else if (r)
log_dbg(cd, "Cannot initialize cipher %s, mode %s, key size %zu, IV size %zu.",
cipher, cipher_mode, volume_key_size, iv_size);
else if (r == -ENOTSUP || r == -ENOENT)
log_dbg(cd, "Cannot initialise cipher %s, mode %s.", cipher, cipher_mode);
out:
free(buffer);
free(key);
@@ -196,7 +190,7 @@ int crypt_benchmark_pbkdf_internal(struct crypt_device *cd,
PBKDF2_tmp = ((double)pbkdf->iterations * pbkdf->time_ms / 1000.);
if (PBKDF2_tmp > (double)UINT32_MAX)
return -EINVAL;
pbkdf->iterations = AT_LEAST((uint32_t)PBKDF2_tmp, pbkdf_limits.min_iterations);
pbkdf->iterations = at_least((uint32_t)PBKDF2_tmp, pbkdf_limits.min_iterations);
} else {
/* Already benchmarked */
if (pbkdf->iterations) {

View File

@@ -1,7 +1,7 @@
/*
* blkid probe utilities
*
* Copyright (C) 2018-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2018-2019 Red Hat, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -310,9 +310,9 @@ int blk_supported(void)
off_t blk_get_offset(struct blkid_handle *h)
{
const char *offset;
off_t offset_value = -1;
#ifdef HAVE_BLKID
const char *offset;
if (blk_is_superblock(h)) {
if (!blkid_probe_lookup_value(h->pr, "SBMAGIC_OFFSET", &offset, NULL))
offset_value = strtoll(offset, NULL, 10);

View File

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

View File

@@ -2,8 +2,8 @@
* utils_crypt - cipher utilities for cryptsetup
*
* Copyright (C) 2004-2007 Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2021 Milan Broz
* Copyright (C) 2009-2019 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2019 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,9 +23,6 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <ctype.h>
#include <errno.h>
#include "libcryptsetup.h"
@@ -79,16 +76,14 @@ int crypt_parse_hash_integrity_mode(const char *s, char *integrity)
return -EINVAL;
r = sscanf(s, "%" MAX_CIPHER_LEN_STR "[^-]-%" MAX_CIPHER_LEN_STR "s", mode, hash);
if (r == 2 && !isdigit(hash[0]))
if (r == 2)
r = snprintf(integrity, MAX_CIPHER_LEN, "%s(%s)", mode, hash);
else if (r == 2)
r = snprintf(integrity, MAX_CIPHER_LEN, "%s-%s", mode, hash);
else if (r == 1)
r = snprintf(integrity, MAX_CIPHER_LEN, "%s", mode);
else
return -EINVAL;
if (r < 0 || r >= MAX_CIPHER_LEN)
if (r < 0 || r == MAX_CIPHER_LEN)
return -EINVAL;
return 0;
@@ -102,6 +97,8 @@ int crypt_parse_integrity_mode(const char *s, char *integrity,
if (!s || !integrity)
return -EINVAL;
// FIXME: do not hardcode it here
/* AEAD modes */
if (!strcmp(s, "aead") ||
!strcmp(s, "poly1305") ||
@@ -152,6 +149,79 @@ int crypt_parse_pbkdf(const char *s, const char **pbkdf)
return 0;
}
/*
* 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)
{
#ifdef HAVE_EXPLICIT_BZERO
explicit_bzero(s, n);
#else
volatile uint8_t *p = (volatile uint8_t *)s;
while(n--)
*p++ = 0;
#endif
}
/* safe allocations */
void *crypt_safe_alloc(size_t size)
{
struct safe_allocation *alloc;
if (!size || size > (SIZE_MAX - offsetof(struct safe_allocation, data)))
return NULL;
alloc = malloc(size + offsetof(struct safe_allocation, data));
if (!alloc)
return NULL;
alloc->size = size;
crypt_memzero(&alloc->data, size);
/* coverity[leaked_storage] */
return &alloc->data;
}
void crypt_safe_free(void *data)
{
struct safe_allocation *alloc;
if (!data)
return;
alloc = (struct safe_allocation *)
((char *)data - offsetof(struct safe_allocation, data));
crypt_memzero(data, alloc->size);
alloc->size = 0x55aa55aa;
free(alloc);
}
void *crypt_safe_realloc(void *data, size_t size)
{
struct safe_allocation *alloc;
void *new_data;
new_data = crypt_safe_alloc(size);
if (new_data && data) {
alloc = (struct safe_allocation *)
((char *)data - offsetof(struct safe_allocation, data));
if (size > alloc->size)
size = alloc->size;
memcpy(new_data, data, size);
}
crypt_safe_free(data);
return new_data;
}
ssize_t crypt_hex_to_bytes(const char *hex, char **result, int safe_alloc)
{
char buf[3] = "xx\0", *endp, *bytes;
@@ -177,10 +247,3 @@ ssize_t crypt_hex_to_bytes(const char *hex, char **result, int safe_alloc)
*result = bytes;
return i;
}
bool crypt_is_cipher_null(const char *cipher_spec)
{
if (!cipher_spec)
return false;
return (strstr(cipher_spec, "cipher_null") || !strcmp(cipher_spec, "null"));
}

View File

@@ -2,8 +2,8 @@
* utils_crypt - cipher utilities for cryptsetup
*
* Copyright (C) 2004-2007 Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2021 Milan Broz
* Copyright (C) 2009-2019 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2019 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,12 +23,20 @@
#ifndef _UTILS_CRYPT_H
#define _UTILS_CRYPT_H
#include <stdbool.h>
#include <unistd.h>
#define MAX_CIPHER_LEN 32
#define MAX_CIPHER_LEN_STR "31"
#define MAX_KEYFILES 32
struct crypt_device;
/* Not to be used directly */
struct safe_allocation {
size_t size;
char data[0];
};
int crypt_parse_name_and_mode(const char *s, char *cipher,
int *key_nums, char *cipher_mode);
int crypt_parse_hash_integrity_mode(const char *s, char *integrity);
@@ -36,8 +44,12 @@ int crypt_parse_integrity_mode(const char *s, char *integrity,
int *integrity_key_size);
int crypt_parse_pbkdf(const char *s, const char **pbkdf);
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);
bool crypt_is_cipher_null(const char *cipher_spec);
#endif /* _UTILS_CRYPT_H */

View File

@@ -3,8 +3,8 @@
*
* Copyright (C) 2004 Jana Saout <jana@saout.de>
* Copyright (C) 2004-2007 Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2021 Milan Broz
* Copyright (C) 2009-2019 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2019 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -24,6 +24,7 @@
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -57,7 +58,6 @@ struct device {
/* cached values */
size_t alignment;
size_t block_size;
size_t loop_block_size;
};
static size_t device_fs_block_size_fd(int fd)
@@ -112,23 +112,6 @@ static size_t device_block_size_fd(int fd, size_t *min_size)
return bsize;
}
static size_t device_block_phys_size_fd(int fd)
{
struct stat st;
int arg;
size_t bsize = SECTOR_SIZE;
if (fstat(fd, &st) < 0)
return bsize;
if (S_ISREG(st.st_mode))
bsize = MAX_SECTOR_SIZE;
else if (ioctl(fd, BLKPBSZGET, &arg) >= 0)
bsize = (size_t)arg;
return bsize;
}
static size_t device_alignment_fd(int devfd)
{
long alignment = DEFAULT_MEM_ALIGNMENT;
@@ -162,7 +145,7 @@ static int device_read_test(int devfd)
if (read_blockwise(devfd, blocksize, alignment, buffer, minsize) == (ssize_t)minsize)
r = 0;
crypt_safe_memzero(buffer, sizeof(buffer));
crypt_memzero(buffer, sizeof(buffer));
return r;
}
@@ -180,9 +163,6 @@ static int device_ready(struct crypt_device *cd, struct device *device)
struct stat st;
size_t tmp_size;
if (!device)
return -EINVAL;
if (device->o_direct) {
log_dbg(cd, "Trying to open and read device %s with direct-io.",
device_path(device));
@@ -205,7 +185,7 @@ static int device_ready(struct crypt_device *cd, struct device *device)
}
if (devfd < 0) {
log_err(cd, _("Device %s does not exist or access denied."),
log_err(cd, _("Device %s doesn't exist or access denied."),
device_path(device));
return -EINVAL;
}
@@ -238,9 +218,6 @@ static int _open_locked(struct crypt_device *cd, struct device *device, int flag
{
int fd;
if (!device)
return -EINVAL;
log_dbg(cd, "Opening locked device %s", device_path(device));
if ((flags & O_ACCMODE) != O_RDONLY && device_locked_readonly(device->lh)) {
@@ -324,9 +301,6 @@ static int device_open_internal(struct crypt_device *cd, struct device *device,
int device_open(struct crypt_device *cd, struct device *device, int flags)
{
if (!device)
return -EINVAL;
assert(!device_locked(device->lh));
return device_open_internal(cd, device, flags);
}
@@ -381,9 +355,6 @@ void device_release_excl(struct crypt_device *cd, struct device *device)
int device_open_locked(struct crypt_device *cd, struct device *device, int flags)
{
if (!device)
return -EINVAL;
assert(!crypt_metadata_locking_enabled() || device_locked(device->lh));
return device_open_internal(cd, device, flags);
}
@@ -550,16 +521,10 @@ void device_topology_alignment(struct crypt_device *cd,
temp_alignment = (unsigned long)min_io_size;
/*
* Ignore bogus opt-io that could break alignment.
* Also real opt_io_size should be aligned to minimal page size (4k).
* Some bogus USB enclosures reports wrong data here.
*/
/* Ignore bogus opt-io that could break alignment */
if ((temp_alignment < (unsigned long)opt_io_size) &&
!((unsigned long)opt_io_size % temp_alignment) && !MISALIGNED_4K(opt_io_size))
!((unsigned long)opt_io_size % temp_alignment))
temp_alignment = (unsigned long)opt_io_size;
else if (opt_io_size && (opt_io_size != min_io_size))
log_err(cd, _("Ignoring bogus optimal-io size for data device (%u bytes)."), opt_io_size);
/* If calculated alignment is multiple of default, keep default */
if (temp_alignment && (default_alignment % temp_alignment))
@@ -593,42 +558,6 @@ size_t device_block_size(struct crypt_device *cd, struct device *device)
return device->block_size;
}
size_t device_optimal_encryption_sector_size(struct crypt_device *cd, struct device *device)
{
int fd;
size_t phys_block_size;
if (!device)
return SECTOR_SIZE;
fd = open(device->file_path ?: device->path, O_RDONLY);
if (fd < 0) {
log_dbg(cd, "Cannot get optimal encryption sector size for device %s.", device_path(device));
return SECTOR_SIZE;
}
/* cache device block size */
device->block_size = device_block_size_fd(fd, NULL);
if (!device->block_size) {
close(fd);
log_dbg(cd, "Cannot get block size for device %s.", device_path(device));
return SECTOR_SIZE;
}
if (device->block_size >= MAX_SECTOR_SIZE) {
close(fd);
return MISALIGNED(device->block_size, MAX_SECTOR_SIZE) ? SECTOR_SIZE : MAX_SECTOR_SIZE;
}
phys_block_size = device_block_phys_size_fd(fd);
close(fd);
if (device->block_size >= phys_block_size || phys_block_size <= SECTOR_SIZE || phys_block_size > MAX_SECTOR_SIZE || MISALIGNED(phys_block_size, device->block_size))
return device->block_size;
return phys_block_size;
}
int device_read_ahead(struct device *device, uint32_t *read_ahead)
{
int fd, r = 0;
@@ -655,11 +584,8 @@ int device_size(struct device *device, uint64_t *size)
struct stat st;
int devfd, r = -EINVAL;
if (!device)
return -EINVAL;
devfd = open(device->path, O_RDONLY);
if (devfd == -1)
if(devfd == -1)
return -EINVAL;
if (fstat(devfd, &st) < 0)
@@ -681,9 +607,6 @@ int device_fallocate(struct device *device, uint64_t size)
struct stat st;
int devfd, r = -EINVAL;
if (!device)
return -EINVAL;
devfd = open(device_path(device), O_RDWR);
if (devfd == -1)
return -EINVAL;
@@ -833,11 +756,10 @@ static int device_internal_prepare(struct crypt_device *cd, struct device *devic
return -ENOTSUP;
}
log_dbg(cd, "Allocating a free loop device (block size: %zu).",
device->loop_block_size ?: SECTOR_SIZE);
log_dbg(cd, "Allocating a free loop device.");
/* Keep the loop open, detached on last close. */
loop_fd = crypt_loop_attach(&loop_device, device->path, 0, 1, &readonly, device->loop_block_size);
loop_fd = crypt_loop_attach(&loop_device, device->path, 0, 1, &readonly);
if (loop_fd == -1) {
log_err(cd, _("Attaching loopback device failed "
"(loop device with autoclear flag is required)."));
@@ -856,8 +778,6 @@ static int device_internal_prepare(struct crypt_device *cd, struct device *devic
return r;
}
log_dbg(cd, "Attached loop device block size is %zu bytes.", device_block_size_fd(loop_fd, NULL));
device->loop_fd = loop_fd;
device->file_path = file_path;
device->init_done = 1;
@@ -927,30 +847,22 @@ size_t size_round_up(size_t size, size_t block)
void device_disable_direct_io(struct device *device)
{
if (device)
device->o_direct = 0;
device->o_direct = 0;
}
int device_direct_io(const struct device *device)
{
return device ? device->o_direct : 0;
return device->o_direct;
}
static int device_compare_path(const char *path1, const char *path2)
static dev_t device_devno(const struct device *device)
{
struct stat st_path1, st_path2;
struct stat st;
if (stat(path1, &st_path1 ) < 0 || stat(path2, &st_path2 ) < 0)
return -EINVAL;
if (stat(device->path, &st) || !S_ISBLK(st.st_mode))
return 0;
if (S_ISBLK(st_path1.st_mode) && S_ISBLK(st_path2.st_mode))
return (st_path1.st_rdev == st_path2.st_rdev) ? 1 : 0;
if (S_ISREG(st_path1.st_mode) && S_ISREG(st_path2.st_mode))
return (st_path1.st_ino == st_path2.st_ino &&
st_path1.st_dev == st_path2.st_dev) ? 1 : 0;
return 0;
return st.st_rdev;
}
int device_is_identical(struct device *device1, struct device *device2)
@@ -961,19 +873,21 @@ int device_is_identical(struct device *device1, struct device *device2)
if (device1 == device2)
return 1;
if (device1->init_done && device2->init_done)
return (device_devno(device1) == device_devno(device2));
else if (device1->init_done || device2->init_done)
return 0;
if (!strcmp(device_path(device1), device_path(device2)))
return 1;
return device_compare_path(device_path(device1), device_path(device2));
return 0;
}
int device_is_rotational(struct device *device)
{
struct stat st;
if (!device)
return -EINVAL;
if (stat(device_path(device), &st) < 0)
return -EINVAL;
@@ -987,9 +901,6 @@ size_t device_alignment(struct device *device)
{
int devfd;
if (!device)
return -EINVAL;
if (!device->alignment) {
devfd = open(device_path(device), O_RDONLY);
if (devfd != -1) {
@@ -1003,18 +914,17 @@ size_t device_alignment(struct device *device)
void device_set_lock_handle(struct device *device, struct crypt_lock_handle *h)
{
if (device)
device->lh = h;
device->lh = h;
}
struct crypt_lock_handle *device_get_lock_handle(struct device *device)
{
return device ? device->lh : NULL;
return device->lh;
}
int device_read_lock(struct crypt_device *cd, struct device *device)
{
if (!device || !crypt_metadata_locking_enabled())
if (!crypt_metadata_locking_enabled())
return 0;
if (device_read_lock_internal(cd, device))
@@ -1025,7 +935,7 @@ int device_read_lock(struct crypt_device *cd, struct device *device)
int device_write_lock(struct crypt_device *cd, struct device *device)
{
if (!device || !crypt_metadata_locking_enabled())
if (!crypt_metadata_locking_enabled())
return 0;
assert(!device_locked(device->lh) || !device_locked_readonly(device->lh));
@@ -1035,7 +945,7 @@ int device_write_lock(struct crypt_device *cd, struct device *device)
void device_read_unlock(struct crypt_device *cd, struct device *device)
{
if (!device || !crypt_metadata_locking_enabled())
if (!crypt_metadata_locking_enabled())
return;
assert(device_locked(device->lh));
@@ -1045,7 +955,7 @@ void device_read_unlock(struct crypt_device *cd, struct device *device)
void device_write_unlock(struct crypt_device *cd, struct device *device)
{
if (!device || !crypt_metadata_locking_enabled())
if (!crypt_metadata_locking_enabled())
return;
assert(device_locked(device->lh) && !device_locked_readonly(device->lh));
@@ -1077,11 +987,3 @@ void device_close(struct crypt_device *cd, struct device *device)
device->dev_fd = -1;
}
}
void device_set_block_size(struct device *device, size_t size)
{
if (!device)
return;
device->loop_block_size = size;
}

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