Import Upstream version 2.2.2

This commit is contained in:
openKylinBot 2022-05-13 20:07:59 +08:00
commit 931508c8db
356 changed files with 149969 additions and 0 deletions

55
.gitignore vendored Normal file
View File

@ -0,0 +1,55 @@
po/*gmo
*~
Makefile
Makefile.in
Makefile.in.in
*.lo
*.la
*.o
**/*.dirstamp
.deps/
.libs/
src/cryptsetup
src/veritysetup
ABOUT-NLS
aclocal.m4
autom4te.cache/
compile
config.guess
config.h
config.h.in
config.log
config.rpath
config.status
config.sub
configure
cryptsetup
cryptsetup-reencrypt
depcomp
install-sh
integritysetup
lib/libcryptsetup.pc
libtool
ltmain.sh
m4/
missing
po/Makevars.template
po/POTFILES
po/Rules-quot
po/*.header
po/*.sed
po/*.sin
po/stamp-po
scripts/cryptsetup.conf
stamp-h1
veritysetup
tests/valglog.*
*/*.dirstamp
*-debug-luks2-backup*
tests/api-test
tests/api-test-2
tests/differ
tests/luks1-images
tests/tcrypt-images
tests/unit-utils-io
tests/vectors-test

160
.travis-functions.sh Normal file
View File

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

40
.travis.yml Normal file
View File

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

4
AUTHORS Normal file
View File

@ -0,0 +1,4 @@
Jana Saout <jana@saout.de>
Clemens Fruhwirth <clemens@endorphin.org>
Milan Broz <gmazyland@gmail.com>
Ondrej Kozina <okozina@redhat.com>

354
COPYING Normal file
View File

@ -0,0 +1,354 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.
-----
In addition, as a special exception, the copyright holders give
permission to link the code of portions of this program with the
OpenSSL library under certain conditions as described in each
individual source file, and distribute linked combinations
including the two.
You must obey the GNU General Public License in all respects
for all of the code used other than OpenSSL. If you modify
file(s) with this exception, you may extend this exception to your
version of the file(s), but you are not obligated to do so. If you
do not wish to do so, delete this exception statement from your
version. If you delete this exception statement from all source
files in the program, then also delete it here.

517
COPYING.LGPL Normal file
View File

@ -0,0 +1,517 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library 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 library 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 library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!
-----
In addition, as a special exception, the copyright holders give
permission to link the code of portions of this program with the
OpenSSL library under certain conditions as described in each
individual source file, and distribute linked combinations
including the two.
You must obey the GNU Lesser General Public License in all respects
for all of the code used other than OpenSSL. If you modify
file(s) with this exception, you may extend this exception to your
version of the file(s), but you are not obligated to do so. If you
do not wish to do so, delete this exception statement from your
version. If you delete this exception statement from all source
files in the program, then also delete it here.

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

2807
FAQ Normal file

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.

50
Makefile.am Normal file
View File

@ -0,0 +1,50 @@
EXTRA_DIST = COPYING.LGPL FAQ docs misc
SUBDIRS = po tests
CLEANFILES =
DISTCLEAN_TARGETS =
AM_CPPFLAGS = \
-include config.h \
-I$(top_srcdir)/lib \
-DDATADIR=\""$(datadir)"\" \
-DLOCALEDIR=\""$(datadir)/locale"\" \
-DLIBDIR=\""$(libdir)"\" \
-DPREFIX=\""$(prefix)"\" \
-DSYSCONFDIR=\""$(sysconfdir)"\" \
-DVERSION=\""$(VERSION)"\"
AM_CFLAGS = -Wall
AM_LDFLAGS =
LDADD = $(LTLIBINTL) -lm
tmpfilesddir = @DEFAULT_TMPFILESDIR@
noinst_LTLIBRARIES =
sbin_PROGRAMS =
man8_MANS =
tmpfilesd_DATA =
include man/Makemodule.am
include scripts/Makemodule.am
if CRYPTO_INTERNAL_ARGON2
include lib/crypto_backend/argon2/Makemodule.am
endif
include lib/crypto_backend/Makemodule.am
include lib/Makemodule.am
include src/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
distclean-local:
-find . -name \*~ -o -name \*.orig -o -name \*.rej | xargs rm -f
rm -rf autom4te.cache
clean-local:
-rm -rf docs/doxygen_api_docs libargon2.la

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

83
README.md Normal file
View File

@ -0,0 +1,83 @@
![LUKS logo](https://gitlab.com/cryptsetup/cryptsetup/wikis/luks-logo.png)
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**
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, since version 2.0, **integritysetup** to setup
[DMIntegrity](https://gitlab.com/cryptsetup/cryptsetup/wikis/DMIntegrity) block integrity kernel module.
LUKS Design
-----------
**LUKS** is the standard for Linux hard disk encryption. By providing a standard on-disk-format, it does not
only facilitate compatibility among distributions, but also provides secure management of multiple user passwords.
LUKS stores all necessary setup information in the partition header, enabling to transport or migrate data seamlessly.
Last version of the LUKS2 format specification is
[available here](https://gitlab.com/cryptsetup/LUKS2-docs).
Last version of the LUKS1 format specification is
[available here](https://www.kernel.org/pub/linux/utils/cryptsetup/LUKS_docs/on-disk-format.pdf).
Why LUKS?
---------
* compatibility via standardization,
* secure against low entropy attacks,
* support for multiple keys,
* effective passphrase revocation,
* free.
[Project home page](https://gitlab.com/cryptsetup/cryptsetup/).
-----------------
[Frequently asked questions (FAQ)](https://gitlab.com/cryptsetup/cryptsetup/wikis/FrequentlyAskedQuestions)
--------------------------------
Download
--------
All release tarballs and release notes are hosted on [kernel.org](https://www.kernel.org/pub/linux/utils/cryptsetup/).
**The latest cryptsetup version is 2.2.1**
* [cryptsetup-2.2.1.tar.xz](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.2/cryptsetup-2.2.1.tar.xz)
* Signature [cryptsetup-2.2.1.tar.sign](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.2/cryptsetup-2.2.1.tar.sign)
_(You need to decompress file first to check signature.)_
* [Cryptsetup 2.2.1 Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.2/v2.2.1-ReleaseNotes).
Previous versions
* [Version 2.2.0](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.2/cryptsetup-2.2.0.tar.xz) -
[Signature](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.2/cryptsetup-2.2.0.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).
* [Version 1.7.5](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.7/cryptsetup-1.7.5.tar.xz) -
[Signature](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.7/cryptsetup-1.7.5.tar.sign) -
[Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.7/v1.7.5-ReleaseNotes).
Source and API docs
-------------------
For development version code, please refer to [source](https://gitlab.com/cryptsetup/cryptsetup/tree/master) page,
mirror on [kernel.org](https://git.kernel.org/cgit/utils/cryptsetup/cryptsetup.git/) or [GitHub](https://github.com/mbroz/cryptsetup).
For libcryptsetup documentation see [libcryptsetup API](https://mbroz.fedorapeople.org/libcryptsetup_API/) page.
The libcryptsetup API/ABI changes are tracked in [compatibility report](https://abi-laboratory.pro/tracker/timeline/cryptsetup/).
NLS PO files are maintained by [TranslationProject](http://translationproject.org/domain/cryptsetup.html).
Help!
-----
Please always read [FAQ](https://gitlab.com/cryptsetup/cryptsetup/wikis/FrequentlyAskedQuestions) first.
For cryptsetup and LUKS related questions, please use the dm-crypt mailing list, [dm-crypt@saout.de](mailto:dm-crypt@saout.de).
If you want to subscribe just send an empty mail to [dm-crypt-subscribe@saout.de](mailto:dm-crypt-subscribe@saout.de).
You can also browse [list archive](http://www.saout.de/pipermail/dm-crypt/) or read it through
[web interface](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.

79
autogen.sh Executable file
View File

@ -0,0 +1,79 @@
#!/bin/sh
# Run this to generate all the initial makefiles, etc.
srcdir=`dirname $0`
PKG_NAME="cryptsetup"
DIE=0
(autopoint --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "**Error**: You must have autopoint installed."
echo "Download the appropriate package for your distribution,"
echo "or see http://www.gnu.org/software/gettext"
DIE=1
}
(autoconf --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "**Error**: You must have autoconf installed to."
echo "Download the appropriate package for your distribution,"
echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
DIE=1
}
(grep "^AM_PROG_LIBTOOL" $srcdir/configure.ac >/dev/null) && {
(libtool --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "**Error**: You must have libtool installed."
echo "Get ftp://ftp.gnu.org/pub/gnu/"
echo "(or a newer version if it is available)"
DIE=1
}
}
(automake --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "**Error**: You must have automake installed."
echo "Get ftp://ftp.gnu.org/pub/gnu/"
echo "(or a newer version if it is available)"
DIE=1
NO_AUTOMAKE=yes
}
# if no automake, don't bother testing for aclocal
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
}
if test "$DIE" -eq 1; then
exit 1
fi
echo
echo "Generate build-system by:"
echo " autopoint: $(autopoint --version | head -1)"
echo " aclocal: $(aclocal --version | head -1)"
echo " autoconf: $(autoconf --version | head -1)"
echo " automake: $(automake --version | head -1)"
echo " libtoolize: $(libtoolize --version | head -1)"
echo
set -e
autopoint --force $AP_OPTS
libtoolize --force --copy
aclocal -I m4 $AL_OPTS
autoheader $AH_OPTS
automake --add-missing --copy --gnu $AM_OPTS
autoconf $AC_OPTS
echo
echo "Now type '$srcdir/configure' and 'make' to compile."
echo

639
configure.ac Normal file
View File

@ -0,0 +1,639 @@
AC_PREREQ([2.67])
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=17:0:5
AM_SILENT_RULES([yes])
AC_CONFIG_SRCDIR(src/cryptsetup.c)
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_HEADERS([config.h:config.h.in])
# We do not want to run test in parallel. Really.
# http://lists.gnu.org/archive/html/automake/2013-01/msg00060.html
# For old automake use this
#AM_INIT_AUTOMAKE(dist-xz subdir-objects)
AM_INIT_AUTOMAKE([dist-xz 1.12 serial-tests subdir-objects])
if test "x$prefix" = "xNONE"; then
sysconfdir=/etc
fi
AC_PREFIX_DEFAULT(/usr)
AC_CANONICAL_HOST
AC_USE_SYSTEM_EXTENSIONS
AC_PROG_CC
AM_PROG_CC_C_O
AC_PROG_CPP
AC_PROG_INSTALL
AC_PROG_MAKE_SET
AC_ENABLE_STATIC(no)
LT_INIT
PKG_PROG_PKG_CONFIG
dnl ==========================================================================
dnl define PKG_CHECK_VAR for old pkg-config <= 0.28
m4_ifndef([AS_VAR_COPY],
[m4_define([AS_VAR_COPY],
[AS_LITERAL_IF([$1[]$2], [$1=$$2], [eval $1=\$$2])])
])
m4_ifndef([PKG_CHECK_VAR], [
AC_DEFUN([PKG_CHECK_VAR],
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])
_PKG_CONFIG([$1], [variable="][$3]["], [$2])
AS_VAR_COPY([$1], [pkg_cv_][$1])
AS_VAR_IF([$1], [""], [$5], [$4])
])
])
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_HEADERS(uuid/uuid.h,,[AC_MSG_ERROR([You need the uuid library.])])
AC_CHECK_HEADER(libdevmapper.h,,[AC_MSG_ERROR([You need the device-mapper library.])])
AC_ARG_ENABLE([keyring],
AS_HELP_STRING([--disable-keyring], [disable kernel keyring support and builtin kernel keyring token]),
[], [enable_keyring=yes])
if test "x$enable_keyring" = "xyes"; then
AC_CHECK_HEADERS(linux/keyctl.h,,[AC_MSG_ERROR([You need Linux kernel headers with kernel keyring service compiled.])])
dnl ==========================================================================
dnl check whether kernel is compiled with kernel keyring service syscalls
AC_CHECK_DECL(__NR_add_key,,[AC_MSG_ERROR([The kernel is missing add_key syscall.])], [#include <syscall.h>])
AC_CHECK_DECL(__NR_keyctl,,[AC_MSG_ERROR([The kernel is missing keyctl syscall.])], [#include <syscall.h>])
AC_CHECK_DECL(__NR_request_key,,[AC_MSG_ERROR([The kernel is missing request_key syscall.])], [#include <syscall.h>])
dnl ==========================================================================
dnl check that key_serial_t hasn't been adopted yet in stdlib
AC_CHECK_TYPES([key_serial_t], [], [], [
AC_INCLUDES_DEFAULT
#ifdef HAVE_LINUX_KEYCTL_H
# include <linux/keyctl.h>
#endif
])
AC_DEFINE(KERNEL_KEYRING, 1, [Enable kernel keyring service support])
fi
AM_CONDITIONAL(KERNEL_KEYRING, test "x$enable_keyring" = "xyes")
saved_LIBS=$LIBS
AC_CHECK_LIB(uuid, uuid_clear, ,[AC_MSG_ERROR([You need the uuid library.])])
AC_SUBST(UUID_LIBS, $LIBS)
LIBS=$saved_LIBS
AC_SEARCH_LIBS([clock_gettime],[rt posix4])
AC_CHECK_FUNCS([posix_memalign clock_gettime posix_fallocate explicit_bzero])
if test "x$enable_largefile" = "xno"; then
AC_MSG_ERROR([Building with --disable-largefile is not supported, it can cause data corruption.])
fi
AC_C_CONST
AC_C_BIGENDIAN
AC_TYPE_OFF_T
AC_SYS_LARGEFILE
AC_FUNC_FSEEKO
AC_PROG_GCC_TRADITIONAL
AC_FUNC_STRERROR_R
dnl ==========================================================================
AM_GNU_GETTEXT([external],[need-ngettext])
AM_GNU_GETTEXT_VERSION([0.18.3])
dnl ==========================================================================
saved_LIBS=$LIBS
AC_CHECK_LIB(popt, poptConfigFileToString,,
[AC_MSG_ERROR([You need popt 1.7 or newer to compile.])])
AC_SUBST(POPT_LIBS, $LIBS)
LIBS=$saved_LIBS
dnl ==========================================================================
dnl FIPS extensions
AC_ARG_ENABLE([fips],
AS_HELP_STRING([--enable-fips], [enable FIPS mode restrictions]))
if test "x$enable_fips" = "xyes"; then
AC_DEFINE(ENABLE_FIPS, 1, [Enable FIPS mode restrictions])
if test "x$enable_static" = "xyes" -o "x$enable_static_cryptsetup" = "xyes" ; then
AC_MSG_ERROR([Static build is not compatible with FIPS.])
fi
fi
AC_DEFUN([NO_FIPS], [
if test "x$enable_fips" = "xyes"; then
AC_MSG_ERROR([This option is not compatible with FIPS.])
fi
])
dnl ==========================================================================
dnl pwquality library (cryptsetup CLI only)
AC_ARG_ENABLE([pwquality],
AS_HELP_STRING([--enable-pwquality], [enable password quality checking using pwquality library]))
if test "x$enable_pwquality" = "xyes"; then
AC_DEFINE(ENABLE_PWQUALITY, 1, [Enable password quality checking using pwquality library])
PKG_CHECK_MODULES([PWQUALITY], [pwquality >= 1.0.0],,
AC_MSG_ERROR([You need pwquality library.]))
dnl FIXME: this is really hack for now
PWQUALITY_STATIC_LIBS="$PWQUALITY_LIBS -lcrack -lz"
fi
dnl ==========================================================================
dnl passwdqc library (cryptsetup CLI only)
AC_ARG_ENABLE([passwdqc],
AS_HELP_STRING([--enable-passwdqc@<:@=CONFIG_PATH@:>@],
[enable password quality checking using passwdqc library (optionally with CONFIG_PATH)]))
case "$enable_passwdqc" in
""|yes|no) use_passwdqc_config="" ;;
/*) use_passwdqc_config="$enable_passwdqc"; enable_passwdqc=yes ;;
*) AC_MSG_ERROR([Unrecognized --enable-passwdqc parameter.]) ;;
esac
AC_DEFINE_UNQUOTED([PASSWDQC_CONFIG_FILE], ["$use_passwdqc_config"], [passwdqc library config file])
if test "x$enable_passwdqc" = "xyes"; then
AC_DEFINE(ENABLE_PASSWDQC, 1, [Enable password quality checking using passwdqc library])
PASSWDQC_LIBS="-lpasswdqc"
fi
if test "x$enable_pwquality$enable_passwdqc" = "xyesyes"; then
AC_MSG_ERROR([--enable-pwquality and --enable-passwdqc are mutually incompatible.])
fi
dnl ==========================================================================
dnl Crypto backend functions
AC_DEFUN([CONFIGURE_GCRYPT], [
if test "x$enable_fips" = "xyes"; then
GCRYPT_REQ_VERSION=1.4.5
else
GCRYPT_REQ_VERSION=1.1.42
fi
dnl libgcrypt rejects to use pkgconfig, use AM_PATH_LIBGCRYPT from gcrypt-devel here.
dnl Do not require gcrypt-devel if other crypto backend is used.
m4_ifdef([AM_PATH_LIBGCRYPT],[
AC_ARG_ENABLE([gcrypt-pbkdf2],
dnl Check if we can use gcrypt PBKDF2 (1.6.0 supports empty password)
AS_HELP_STRING([--enable-gcrypt-pbkdf2], [force enable internal gcrypt PBKDF2]),
if test "x$enableval" = "xyes"; then
[use_internal_pbkdf2=0]
else
[use_internal_pbkdf2=1]
fi,
[AM_PATH_LIBGCRYPT([1.6.1], [use_internal_pbkdf2=0], [use_internal_pbkdf2=1])])
AM_PATH_LIBGCRYPT($GCRYPT_REQ_VERSION,,[AC_MSG_ERROR([You need the gcrypt library.])])],
AC_MSG_ERROR([Missing support for gcrypt: install gcrypt and regenerate configure.]))
AC_MSG_CHECKING([if internal cryptsetup PBKDF2 is compiled-in])
if test $use_internal_pbkdf2 = 0; then
AC_MSG_RESULT([no])
else
AC_MSG_RESULT([yes])
NO_FIPS([])
fi
AC_CHECK_DECLS([GCRY_CIPHER_MODE_XTS], [], [], [#include <gcrypt.h>])
if test "x$enable_static_cryptsetup" = "xyes"; then
saved_LIBS=$LIBS
LIBS="$saved_LIBS $LIBGCRYPT_LIBS -static"
AC_CHECK_LIB(gcrypt, gcry_check_version,,
AC_MSG_ERROR([Cannot find static gcrypt library.]),
[-lgpg-error])
LIBGCRYPT_STATIC_LIBS="$LIBGCRYPT_LIBS -lgpg-error"
LIBS=$saved_LIBS
fi
CRYPTO_CFLAGS=$LIBGCRYPT_CFLAGS
CRYPTO_LIBS=$LIBGCRYPT_LIBS
CRYPTO_STATIC_LIBS=$LIBGCRYPT_STATIC_LIBS
AC_DEFINE_UNQUOTED(GCRYPT_REQ_VERSION, ["$GCRYPT_REQ_VERSION"], [Requested gcrypt version])
])
AC_DEFUN([CONFIGURE_OPENSSL], [
PKG_CHECK_MODULES([OPENSSL], [openssl >= 0.9.8],,
AC_MSG_ERROR([You need openssl library.]))
CRYPTO_CFLAGS=$OPENSSL_CFLAGS
CRYPTO_LIBS=$OPENSSL_LIBS
use_internal_pbkdf2=0
if test "x$enable_static_cryptsetup" = "xyes"; then
saved_PKG_CONFIG=$PKG_CONFIG
PKG_CONFIG="$PKG_CONFIG --static"
PKG_CHECK_MODULES([OPENSSL_STATIC], [openssl])
CRYPTO_STATIC_LIBS=$OPENSSL_STATIC_LIBS
PKG_CONFIG=$saved_PKG_CONFIG
fi
])
AC_DEFUN([CONFIGURE_NSS], [
if test "x$enable_static_cryptsetup" = "xyes"; then
AC_MSG_ERROR([Static build of cryptsetup is not supported with NSS.])
fi
AC_MSG_WARN([NSS backend does NOT provide backward compatibility (missing ripemd160 hash).])
PKG_CHECK_MODULES([NSS], [nss],,
AC_MSG_ERROR([You need nss library.]))
saved_CFLAGS=$CFLAGS
CFLAGS="$CFLAGS $NSS_CFLAGS"
AC_CHECK_DECLS([NSS_GetVersion], [], [], [#include <nss.h>])
CFLAGS=$saved_CFLAGS
CRYPTO_CFLAGS=$NSS_CFLAGS
CRYPTO_LIBS=$NSS_LIBS
use_internal_pbkdf2=1
NO_FIPS([])
])
AC_DEFUN([CONFIGURE_KERNEL], [
AC_CHECK_HEADERS(linux/if_alg.h,,
[AC_MSG_ERROR([You need Linux kernel headers with userspace crypto interface.])])
# AC_CHECK_DECLS([AF_ALG],,
# [AC_MSG_ERROR([You need Linux kernel with userspace crypto interface.])],
# [#include <sys/socket.h>])
use_internal_pbkdf2=1
NO_FIPS([])
])
AC_DEFUN([CONFIGURE_NETTLE], [
AC_CHECK_HEADERS(nettle/sha.h,,
[AC_MSG_ERROR([You need Nettle cryptographic library.])])
AC_CHECK_HEADERS(nettle/version.h)
saved_LIBS=$LIBS
AC_CHECK_LIB(nettle, nettle_pbkdf2_hmac_sha256,,
[AC_MSG_ERROR([You need Nettle library version 2.6 or more recent.])])
CRYPTO_LIBS=$LIBS
LIBS=$saved_LIBS
CRYPTO_STATIC_LIBS=$CRYPTO_LIBS
use_internal_pbkdf2=0
NO_FIPS([])
])
dnl ==========================================================================
saved_LIBS=$LIBS
AC_ARG_ENABLE([static-cryptsetup],
AS_HELP_STRING([--enable-static-cryptsetup], [enable build of static version of tools]))
if test "x$enable_static_cryptsetup" = "xyes"; then
if test "x$enable_static" = "xno"; then
AC_MSG_WARN([Requested static cryptsetup build, enabling static library.])
enable_static=yes
fi
fi
AM_CONDITIONAL(STATIC_TOOLS, test "x$enable_static_cryptsetup" = "xyes")
AC_ARG_ENABLE([cryptsetup],
AS_HELP_STRING([--disable-cryptsetup], [disable cryptsetup support]),
[], [enable_cryptsetup=yes])
AM_CONDITIONAL(CRYPTSETUP, test "x$enable_cryptsetup" = "xyes")
AC_ARG_ENABLE([veritysetup],
AS_HELP_STRING([--disable-veritysetup], [disable veritysetup support]),
[], [enable_veritysetup=yes])
AM_CONDITIONAL(VERITYSETUP, test "x$enable_veritysetup" = "xyes")
AC_ARG_ENABLE([cryptsetup-reencrypt],
AS_HELP_STRING([--disable-cryptsetup-reencrypt], [disable cryptsetup-reencrypt tool]),
[], [enable_cryptsetup_reencrypt=yes])
AM_CONDITIONAL(REENCRYPT, test "x$enable_cryptsetup_reencrypt" = "xyes")
AC_ARG_ENABLE([integritysetup],
AS_HELP_STRING([--disable-integritysetup], [disable integritysetup support]),
[], [enable_integritysetup=yes])
AM_CONDITIONAL(INTEGRITYSETUP, test "x$enable_integritysetup" = "xyes")
AC_ARG_ENABLE([selinux],
AS_HELP_STRING([--disable-selinux], [disable selinux support [default=auto]]),
[], [enable_selinux=yes])
AC_ARG_ENABLE([udev],
AS_HELP_STRING([--disable-udev], [disable udev support]),
[], [enable_udev=yes])
dnl Try to use pkg-config for devmapper, but fallback to old detection
PKG_CHECK_MODULES([DEVMAPPER], [devmapper >= 1.02.03],, [
AC_CHECK_LIB(devmapper, dm_task_set_name,,
[AC_MSG_ERROR([You need the device-mapper library.])])
AC_CHECK_LIB(devmapper, dm_task_set_message,,
[AC_MSG_ERROR([The device-mapper library on your system is too old.])])
DEVMAPPER_LIBS=$LIBS
])
LIBS=$saved_LIBS
LIBS="$LIBS $DEVMAPPER_LIBS"
AC_CHECK_DECLS([dm_task_secure_data], [], [], [#include <libdevmapper.h>])
AC_CHECK_DECLS([dm_task_retry_remove], [], [], [#include <libdevmapper.h>])
AC_CHECK_DECLS([dm_task_deferred_remove], [], [], [#include <libdevmapper.h>])
AC_CHECK_DECLS([dm_device_has_mounted_fs], [], [], [#include <libdevmapper.h>])
AC_CHECK_DECLS([dm_device_has_holders], [], [], [#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
if test "x$have_cookie" = xno; then
AC_MSG_WARN([The device-mapper library on your system has no udev support, udev support disabled.])
else
AC_DEFINE(USE_UDEV, 1, [Try to use udev synchronisation?])
fi
fi
LIBS=$saved_LIBS
dnl Check for JSON-C used in LUKS2
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 Crypto backend configuration.
AC_ARG_WITH([crypto_backend],
AS_HELP_STRING([--with-crypto_backend=BACKEND], [crypto backend (gcrypt/openssl/nss/kernel/nettle) [openssl]]),
[], [with_crypto_backend=openssl])
dnl Kernel crypto API backend needed for benchmark and tcrypt
AC_ARG_ENABLE([kernel_crypto],
AS_HELP_STRING([--disable-kernel_crypto], [disable kernel userspace crypto (no benchmark and tcrypt)]),
[], [enable_kernel_crypto=yes])
if test "x$enable_kernel_crypto" = "xyes"; then
AC_CHECK_HEADERS(linux/if_alg.h,,
[AC_MSG_ERROR([You need Linux kernel headers with userspace crypto interface. (Or use --disable-kernel_crypto.)])])
AC_DEFINE(ENABLE_AF_ALG, 1, [Enable using of kernel userspace crypto])
fi
case $with_crypto_backend in
gcrypt) CONFIGURE_GCRYPT([]) ;;
openssl) CONFIGURE_OPENSSL([]) ;;
nss) CONFIGURE_NSS([]) ;;
kernel) CONFIGURE_KERNEL([]) ;;
nettle) CONFIGURE_NETTLE([]) ;;
*) AC_MSG_ERROR([Unknown crypto backend.]) ;;
esac
AM_CONDITIONAL(CRYPTO_BACKEND_GCRYPT, test "$with_crypto_backend" = "gcrypt")
AM_CONDITIONAL(CRYPTO_BACKEND_OPENSSL, test "$with_crypto_backend" = "openssl")
AM_CONDITIONAL(CRYPTO_BACKEND_NSS, test "$with_crypto_backend" = "nss")
AM_CONDITIONAL(CRYPTO_BACKEND_KERNEL, test "$with_crypto_backend" = "kernel")
AM_CONDITIONAL(CRYPTO_BACKEND_NETTLE, test "$with_crypto_backend" = "nettle")
AM_CONDITIONAL(CRYPTO_INTERNAL_PBKDF2, test $use_internal_pbkdf2 = 1)
AC_DEFINE_UNQUOTED(USE_INTERNAL_PBKDF2, [$use_internal_pbkdf2], [Use internal PBKDF2])
dnl Argon2 implementation
AC_ARG_ENABLE([internal-argon2],
AS_HELP_STRING([--disable-internal-argon2], [disable internal implementation of Argon2 PBKDF]),
[], [enable_internal_argon2=yes])
AC_ARG_ENABLE([libargon2],
AS_HELP_STRING([--enable-libargon2], [enable external libargon2 (PHC) library (disables internal bundled version)]))
if test "x$enable_libargon2" = "xyes" ; then
AC_CHECK_HEADERS(argon2.h,,
[AC_MSG_ERROR([You need libargon2 development library installed.])])
AC_CHECK_DECL(Argon2_id,,[AC_MSG_ERROR([You need more recent Argon2 library with support for Argon2id.])], [#include <argon2.h>])
PKG_CHECK_MODULES([LIBARGON2], [libargon2],,[LIBARGON2_LIBS="-largon2"])
enable_internal_argon2=no
else
AC_MSG_WARN([Argon2 bundled (slow) reference implementation will be used, please consider to use system library with --enable-libargon2.])
AC_ARG_ENABLE([internal-sse-argon2],
AS_HELP_STRING([--enable-internal-sse-argon2], [enable internal SSE implementation of Argon2 PBKDF]))
if test "x$enable_internal_sse_argon2" = "xyes"; then
AC_MSG_CHECKING(if Argon2 SSE optimization can be used)
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#include <emmintrin.h>
__m128i testfunc(__m128i *a, __m128i *b) {
return _mm_xor_si128(_mm_loadu_si128(a), _mm_loadu_si128(b));
}
]])],,[enable_internal_sse_argon2=no])
AC_MSG_RESULT($enable_internal_sse_argon2)
fi
fi
if test "x$enable_internal_argon2" = "xyes"; then
AC_DEFINE(USE_INTERNAL_ARGON2, 1, [Use internal Argon2])
fi
AM_CONDITIONAL(CRYPTO_INTERNAL_ARGON2, test "x$enable_internal_argon2" = "xyes")
AM_CONDITIONAL(CRYPTO_INTERNAL_SSE_ARGON2, test "x$enable_internal_sse_argon2" = "xyes")
dnl Link with blkid to check for other device types
AC_ARG_ENABLE([blkid],
AS_HELP_STRING([--disable-blkid], [disable use of blkid for device signature detection and wiping]),
[], [enable_blkid=yes])
if test "x$enable_blkid" = "xyes"; then
PKG_CHECK_MODULES([BLKID], [blkid],[AC_DEFINE([HAVE_BLKID], 1, [Define to 1 to use blkid for detection of disk signatures.])],[LIBBLKID_LIBS="-lblkid"])
AC_CHECK_HEADERS(blkid/blkid.h,,[AC_MSG_ERROR([You need blkid development library installed.])])
AC_CHECK_DECL([blkid_do_wipe],
[ AC_DEFINE([HAVE_BLKID_WIPE], 1, [Define to 1 to use blkid_do_wipe.])
enable_blkid_wipe=yes
],,
[#include <blkid/blkid.h>])
AC_CHECK_DECL([blkid_probe_step_back],
[ AC_DEFINE([HAVE_BLKID_STEP_BACK], 1, [Define to 1 to use blkid_probe_step_back.])
enable_blkid_step_back=yes
],,
[#include <blkid/blkid.h>])
AC_CHECK_DECLS([ blkid_reset_probe,
blkid_probe_set_device,
blkid_probe_filter_superblocks_type,
blkid_do_safeprobe,
blkid_do_probe,
blkid_probe_lookup_value
],,
[AC_MSG_ERROR([Can not compile with blkid support, disable it by --disable-blkid.])],
[#include <blkid/blkid.h>])
fi
AM_CONDITIONAL(HAVE_BLKID, test "x$enable_blkid" = "xyes")
AM_CONDITIONAL(HAVE_BLKID_WIPE, test "x$enable_blkid_wipe" = "xyes")
AM_CONDITIONAL(HAVE_BLKID_STEP_BACK, test "x$enable_blkid_step_back" = "xyes")
dnl Magic for cryptsetup.static build.
if test "x$enable_static_cryptsetup" = "xyes"; then
saved_PKG_CONFIG=$PKG_CONFIG
PKG_CONFIG="$PKG_CONFIG --static"
LIBS="$saved_LIBS -static"
AC_CHECK_LIB(popt, poptGetContext,,
AC_MSG_ERROR([Cannot find static popt library.]))
dnl Try to detect needed device-mapper static libraries, try pkg-config first.
LIBS="$saved_LIBS -static"
PKG_CHECK_MODULES([DEVMAPPER_STATIC], [devmapper >= 1.02.27],,[
DEVMAPPER_STATIC_LIBS=$DEVMAPPER_LIBS
if test "x$enable_selinux" = "xyes"; then
AC_CHECK_LIB(sepol, sepol_bool_set)
AC_CHECK_LIB(selinux, is_selinux_enabled)
DEVMAPPER_STATIC_LIBS="$DEVMAPPER_STATIC_LIBS $LIBS"
fi
])
LIBS="$saved_LIBS $DEVMAPPER_STATIC_LIBS"
AC_CHECK_LIB(devmapper, dm_task_set_uuid,,
AC_MSG_ERROR([Cannot link with static device-mapper library.]))
dnl Try to detect uuid static library.
LIBS="$saved_LIBS -static"
AC_CHECK_LIB(uuid, uuid_generate,,
AC_MSG_ERROR([Cannot find static uuid library.]))
LIBS=$saved_LIBS
PKG_CONFIG=$saved_PKG_CONFIG
fi
AC_MSG_CHECKING([for systemd tmpfiles config directory])
PKG_CHECK_VAR([systemd_tmpfilesdir], [systemd], [tmpfilesdir], [], [systemd_tmpfilesdir=no])
AC_MSG_RESULT([$systemd_tmpfilesdir])
AC_SUBST([DEVMAPPER_LIBS])
AC_SUBST([DEVMAPPER_STATIC_LIBS])
AC_SUBST([PWQUALITY_LIBS])
AC_SUBST([PWQUALITY_STATIC_LIBS])
AC_SUBST([PASSWDQC_LIBS])
AC_SUBST([CRYPTO_CFLAGS])
AC_SUBST([CRYPTO_LIBS])
AC_SUBST([CRYPTO_STATIC_LIBS])
AC_SUBST([JSON_C_LIBS])
AC_SUBST([LIBARGON2_LIBS])
AC_SUBST([BLKID_LIBS])
AC_SUBST([LIBCRYPTSETUP_VERSION])
AC_SUBST([LIBCRYPTSETUP_VERSION_INFO])
dnl ==========================================================================
AC_ARG_ENABLE([dev-random],
AS_HELP_STRING([--enable-dev-random], [use /dev/random by default for key generation (otherwise use /dev/urandom)]))
if test "x$enable_dev_random" = "xyes"; then
default_rng=/dev/random
else
default_rng=/dev/urandom
fi
AC_DEFINE_UNQUOTED(DEFAULT_RNG, ["$default_rng"], [default RNG type for key generator])
dnl ==========================================================================
AC_DEFUN([CS_DEFINE],
[AC_DEFINE_UNQUOTED(DEFAULT_[]m4_translit([$1], [-a-z], [_A-Z]), [$2], [$3])
])
AC_DEFUN([CS_STR_WITH], [AC_ARG_WITH([$1],
[AS_HELP_STRING(--with-[$1], [default $2 [$3]])],
[CS_DEFINE([$1], ["$withval"], [$2])],
[CS_DEFINE([$1], ["$3"], [$2])]
)])
AC_DEFUN([CS_NUM_WITH], [AC_ARG_WITH([$1],
[AS_HELP_STRING(--with-[$1], [default $2 [$3]])],
[CS_DEFINE([$1], [$withval], [$2])],
[CS_DEFINE([$1], [$3], [$2])]
)])
AC_DEFUN([CS_ABSPATH], [
case "$1" in
/*) ;;
*) AC_MSG_ERROR([$2 argument must be an absolute path.]);;
esac
])
dnl ==========================================================================
CS_STR_WITH([plain-hash], [password hashing function for plain mode], [ripemd160])
CS_STR_WITH([plain-cipher], [cipher for plain mode], [aes])
CS_STR_WITH([plain-mode], [cipher mode for plain mode], [cbc-essiv:sha256])
CS_NUM_WITH([plain-keybits],[key length in bits for plain mode], [256])
CS_STR_WITH([luks1-hash], [hash function for LUKS1 header], [sha256])
CS_STR_WITH([luks1-cipher], [cipher for LUKS1], [aes])
CS_STR_WITH([luks1-mode], [cipher mode for LUKS1], [xts-plain64])
CS_NUM_WITH([luks1-keybits],[key length in bits for LUKS1], [256])
AC_ARG_ENABLE([luks_adjust_xts_keysize], AS_HELP_STRING([--disable-luks-adjust-xts-keysize],
[XTS mode requires two keys, double default LUKS keysize if needed]),
[], [enable_luks_adjust_xts_keysize=yes])
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], [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])
CS_NUM_WITH([luks2-parallel-threads],[Argon2 PBKDF max parallel cost for LUKS2 (if CPUs available)], [4])
CS_STR_WITH([luks2-keyslot-cipher], [fallback cipher for LUKS2 keyslot (if data encryption is incompatible)], [aes-xts-plain64])
CS_NUM_WITH([luks2-keyslot-keybits],[fallback key size for LUKS2 keyslot (if data encryption is incompatible)], [512])
CS_STR_WITH([loopaes-cipher], [cipher for loop-AES mode], [aes])
CS_NUM_WITH([loopaes-keybits],[key length in bits for loop-AES mode], [256])
CS_NUM_WITH([keyfile-size-maxkb],[maximum keyfile size (in KiB)], [8192])
CS_NUM_WITH([passphrase-size-max],[maximum keyfile size (in characters)], [512])
CS_STR_WITH([verity-hash], [hash function for verity mode], [sha256])
CS_NUM_WITH([verity-data-block], [data block size for verity mode], [4096])
CS_NUM_WITH([verity-hash-block], [hash block size for verity mode], [4096])
CS_NUM_WITH([verity-salt-size], [salt size for verity mode], [32])
CS_NUM_WITH([verity-fec-roots], [parity bytes for verity FEC], [2])
CS_STR_WITH([tmpfilesdir], [override default path to directory with systemd temporary files], [])
test -z "$with_tmpfilesdir" && with_tmpfilesdir=$systemd_tmpfilesdir
test "x$with_tmpfilesdir" = "xno" || {
CS_ABSPATH([${with_tmpfilesdir}],[with-tmpfilesdir])
DEFAULT_TMPFILESDIR=$with_tmpfilesdir
AC_SUBST(DEFAULT_TMPFILESDIR)
}
AM_CONDITIONAL(CRYPTSETUP_TMPFILE, test -n "$DEFAULT_TMPFILESDIR")
CS_STR_WITH([luks2-lock-path], [path to directory for LUKSv2 locks], [/run/cryptsetup])
test -z "$with_luks2_lock_path" && with_luks2_lock_path=/run/cryptsetup
CS_ABSPATH([${with_luks2_lock_path}],[with-luks2-lock-path])
DEFAULT_LUKS2_LOCK_PATH=$with_luks2_lock_path
AC_SUBST(DEFAULT_LUKS2_LOCK_PATH)
CS_NUM_WITH([luks2-lock-dir-perms], [default luks2 locking directory permissions], [0700])
test -z "$with_luks2_lock_dir_perms" && with_luks2_lock_dir_perms=0700
DEFAULT_LUKS2_LOCK_DIR_PERMS=$with_luks2_lock_dir_perms
AC_SUBST(DEFAULT_LUKS2_LOCK_DIR_PERMS)
dnl 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]]),
[], [with_default_luks_format=LUKS2])
case $with_default_luks_format in
LUKS1) default_luks=CRYPT_LUKS1 ;;
LUKS2) default_luks=CRYPT_LUKS2 ;;
*) AC_MSG_ERROR([Unknown default LUKS format. Use LUKS1 or LUKS2 only.]) ;;
esac
AC_DEFINE_UNQUOTED([DEFAULT_LUKS_FORMAT], [$default_luks], [default LUKS format version])
dnl ==========================================================================
AC_CONFIG_FILES([ Makefile
lib/libcryptsetup.pc
po/Makefile.in
scripts/cryptsetup.conf
tests/Makefile
])
AC_OUTPUT

887
docs/ChangeLog.old Normal file
View File

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

56
docs/Keyring.txt Normal file
View File

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

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

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

313
docs/doxyfile Normal file
View File

@ -0,0 +1,313 @@
# Doxyfile 1.8.8
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = "cryptsetup API"
PROJECT_NUMBER =
PROJECT_BRIEF = "Public cryptsetup API"
PROJECT_LOGO =
OUTPUT_DIRECTORY = doxygen_api_docs
CREATE_SUBDIRS = NO
ALLOW_UNICODE_NAMES = NO
OUTPUT_LANGUAGE = English
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
ABBREVIATE_BRIEF =
ALWAYS_DETAILED_SEC = NO
INLINE_INHERITED_MEMB = NO
FULL_PATH_NAMES = YES
STRIP_FROM_PATH =
STRIP_FROM_INC_PATH =
SHORT_NAMES = NO
JAVADOC_AUTOBRIEF = NO
QT_AUTOBRIEF = NO
MULTILINE_CPP_IS_BRIEF = NO
INHERIT_DOCS = YES
SEPARATE_MEMBER_PAGES = NO
TAB_SIZE = 8
ALIASES =
TCL_SUBST =
OPTIMIZE_OUTPUT_FOR_C = YES
OPTIMIZE_OUTPUT_JAVA = NO
OPTIMIZE_FOR_FORTRAN = NO
OPTIMIZE_OUTPUT_VHDL = NO
EXTENSION_MAPPING =
MARKDOWN_SUPPORT = YES
AUTOLINK_SUPPORT = YES
BUILTIN_STL_SUPPORT = NO
CPP_CLI_SUPPORT = NO
SIP_SUPPORT = NO
IDL_PROPERTY_SUPPORT = YES
DISTRIBUTE_GROUP_DOC = NO
SUBGROUPING = YES
INLINE_GROUPED_CLASSES = NO
INLINE_SIMPLE_STRUCTS = NO
TYPEDEF_HIDES_STRUCT = YES
LOOKUP_CACHE_SIZE = 0
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
EXTRACT_ALL = NO
EXTRACT_PRIVATE = NO
EXTRACT_PACKAGE = NO
EXTRACT_STATIC = NO
EXTRACT_LOCAL_CLASSES = YES
EXTRACT_LOCAL_METHODS = NO
EXTRACT_ANON_NSPACES = NO
HIDE_UNDOC_MEMBERS = NO
HIDE_UNDOC_CLASSES = NO
HIDE_FRIEND_COMPOUNDS = NO
HIDE_IN_BODY_DOCS = NO
INTERNAL_DOCS = NO
CASE_SENSE_NAMES = YES
HIDE_SCOPE_NAMES = NO
SHOW_INCLUDE_FILES = YES
SHOW_GROUPED_MEMB_INC = NO
FORCE_LOCAL_INCLUDES = NO
INLINE_INFO = YES
SORT_MEMBER_DOCS = YES
SORT_BRIEF_DOCS = NO
SORT_MEMBERS_CTORS_1ST = NO
SORT_GROUP_NAMES = NO
SORT_BY_SCOPE_NAME = NO
STRICT_PROTO_MATCHING = NO
GENERATE_TODOLIST = YES
GENERATE_TESTLIST = YES
GENERATE_BUGLIST = YES
GENERATE_DEPRECATEDLIST= YES
ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = YES
SHOW_FILES = YES
SHOW_NAMESPACES = YES
FILE_VERSION_FILTER =
LAYOUT_FILE =
CITE_BIB_FILES =
#---------------------------------------------------------------------------
# Configuration options related to warning and progress messages
#---------------------------------------------------------------------------
QUIET = NO
WARNINGS = YES
WARN_IF_UNDOCUMENTED = YES
WARN_IF_DOC_ERROR = YES
WARN_NO_PARAMDOC = NO
WARN_FORMAT = "$file:$line: $text"
WARN_LOGFILE =
#---------------------------------------------------------------------------
# Configuration options related to the input files
#---------------------------------------------------------------------------
INPUT = "doxygen_index.h" \
"../lib/libcryptsetup.h"
INPUT_ENCODING = UTF-8
FILE_PATTERNS =
RECURSIVE = NO
EXCLUDE =
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS =
EXCLUDE_SYMBOLS =
EXAMPLE_PATH = "examples"
EXAMPLE_PATTERNS =
EXAMPLE_RECURSIVE = NO
IMAGE_PATH =
INPUT_FILTER =
FILTER_PATTERNS =
FILTER_SOURCE_FILES = NO
FILTER_SOURCE_PATTERNS =
USE_MDFILE_AS_MAINPAGE =
#---------------------------------------------------------------------------
# Configuration options related to source browsing
#---------------------------------------------------------------------------
SOURCE_BROWSER = NO
INLINE_SOURCES = NO
STRIP_CODE_COMMENTS = YES
REFERENCED_BY_RELATION = NO
REFERENCES_RELATION = NO
REFERENCES_LINK_SOURCE = YES
SOURCE_TOOLTIPS = YES
USE_HTAGS = NO
VERBATIM_HEADERS = YES
CLANG_ASSISTED_PARSING = NO
CLANG_OPTIONS =
#---------------------------------------------------------------------------
# Configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
ALPHABETICAL_INDEX = YES
COLS_IN_ALPHA_INDEX = 5
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the HTML output
#---------------------------------------------------------------------------
GENERATE_HTML = YES
HTML_OUTPUT = html
HTML_FILE_EXTENSION = .html
HTML_HEADER =
HTML_FOOTER =
HTML_STYLESHEET =
HTML_EXTRA_STYLESHEET =
HTML_EXTRA_FILES =
HTML_COLORSTYLE_HUE = 220
HTML_COLORSTYLE_SAT = 100
HTML_COLORSTYLE_GAMMA = 80
HTML_TIMESTAMP = YES
HTML_DYNAMIC_SECTIONS = NO
HTML_INDEX_NUM_ENTRIES = 100
GENERATE_DOCSET = NO
DOCSET_FEEDNAME = "Doxygen generated docs"
DOCSET_BUNDLE_ID = org.doxygen.Project
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
DOCSET_PUBLISHER_NAME = Publisher
GENERATE_HTMLHELP = NO
CHM_FILE =
HHC_LOCATION =
GENERATE_CHI = NO
CHM_INDEX_ENCODING =
BINARY_TOC = NO
TOC_EXPAND = NO
GENERATE_QHP = NO
QCH_FILE =
QHP_NAMESPACE = org.doxygen.Project
QHP_VIRTUAL_FOLDER = doc
QHP_CUST_FILTER_NAME =
QHP_CUST_FILTER_ATTRS =
QHP_SECT_FILTER_ATTRS =
QHG_LOCATION =
GENERATE_ECLIPSEHELP = NO
ECLIPSE_DOC_ID = org.doxygen.Project
DISABLE_INDEX = NO
GENERATE_TREEVIEW = NO
ENUM_VALUES_PER_LINE = 4
TREEVIEW_WIDTH = 250
EXT_LINKS_IN_WINDOW = NO
FORMULA_FONTSIZE = 10
FORMULA_TRANSPARENT = YES
USE_MATHJAX = NO
MATHJAX_FORMAT = HTML-CSS
MATHJAX_RELPATH = http://www.mathjax.org/mathjax
MATHJAX_EXTENSIONS =
MATHJAX_CODEFILE =
SEARCHENGINE = YES
SERVER_BASED_SEARCH = NO
EXTERNAL_SEARCH = NO
SEARCHENGINE_URL =
SEARCHDATA_FILE = searchdata.xml
EXTERNAL_SEARCH_ID =
EXTRA_SEARCH_MAPPINGS =
#---------------------------------------------------------------------------
# Configuration options related to the LaTeX output
#---------------------------------------------------------------------------
GENERATE_LATEX = YES
LATEX_OUTPUT = latex
LATEX_CMD_NAME = latex
MAKEINDEX_CMD_NAME = makeindex
COMPACT_LATEX = NO
PAPER_TYPE = a4
EXTRA_PACKAGES =
LATEX_HEADER =
LATEX_FOOTER =
LATEX_EXTRA_FILES =
PDF_HYPERLINKS = YES
USE_PDFLATEX = YES
LATEX_BATCHMODE = NO
LATEX_HIDE_INDICES = NO
LATEX_SOURCE_CODE = NO
LATEX_BIB_STYLE = plain
#---------------------------------------------------------------------------
# Configuration options related to the RTF output
#---------------------------------------------------------------------------
GENERATE_RTF = NO
RTF_OUTPUT = rtf
COMPACT_RTF = NO
RTF_HYPERLINKS = NO
RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
#---------------------------------------------------------------------------
# Configuration options related to the man page output
#---------------------------------------------------------------------------
GENERATE_MAN = NO
MAN_OUTPUT = man
MAN_EXTENSION = .3
MAN_SUBDIR =
MAN_LINKS = NO
#---------------------------------------------------------------------------
# Configuration options related to the XML output
#---------------------------------------------------------------------------
GENERATE_XML = NO
XML_OUTPUT = xml
XML_PROGRAMLISTING = YES
#---------------------------------------------------------------------------
# Configuration options related to the DOCBOOK output
#---------------------------------------------------------------------------
GENERATE_DOCBOOK = NO
DOCBOOK_OUTPUT = docbook
DOCBOOK_PROGRAMLISTING = NO
#---------------------------------------------------------------------------
# Configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
# Configuration options related to the Perl module output
#---------------------------------------------------------------------------
GENERATE_PERLMOD = NO
PERLMOD_LATEX = NO
PERLMOD_PRETTY = YES
PERLMOD_MAKEVAR_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = NO
EXPAND_ONLY_PREDEF = NO
SEARCH_INCLUDES = YES
INCLUDE_PATH =
INCLUDE_FILE_PATTERNS =
PREDEFINED =
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration options related to external references
#---------------------------------------------------------------------------
TAGFILES =
GENERATE_TAGFILE =
ALLEXTERNALS = NO
EXTERNAL_GROUPS = YES
EXTERNAL_PAGES = YES
PERL_PATH =
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
CLASS_DIAGRAMS = YES
MSCGEN_PATH =
DIA_PATH =
HIDE_UNDOC_RELATIONS = YES
HAVE_DOT = NO
DOT_NUM_THREADS = 0
DOT_FONTNAME = Helvetica
DOT_FONTSIZE = 10
DOT_FONTPATH =
CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES
GROUP_GRAPHS = YES
UML_LOOK = NO
UML_LIMIT_NUM_FIELDS = 10
TEMPLATE_RELATIONS = NO
INCLUDE_GRAPH = YES
INCLUDED_BY_GRAPH = YES
CALL_GRAPH = NO
CALLER_GRAPH = NO
GRAPHICAL_HIERARCHY = YES
DIRECTORY_GRAPH = YES
DOT_IMAGE_FORMAT = png
INTERACTIVE_SVG = NO
DOT_PATH =
DOTFILE_DIRS =
MSCFILE_DIRS =
DIAFILE_DIRS =
PLANTUML_JAR_PATH =
DOT_GRAPH_MAX_NODES = 50
MAX_DOT_GRAPH_DEPTH = 0
DOT_TRANSPARENT = NO
DOT_MULTI_TARGETS = NO
GENERATE_LEGEND = YES
DOT_CLEANUP = YES

110
docs/doxygen_index.h Normal file
View File

@ -0,0 +1,110 @@
/*! \mainpage Cryptsetup API
*
* <b>The</b> documentation covers public parts of cryptsetup API. In the following sections you'll find
* the examples that describe some features of cryptsetup API.
* For more info about libcryptsetup API versions see
* <a href="https://gitlab.com/cryptsetup/cryptsetup/wikis/ABI-tracker/timeline/libcryptsetup/index.html">API Tracker</a>.
*
* <OL type="A">
* <LI>@ref cexamples "Cryptsetup API examples"</LI>
* <OL type="1">
* <LI>@ref cluks "crypt_luks_usage" - cryptsetup LUKS device type usage examples</LI>
* <UL>
* <LI>@ref cinit "crypt_init()"</LI>
* <LI>@ref cformat "crypt_format()" - header and payload on mutual device</LI>
* <LI>@ref ckeys "Keyslot operations" </LI>
* <UL>
* <LI>@ref ckeyslot_vol "crypt_keyslot_add_by_volume_key()"</LI>
* <LI>@ref ckeyslot_pass "crypt_keyslot_add_by_passphrase()"</LI>
* </UL>
* <LI>@ref cload "crypt_load()"
* <LI>@ref cactivate "crypt_activate_by_passphrase()"</LI>
* <LI>@ref cactive_pars "crypt_get_active_device()"</LI>
* <LI>@ref cinit_by_name "crypt_init_by_name()"</LI>
* <LI>@ref cdeactivate "crypt_deactivate()"</LI>
* <LI>@ref cluks_ex "crypt_luks_usage.c"</LI>
* </UL>
* <LI>@ref clog "crypt_log_usage" - cryptsetup logging API examples</LI>
* </OL>
* </OL>
*
* @section cexamples Cryptsetup API examples
* @section cluks crypt_luks_usage - cryptsetup LUKS device type usage
* @subsection cinit crypt_init()
* Every time you need to do something with cryptsetup or dmcrypt device
* you need a valid context. The first step to start your work is
* @ref crypt_init call. You can call it either with path
* to the block device or path to the regular file. If you don't supply the path,
* empty context is initialized.
*
* @subsection cformat crypt_format() - header and payload on mutual device
* This section covers basic use cases for formatting LUKS devices. Format operation
* sets device type in context and in case of LUKS header is written at the beginning
* of block device. In the example below we use the scenario where LUKS header and data
* are both stored on the same device. There's also a possibility to store header and
* data separately.
*
* <B>Bear in mind</B> that @ref crypt_format() is destructive operation and it
* overwrites part of the backing block device.
*
* @subsection ckeys Keyslot operations examples
* After successful @ref crypt_format of LUKS device, volume key is not stored
* in a persistent way on the device. Keyslot area is an array beyond LUKS header, where
* volume key is stored in the encrypted form using user input passphrase. For more info about
* LUKS keyslots and how it's actually protected, please look at
* <A HREF="https://gitlab.com/cryptsetup/cryptsetup/wikis/Specification">LUKS specification</A>.
* There are two basic methods to create a new keyslot:
*
* @subsection ckeyslot_vol crypt_keyslot_add_by_volume_key()
* Creates a new keyslot directly by encrypting volume_key stored in the device
* context. Passphrase should be supplied or user is prompted if passphrase param is
* NULL.
*
* @subsection ckeyslot_pass crypt_keyslot_add_by_passphrase()
* Creates a new keyslot for the volume key by opening existing active keyslot,
* extracting volume key from it and storing it into a new keyslot
* protected by a new passphrase
*
* @subsection cload crypt_load()
* Function loads header from backing block device into device context.
*
* @subsection cactivate crypt_activate_by_passphrase()
* Activates crypt device by user supplied password for keyslot containing the volume_key.
* If <I>keyslot</I> parameter is set to <I>CRYPT_ANY_SLOT</I> then all active keyslots
* are tried one by one until the volume key is found.
*
* @subsection cactive_pars crypt_get_active_device()
* This call returns structure containing runtime attributes of active device.
*
* @subsection cinit_by_name crypt_init_by_name()
* In case you need to do operations with active device (device which already
* has its corresponding mapping) and you miss valid device context stored in
* *crypt_device reference, you should use this call. Function tries to
* get path to backing device from DM, initializes context for it and loads LUKS
* header.
*
* @subsection cdeactivate crypt_deactivate()
* Deactivates crypt device (removes DM mapping and safely erases volume key from kernel).
*
* @subsection cluks_ex crypt_luks_usage.c - Complex example
* To compile and run use following commands in examples directory:
*
* @code
* make
* ./crypt_luks_usage _path_to_[block_device]_file
* @endcode
* Note that you need to have the cryptsetup library compiled. @include crypt_luks_usage.c
*
* @section clog crypt_log_usage - cryptsetup logging API example
* Example describes basic use case for cryptsetup logging. To compile and run
* use following commands in examples directory:
*
* @code
* make
* ./crypt_log_usage
* @endcode
* Note that you need to have the cryptsetup library compiled. @include crypt_log_usage.c
*
* @example crypt_luks_usage.c
* @example crypt_log_usage.c
*/

17
docs/examples/Makefile Normal file
View File

@ -0,0 +1,17 @@
TARGETS=crypt_log_usage crypt_luks_usage
CFLAGS=-O0 -g -Wall -D_GNU_SOURCE
LDLIBS=-lcryptsetup
CC=gcc
all: $(TARGETS)
crypt_log_usage: crypt_log_usage.o
$(CC) -o $@ $^ $(LDLIBS)
crypt_luks_usage: crypt_luks_usage.o
$(CC) -o $@ $^ $(LDLIBS)
clean:
rm -f *.o *~ core $(TARGETS)
.PHONY: clean

View File

@ -0,0 +1,94 @@
/*
* libcryptsetup API log example
*
* 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
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this file; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdio.h>
#include <sys/types.h>
#include <syslog.h>
#include <unistd.h>
#include <libcryptsetup.h>
/*
* This is an example of crypt_set_log_callback API callback.
*
*/
static void simple_syslog_wrapper(int level, const char *msg, void *usrptr)
{
const char *prefix = (const char *)usrptr;
int priority;
switch(level) {
case CRYPT_LOG_NORMAL: priority = LOG_NOTICE; break;
case CRYPT_LOG_ERROR: priority = LOG_ERR; break;
case CRYPT_LOG_VERBOSE: priority = LOG_INFO; break;
case CRYPT_LOG_DEBUG: priority = LOG_DEBUG; break;
default:
fprintf(stderr, "Unsupported log level requested!\n");
return;
}
if (prefix)
syslog(priority, "%s:%s", prefix, msg);
else
syslog(priority, "%s", msg);
}
int main(void)
{
struct crypt_device *cd;
char usrprefix[] = "cslog_example";
int r;
if (geteuid()) {
printf("Using of libcryptsetup requires super user privileges.\n");
return 1;
}
openlog("cryptsetup", LOG_CONS | LOG_PID, LOG_USER);
/* Initialize empty crypt device context */
r = crypt_init(&cd, NULL);
if (r < 0) {
printf("crypt_init() failed.\n");
return 2;
}
/* crypt_set_log_callback() - register a log callback for crypt context */
crypt_set_log_callback(cd, &simple_syslog_wrapper, (void *)usrprefix);
/* send messages ithrough the crypt_log() interface */
crypt_log(cd, CRYPT_LOG_NORMAL, "This is normal log message");
crypt_log(cd, CRYPT_LOG_ERROR, "This is error log message");
crypt_log(cd, CRYPT_LOG_VERBOSE, "This is verbose log message");
crypt_log(cd, CRYPT_LOG_DEBUG, "This is debug message");
/* release crypt context */
crypt_free(cd);
/* Initialize default (global) log callback */
crypt_set_log_callback(NULL, &simple_syslog_wrapper, NULL);
crypt_log(NULL, CRYPT_LOG_NORMAL, "This is normal log message");
crypt_log(NULL, CRYPT_LOG_ERROR, "This is error log message");
crypt_log(NULL, CRYPT_LOG_VERBOSE, "This is verbose log message");
crypt_log(NULL, CRYPT_LOG_DEBUG, "This is debug message");
closelog();
return 0;
}

View File

@ -0,0 +1,250 @@
/*
* libcryptsetup API - using LUKS device example
*
* 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
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this file; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <inttypes.h>
#include <sys/types.h>
#include <libcryptsetup.h>
static int format_and_add_keyslots(const char *path)
{
struct crypt_device *cd;
int r;
/*
* The crypt_init() call is used to initialize crypt_device context,
* The path parameter specifies a device path.
*
* For path, you can use either link to a file or block device.
* The loopback device will be detached automatically.
*/
r = crypt_init(&cd, path);
if (r < 0) {
printf("crypt_init() failed for %s.\n", path);
return r;
}
printf("Context is attached to block device %s.\n", crypt_get_device_name(cd));
/*
* So far, no data were written to the device.
*/
printf("Device %s will be formatted as a LUKS device after 5 seconds.\n"
"Press CTRL+C now if you want to cancel this operation.\n", path);
sleep(5);
/*
* NULLs for uuid and volume_key means that these attributes will be
* generated during crypt_format().
*/
r = crypt_format(cd, /* crypt context */
CRYPT_LUKS2, /* LUKS2 is a new LUKS format; use CRYPT_LUKS1 for LUKS1 */
"aes", /* used cipher */
"xts-plain64", /* used block mode and IV */
NULL, /* generate UUID */
NULL, /* generate volume key from RNG */
512 / 8, /* 512bit key - here AES-256 in XTS mode, size is in bytes */
NULL); /* default parameters */
if (r < 0) {
printf("crypt_format() failed on device %s\n", crypt_get_device_name(cd));
crypt_free(cd);
return r;
}
/*
* The device now contains a LUKS header, but there is no active keyslot.
*
* crypt_keyslot_add_* call stores the volume_key in the encrypted form into the keyslot.
*
* After format, the volume key is stored internally.
*/
r = crypt_keyslot_add_by_volume_key(cd, /* crypt context */
CRYPT_ANY_SLOT, /* just use first free slot */
NULL, /* use internal volume key */
0, /* unused (size of volume key) */
"foo", /* passphrase - NULL means query*/
3); /* size of passphrase */
if (r < 0) {
printf("Adding keyslot failed.\n");
crypt_free(cd);
return r;
}
printf("The first keyslot is initialized.\n");
/*
* Add another keyslot, now authenticating with the first keyslot.
* It decrypts the volume key from the first keyslot and creates a new one with the specified passphrase.
*/
r = crypt_keyslot_add_by_passphrase(cd, /* crypt context */
CRYPT_ANY_SLOT, /* just use first free slot */
"foo", 3, /* passphrase for the old keyslot */
"bar", 3); /* passphrase for the new kesylot */
if (r < 0) {
printf("Adding keyslot failed.\n");
crypt_free(cd);
return r;
}
printf("The second keyslot is initialized.\n");
crypt_free(cd);
return 0;
}
static int activate_and_check_status(const char *path, const char *device_name)
{
struct crypt_device *cd;
struct crypt_active_device cad;
int r;
/*
* LUKS device activation example.
*/
r = crypt_init(&cd, path);
if (r < 0) {
printf("crypt_init() failed for %s.\n", path);
return r;
}
/*
* crypt_load() is used to load existing LUKS header from a block device
*/
r = crypt_load(cd, /* crypt context */
CRYPT_LUKS, /* requested type - here LUKS of any type */
NULL); /* additional parameters (not used) */
if (r < 0) {
printf("crypt_load() failed on device %s.\n", crypt_get_device_name(cd));
crypt_free(cd);
return r;
}
/*
* Device activation creates a device-mapper device with the specified name.
*/
r = crypt_activate_by_passphrase(cd, /* crypt context */
device_name, /* device name to activate */
CRYPT_ANY_SLOT,/* the keyslot use (try all here) */
"foo", 3, /* passphrase */
CRYPT_ACTIVATE_READONLY); /* flags */
if (r < 0) {
printf("Device %s activation failed.\n", device_name);
crypt_free(cd);
return r;
}
printf("%s device %s/%s is active.\n", crypt_get_type(cd), crypt_get_dir(), device_name);
printf("\tcipher used: %s\n", crypt_get_cipher(cd));
printf("\tcipher mode: %s\n", crypt_get_cipher_mode(cd));
printf("\tdevice UUID: %s\n", crypt_get_uuid(cd));
/*
* Get info about the active device.
*/
r = crypt_get_active_device(cd, device_name, &cad);
if (r < 0) {
printf("Get info about active device %s failed.\n", device_name);
crypt_deactivate(cd, device_name);
crypt_free(cd);
return r;
}
printf("Active device parameters for %s:\n"
"\tDevice offset (in sectors): %" PRIu64 "\n"
"\tIV offset (in sectors) : %" PRIu64 "\n"
"\tdevice size (in sectors) : %" PRIu64 "\n"
"\tread-only flag : %s\n",
device_name, cad.offset, cad.iv_offset, cad.size,
cad.flags & CRYPT_ACTIVATE_READONLY ? "1" : "0");
crypt_free(cd);
return 0;
}
static int handle_active_device(const char *device_name)
{
struct crypt_device *cd;
int r;
/*
* crypt_init_by_name() initializes context by an active device-mapper name
*/
r = crypt_init_by_name(&cd, device_name);
if (r < 0) {
printf("crypt_init_by_name() failed for %s.\n", device_name);
return r;
}
if (crypt_status(cd, device_name) == CRYPT_ACTIVE)
printf("Device %s is still active.\n", device_name);
else {
printf("Something failed perhaps, device %s is not active.\n", device_name);
crypt_free(cd);
return -1;
}
/*
* crypt_deactivate() is used to deactivate a device
*/
r = crypt_deactivate(cd, device_name);
if (r < 0) {
printf("crypt_deactivate() failed.\n");
crypt_free(cd);
return r;
}
printf("Device %s is now deactivated.\n", device_name);
crypt_free(cd);
return 0;
}
int main(int argc, char **argv)
{
if (geteuid()) {
printf("Using of libcryptsetup requires super user privileges.\n");
return 1;
}
if (argc != 2) {
printf("usage: ./crypt_luks_usage <path>\n"
"<path> refers to either a regular file or a block device.\n"
" WARNING: the file or device will be wiped.\n");
return 2;
}
if (format_and_add_keyslots(argv[1]))
return 3;
if (activate_and_check_status(argv[1], "example_device"))
return 4;
if (handle_active_device("example_device"))
return 5;
return 0;
}

Binary file not shown.

BIN
docs/on-disk-format.pdf Normal file

Binary file not shown.

92
docs/v1.0.7-ReleaseNotes Normal file
View File

@ -0,0 +1,92 @@
cryptsetup 1.0.7 Release Notes (2009-07-22)
===========================================
Changes since 1.0.7-rc1
------------------------
[committer name]
* Allow removal of last slot in luksRemoveKey
and luksKillSlot. [Milan Broz]
* Add --disable-selinux option and fix static build if selinux
is required. [Milan Broz]
* Reject unsupported --offset and --skip options for luksFormat
and update man page. [Milan Broz]
Changes since 1.0.6
--------------------
[committer name]
* Various man page fixes. Also merged some Debian/Ubuntu man page
fixes. (thanks to Martin Pitt) [Milan Broz]
* Set UUID in device-mapper for LUKS devices. [Milan Broz]
* Retain readahead of underlying device. [Milan Broz]
* Display device name when asking for password. (thanks to Till
Maas) [Milan Broz]
* Check device size when loading LUKS header. Remove misleading
error message later. [Milan Broz]
* Add error hint if dm-crypt mapping failed. (Key size and kernel
version check for XTS and LRW mode for now.) [Milan Broz]
* Use better error messages if device doesn't exist or is already
used by other mapping. [Milan Broz]
* Fix make distcheck. (thanks to Mike Kelly) [Milan Broz]
* Check if all slots are full during luksAddKey. [Clemens Fruhwirth]
* Fix segfault in set_error (thanks to Oliver Metz). [Clemens Fruhwirth]
* Remove precompiled pot files. Fix uninitialized return value
variable in setup.c. [Clemens Fruhwirth]
* Code cleanups. (thanks to Ivan Stankovic) [Clemens Fruhwirth]
* Remove unnecessary files from po directory. They will be
regenerated by autogen.sh. [Clemens Fruhwirth]
* Fix wrong output for remaining key at key deletion. Allow deletion
of key slot while other keys have the same key information. [Clemens
Fruhwirth]
* Add missing AM_PROG_CC_C_O to configure.in [Milan Broz]
* Remove duplicate sentence in man page (thanks to Till Maas).
[Milan Broz]
* Wipe start of device (possible fs signature) before
LUKS-formatting. [Milan Broz]
* Do not process configure.in in hidden directories. [Milan Broz]
* Return more descriptive error in case of IO or header format
error. [Milan Broz]
* Use remapping to error target instead of calling udevsettle
for temporary crypt device. [Milan Broz]
* Check device mapper communication and warn user in case the
communication fails. (thanks to Milan Broz) [Clemens Fruhwirth]
* Fix signal handler to proper close device. (thanks to Milan Broz)
[Clemens Fruhwirth]
* write_lseek_blockwise: declare innerCount outside the if block,
add -Wall to the default CFLAGS, * fix some signedness issues
(thanks to Ivan Stankovic) [Clemens Fruhwirth]
* Error handling improvement. (thanks to Erik Edin) [Clemens Fruhwirth]
* Add non-exclusive override to interface definition. [Clemens
Fruhwirth]
* Refactor key slot selection into keyslot_from_option. Either
autoselect next free keyslot or honor user choice (after checking).
[Clemens Fruhwirth]

110
docs/v1.1.0-ReleaseNotes Normal file
View File

@ -0,0 +1,110 @@
Cryptsetup 1.1.0 Release Notes
==============================
Changes since version 1.0.7
----------------------------
Important changes:
~~~~~~~~~~~~~~~~~~
* IMPORTANT: the default compiled-in cipher parameters changed
plain mode: aes-cbc-essiv:sha256 (default is backward incompatible!).
LUKS mode: aes-cbc-essiv:sha256 (only key size increased)
In both modes is now default key size 256bits.
* Default compiled-in parameters are now configurable through configure options:
--with-plain-* / --with-luks1-* (see configure --help)
* If you need backward compatible defaults for distribution use
configure --with-plain-mode=cbc-plain --with-luks1-keybits=128
Default compiled-in modes are printed in "cryptsetup --help" output.
* Change in iterations count (LUKS):
The slot and key digest iteration minimum count is now 1000.
The key digest iteration count is calculated from iteration time (approx 1/8 of req. time).
For more info about above items see discussion here: http://tinyurl.com/yaug97y
* New libcryptsetup API (documented in libcryptsetup.h).
The old API (using crypt_options struct) is still available but will remain
frozen and not used for new functions.
Soname of library changed to libcryptsetup.so.1.0.0.
(But only recompilation should be needed for old programs.)
The new API provides much more flexible operation over LUKS device for
applications, it is preferred that new applications will use libcryptsetup
and not wrapper around cryptsetup binary.
* New luksHeaderBackup and luksHeaderRestore commands.
These commands allows binary backup of LUKS header.
Please read man page about possible security issues with backup files.
* New luksSuspend (freeze device and wipe key) and luksResume (with provided passphrase).
luksSuspend wipe encryption key in kernel memory and set device to suspend
(blocking all IO) state. This option can be used for situations when you need
temporary wipe encryption key (like suspend to RAM etc.)
Please read man page for more information.
* New --master-key-file option for luksFormat and luksAddKey.
User can now specify pre-generated master key in file, which allows regenerating
LUKS header or add key with only master key knowledge.
* Uses libgcrypt and enables all gcrypt hash algorithms for LUKS through -h luksFormat option.
Please note that using different hash for LUKS header make device incompatible with
old cryptsetup releases.
* Introduces --debug parameter.
Use when reporting bugs (just run cryptsetup with --debug and attach output
to issue report.) Sensitive data are never printed to this log.
* Moves command successful messages to verbose level.
* Requires device-mapper library and libgcrypt to build.
* Uses dm-uuid for all crypt devices, contains device type and name now.
* Removes support for dangerous non-exclusive option
(it is ignored now, LUKS device must be always opened exclusive)
Other changes:
~~~~~~~~~~~~~~
* Fixed localization to work again. Also cryptsetup is now translated by translationproject.org.
* Fix some libcryptsetup problems, including
* exported symbols and versions in libcryptsetup (properly use versioned symbols)
* Add crypt_log library function.
* Add CRYPT_ prefix to enum defined in libcryptsetup.h.
* Move duplicate Command failed message to verbose level (error is printed always).
* Fix several problems in build system
* use autopoint and clean gettext processing.
* Check in configure if selinux libraries are required in static version.
* Fix build for non-standard location of gcrypt library.
* Add temporary debug code to find processes locking internal device.
* Fix error handling during reading passphrase.
* Fail passphrase read if piped input no longer exists.
* Fix man page to not require --size which expands to device size by default.
* Clean up Makefiles and configure script.
* Try to read first sector from device to properly check that device is ready.
* Move memory locking and dm initialization to command layer.
* Increase priority of process if memory is locked.
* Add log macros and make logging more consistent.
* Keyfile now must be provided by path, only stdin file descriptor is used (api only).
* Do not call isatty() on closed keyfile descriptor.
* Move key slot manipulation function into LUKS specific code.
* Replace global options struct with separate parameters in helper functions.
* Implement old API calls using new functions.
* Allow using passphrase provided in options struct for LuksOpen.
* Allow restrict keys size in LuksOpen.
* Fix errors when compiled with LUKS_DEBUG.
* Print error when getline fails.
* Completely remove internal SHA1 implementation code, not needed anymore.
* Pad luks header to 512 sector size.
* Rework read/write blockwise to not split operation to many pieces.
* Use posix_memalign if available.
* Fix segfault if provided slot in luksKillslot is invalid.
* Remove unneeded timeout when remove of temporary device succeeded.

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

@ -0,0 +1,47 @@
Cryptsetup 1.1.1 Release Notes
==============================
Changes since version 1.1.1-rc2
* Fix luksClose error if underlying device is LVM logical volume.
Changes since version 1.1.1-rc1
* Fix automatic dm-crypt module loading.
Changes since version 1.1.0
Important changes:
~~~~~~~~~~~~~~~~~~
* Detects and use device-mapper udev support if available.
This should allow synchronisation with udev rules and avoid races with udev.
If package maintainer want to use old, direct libdevmapper device node creation,
use configure option --disable-udev.
* Supports device topology detection for data alignment.
If kernel provides device topology ioctl calls, the LUKS data area
alignment is automatically set to optimal value.
This means that stacked devices (like LUKS over MD/LVM)
should use the most optimal data alignment.
(You can still overwrite this calculation using --align-payload option.)
* Prefers some device paths in status display.
(So status command will try to find top level device name, like /dev/sdb.)
* Fix package config file to use proper package version.
Other changes:
~~~~~~~~~~~~~~
* Fix luksOpen reading of passphrase on stdin (if "-" keyfile specified).
* Fix isLuks to initialise crypto backend (blkid instead is suggested anyway).
* Properly initialise crypto backend in header backup/restore commands.
* Do not verify unlocking passphrase in luksAddKey command.
* Allow no hash specification in plain device constructor - user can provide volume key directly.
* Try to use pkgconfig for device mapper library in configuration script.
* Add some compatibility checks and disable LUKS suspend/resume if not supported.
* Rearrange tests, "make check" now run all available test for package.
* Avoid class C++ keyword in library header.

33
docs/v1.1.2-ReleaseNotes Normal file
View File

@ -0,0 +1,33 @@
== Cryptsetup 1.1.2 Release Notes ==
This release fixes a regression (introduced in 1.1.1 version) in handling
key files containing new line characters (affects only files read from
standard input).
Cryptsetup can accept passphrase on stdin (standard input).
Handling of new line (\n) character is defined by input specification:
* if keyfile is specified as "-" (using --key-file=- of by "-" positional argument
in luksFormat and luksAddKey, like cat file | cryptsetup --key-file=- <action>),
input is processed as normal binary file and no new line is interpreted.
* if there is no key file specification (with default input from stdin pipe
like echo passphrase | cryptsetup <action>) input is processed as input from terminal,
reading will stop after new line is detected.
Moreover, luksFormat now understands --key-file (in addition to positional key
file argument).
N.B. Using of standard input and pipes for passphrases should be avoided if possible,
cryptsetup have no control of used pipe buffers between commands in scripts and cannot
guarantee that all passphrase/key-file buffers are properly wiped after use.
=== changes since version 1.1.1 ===
* Fix luksFormat/luksOpen reading passphrase from stdin and "-" keyfile.
* Support --key-file/-d option for luksFormat.
* Fix description of --key-file and add --verbose and --debug options to man page.
* Add verbose log level and move unlocking message there.
* Remove device even if underlying device disappeared (remove, luksClose).
* Fix (deprecated) reload device command to accept new device argument.

13
docs/v1.1.3-ReleaseNotes Normal file
View File

@ -0,0 +1,13 @@
== Cryptsetup 1.1.3 Release Notes ==
=== changes since version 1.1.2 ===
* Fix device alignment ioctl calls parameters.
(Device alignment code was not working properly on some architectures like ppc64.)
* Fix activate_by_* API calls to handle NULL device name as documented.
(To enable check of passphrase/keyfile using libcryptsetup without activating the device.)
* Fix udev support for old libdevmapper with not compatible definition.
* Added Polish translation file.

126
docs/v1.2.0-ReleaseNotes Normal file
View File

@ -0,0 +1,126 @@
Cryptsetup 1.2.0 Release Notes
==============================
Changes since version 1.2.0-rc1
* Fix crypt_activate_by_keyfile() to work with PLAIN devices.
* Fix plain create command to properly handle keyfile size.
* Update translations.
Changes since version 1.1.3
Important changes
~~~~~~~~~~~~~~~~~
* Add text version of *FAQ* (Frequently Asked Questions) to distribution.
* Add selection of random/urandom number generator for luksFormat
(option --use-random and --use-urandom).
(This affects only long term volume key in *luksFormat*,
not RNG used for salt and AF splitter).
You can also set the default to /dev/random during compilation with
--enable-dev-random. Compiled-in default is printed in --help output.
Be very careful before changing default to blocking /dev/random use here.
* Fix *luksRemoveKey* to not ask for remaining keyslot passphrase,
only for removed one.
* No longer support *luksDelKey* (replaced with luksKillSlot).
* if you want to remove particular passphrase, use *luksKeyRemove*
* if you want to remove particular keyslot, use *luksKillSlot*
Note that in batch mode *luksKillSlot* allows removing of any keyslot
without question, in normal mode requires passphrase or keyfile from
other keyslot.
* *Default alignment* for device (if not overridden by topology info)
is now (multiple of) *1MiB*.
This reflects trends in storage technologies and aligns to the same
defaults for partitions and volume management.
* Allow explicit UUID setting in *luksFormat* and allow change it later
in *luksUUID* (--uuid parameter).
* All commands using key file now allows limited read from keyfile using
--keyfile-size and --new-keyfile-size parameters (in bytes).
This change also disallows overloading of --key-size parameter which
is now exclusively used for key size specification (in bits.)
* *luksFormat* using pre-generated master key now properly allows
using key file (only passphrase was allowed prior to this update).
* Add --dump-master-key option for *luksDump* to perform volume (master)
key dump. Note that printed information allows accessing device without
passphrase so it must be stored encrypted.
This operation is useful for simple Key Escrow function (volume key and
encryption parameters printed on paper on safe place).
This operation requires passphrase or key file.
* The reload command is no longer supported.
(Use dmsetup reload instead if needed. There is no real use for this
function except explicit data corruption:-)
* Cryptsetup now properly checks if underlying device is in use and
disallows *luksFormat*, *luksOpen* and *create* commands on open
(e.g. already mapped or mounted) device.
* Option --non-exclusive (already deprecated) is removed.
Libcryptsetup API additions:
* new functions
* crypt_get_type() - explicit query to crypt device context type
* crypt_resize() - new resize command using context
* crypt_keyslot_max() - helper to get number of supported keyslots
* crypt_get_active_device() - get active device info
* crypt_set/get_rng_type() - random/urandom RNG setting
* crypt_set_uuid() - explicit UUID change of existing device
* crypt_get_device_name() - get underlying device name
* Fix optional password callback handling.
* Allow to activate by internally cached volume key immediately after
crypt_format() without active slot (for temporary devices with
on-disk metadata)
* libcryptsetup is binary compatible with 1.1.x release and still
supports legacy API calls
* cryptsetup binary now uses only new API calls.
* Static compilation of both library (--enable-static) and cryptsetup
binary (--enable-static-cryptsetup) is now properly implemented by common
libtool logic.
Prior to this it produced miscompiled dynamic cryptsetup binary with
statically linked libcryptsetup.
The static binary is compiled as src/cryptsetup.static in parallel
with dynamic build if requested.
Other changes
~~~~~~~~~~~~~
* Fix default plain password entry from terminal in activate_by_passphrase.
* Initialize volume key from active device in crypt_init_by_name()
* Fix cryptsetup binary exit codes.
0 - success, otherwise fail
1 - wrong parameters
2 - no permission
3 - out of memory
4 - wrong device specified
5 - device already exists or device is busy
* Remove some obsolete info from man page.
* Add more regression tests for commands.
* Fix possible double free when handling master key file.
* Fix pkg-config use in automake scripts.
* Wipe iteration and salt after luksKillSlot in LUKS header.
* Rewrite file differ test to C (and fix it to really work).
* Do not query non-existent device twice (cryptsetup status /dev/nonexistent).
* Check if requested hash is supported before writing LUKS header.
* Fix problems reported by clang scan-build.

101
docs/v1.3.0-ReleaseNotes Normal file
View File

@ -0,0 +1,101 @@
Cryptsetup 1.3.0 Release Notes
==============================
Changes since version 1.2.0
Important changes
~~~~~~~~~~~~~~~~~
* Several userspace crypto backends support
cryptsetup now supports generic crypto backend interface which allows
compile package with various crypto libraries, these are already implemented:
* gcrypt (default, used in previous versions)
* OpenSSL
* NSS (because of missing ripemd160 it cannot provide full backward compatibility)
* kernel userspace API (provided by kernel 2.6.38 and above)
(Note that kernel userspace backend is very slow for this type of operation.
But it can be useful for embedded systems, because you can avoid userspace
crypto library completely.)
Backend is selected during configure time, using --with-crypto_backend option.
configure --with-crypto_backend=BACKEND (gcrypt/openssl/nss/kernel) [gcrypt]
Note that performance checked (iterations) in LUKS header will cause that
real iteration time will differ with different backends.
(There are huge differences in speed between libraries.)
* Cryptsetup now automatically allocates loopback device (/dev/loop) if device
argument is file and not plain device.
This require Linux kernel 2.6.25 and above (which implements loop autoclear flag).
You can see backing file in cryptsetup status output if underlying device is loopback.
* Introduce maximum default keyfile size, add configure option, visible in --help.
Cryptsetup now fails if read from keyfile exceeds internal limit.
You can always specify keyfile size (overrides limit) by using --keyfile-size option.
* Adds luksChangeKey command
cryptestup luksChangeKey --key-file <old keyfile> <new keyfile> [--key-slot X]
cryptestup luksChangeKey [--key-slot X] (for passphrase change)
This command allows passphrase/keyfile change in one step. If no key slot is
specified (and there is still free key slot on device) new slot is allocated before
the old is purged.
If --key-slot option is specified (or there is no free slot) command will overwrite
existing slot.
WARNING: Be sure you have another slot active or header backup when using explicit
key slot (so you can unlock the device even after possible media failure).
* Adds compatible support for loop-AES encryption type in loopaesOpen command.
Linux dm-crypt in 2.6.38 and above supports loop-AES compatible mapping
(including multi-key and special CBC mode, all three modes are supported).
If you have raw loop-AES keyfile (text file with uuencoded per-line keys), you can
access loop-AES volume using
cryptsetup loopaesOpen <device> <name> [--key-size 128] --key-file <key-file>
If you are using GPG encrypted keyfile
gpg --decrypt <key-file> | cryptsetup loopaesOpen --key-file=- <device> <name>
Do not forget to specify key size. Version and hash is automatically detected
according to number of lines in key file. For special configuration you can
override IV sector offset using --skip option, device offset with --offset
and hash algorithm using --hash, see man page for details.
Please note that loopAES dm-crypt mode is provided for compatibility reasons
(so you do not need to patch kernel and util-linux to map existing volumes)
but it is not, and never will be, optimized for speed.
It is experimental feature for now.
* Require the whole key read from keyfile in create command (regression in 1.2.0).
* WARNING: This is the last cryptsetup release which supports library with
old API (using struct crypt_options).
These calls are deprecated since 1.1.0 and AFAIK no application
is using it in recent distros. Removing compatible code will allow
new features to be implemented easily.
Other changes
~~~~~~~~~~~~~
* Lock memory also in luksDump command.
* Fix return code when passphrase is read from pipe.
* Increase libcryptsetup version (loopAES change), still fully backward compatible.
* Fixes static build (--disable-static-cryptsetup now works properly).
* Supports secure data flag for device-mapper ioctl (will be in 2.6.39,
forcing kernel to wipe all ioctl buffers with possible key data).
To enable this flag you need new device-mapper library, in LVM2 2.02.84.
* Add copyright texts into some files and adds GPL exception allowing
to distribute resulting binaries linked with OpenSSL.
* Update FAQ.
* Fix message when locking memory fails.
* Fix luksAddKey return code if master key is used.
* Update some text files in distributions.
* Add docs directory with Release Notes archive.
* Do not hardcode loopback device name in tests, use internal loopback library.

14
docs/v1.3.1-ReleaseNotes Normal file
View File

@ -0,0 +1,14 @@
Cryptsetup 1.3.1 Release Notes
==============================
Changes since version 1.3.0
* Fix keyfile=- processing in create command (regression in 1.3.0).
* Simplify device path status check (use /sys and do not scan /dev).
* Do not ignore device size argument for create command (regression in 1.2.0).
* Fix error paths in blockwise code and lseek_write call.
* Add optional Nettle crypto backend support.

131
docs/v1.4.0-ReleaseNotes Normal file
View File

@ -0,0 +1,131 @@
Cryptsetup 1.4.0 Release Notes
==============================
Changes since version 1.3.1
Important changes
~~~~~~~~~~~~~~~~~
WARNING: This release removes old deprecated API from libcryptsetup
(all functions using struct crypt_options).
This require libcrypsetup version change and
rebuild of applications using cryptsetup library.
All new API symbols are backward compatible.
* If device is not rotational disk, cryptsetup no longer tries
to wipe keyslot with Gutmann algorithm for magnetic media erase
but simply rewrites area once by random data.
* The on-disk LUKS header can now be detached (e.g. placed on separate
device or in file) using new --header option.
This option is only relevant for LUKS devices and can be used in
luksFormat, luksOpen, luksSuspend, luksResume and resize commands.
If used with luksFormat the --align-payload option is taken
as absolute sector alignment on ciphertext device and can be zero.
Example:
Create LUKS device with ciphertext device on /dev/sdb and header
on device /dev/sdc. Use all space on /dev/sdb (no reserved area for header).
cryptsetup luksFormat /dev/sdb --header /dev/sdc --align-payload 0
Activate such device:
cryptsetup luksOpen /dev/sdb --header /dev/sdc test_disk
You can use file for LUKS header (loop device will be used while
manipulating with such detached header), just you have to create
large enough file in advance.
dd if=/dev/zero of=/mnt/luks_header bs=1M count=4
cryptsetup luksFormat /dev/sdb --header /mnt/luks_header --align-payload 0
Activation is the same as above.
cryptsetup luksOpen /dev/sdb --header /mnt/luks_header test_disk
All keyslot operations need to be run on _header_ not on ciphertext device,
an example:
cryptsetup luksAddKey /mnt/luks_header
If you do not use --align-payload 0, you can later restore LUKS header
on device itself (and use it as normal LUKS device without detached header).
WARNING: There is no possible check that specified ciphertext device
matches detached on-disk header. Use with care, it can destroy
your data in case of a mistake.
WARNING: Storing LUKS header in a file means that anti-forensic splitter
cannot properly work (there is filesystem allocation layer between
header and disk).
* Support --allow-discards option to allow discards/TRIM requests.
Since kernel 3.1, dm-crypt devices optionally (not by default) support
block discards (TRIM) commands.
If you want to enable this operation, you have to enable it manually
on every activation using --allow-discards
cryptsetup luksOpen --allow-discards /dev/sdb test_disk
WARNING: There are several security consequences, please read at least
http://asalor.blogspot.com/2011/08/trim-dm-crypt-problems.html
before you enable it.
* Add --shared option for creating non-overlapping crypt segments.
The --shared options checks that mapped segments are not overlapping
and allows non-exclusive access to underlying device.
Only plain crypt devices can be used in this mode.
Example - map 64M of device disk and following 32 M area as another disk.
cryptsetup create outer_disk /dev/sdb --offset 0 --size 65536
cryptsetup create inner_disk /dev/sdb --offset 65536 --size 32768 --shared
(It can be used to simulate trivial hidden disk concepts.)
libcryptsetup API changes:
* Added options to support detached metadata device
crypt_init_by_name_and_header()
crypt_set_data_device()
* Add crypt_last_error() API call.
* Fix plain crypt format parameters to include size option.
* Add crypt_get_iv_offset() function.
* Remove old API functions (all functions using crypt_options).
* Support key-slot option for luksOpen (use only explicit keyslot).
You can now specify key slot in luksOpen and limit checking
only to specified slot.
* Support retries and timeout parameters for luksSuspend.
(The same way as in luksOpen.)
* Add doxygen-like documentation (it will be available on project page later).
(To generate it manually run doxygen in docs directory.)
Other changes
~~~~~~~~~~~~~
* Fix crypt_load to properly check device size.
* Do not allow context format of already formatted device.
* Do not allow key retrieval while suspended (key could be wiped).
* Do not allow suspend for non-LUKS devices.
* Fix luksKillSLot exit code if slot is inactive or invalid.
* Fix exit code if passphrases do not match in luksAddKey.
* Fix return code for status command when device doesn't exists.
* Fix verbose messages in isLuks command.
* Support Nettle 2.4 crypto backend (supports ripemd160).
* Add LUKS on-disk format description into package.
* Enhance check of device size before writing LUKS header.
* Add more paranoid checks for LUKS header and keyslot attributes.
* Use new /dev/loop-control (kernel 3.1) if possible.
* Remove hash/hmac restart from crypto backend and make it part of hash/hmac final.
* Improve check for invalid offset and size values.
* Revert default initialisation of volume key in crypt_init_by_name().
* Add more regression tests.
* Add some libcryptsetup example files (see docs/examples).

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

@ -0,0 +1,25 @@
Cryptsetup 1.4.1 Release Notes
==============================
Changes since version 1.4.0
* Merge experimental Python cryptsetup (pycryptsetup) binding.
This option is disabled by default, you can enable build of Python binding
with --enable--python configure switch.
Note that binding currently covers only partial libcryptsetup functions,
mainly LUKS device handling needed for Anaconda installer.
Until now provided separately as python-cryptsetup.
Thanks to Martin Sivak for the code.
See python subdirectory for more info.
Python binding code is experimental for now, no stable API guarantee.
* Fix crypt_get_volume_key_size() for plain device.
(cryptsetup status reported zero key size for plain crypt devices).
* Fix typo in set_iteration_time API call (old name remains for compatibility reasons).
* Fix FSF address in license and add LGPL license text.

44
docs/v1.4.2-ReleaseNotes Normal file
View File

@ -0,0 +1,44 @@
Cryptsetup 1.4.2 Release Notes
==============================
Changes since version 1.4.1
* Add --keyfile-offset and --new-keyfile-offset parameters to API and CLI.
These options can be used to skip start of keyfile or device used as keyfile.
* Add repair command and crypt_repair() for known LUKS metadata problems repair.
Some well-known LUKS metadata corruptions are easy to repair, this
command should provide a way to fix these problems.
Always create binary backup of header device before running repair,
(only 4kB - visible header) for example by using dd:
dd if=/dev/<LUKS header device> of=repair_bck.img bs=1k count=4
Then you can try to run repair:
cryptsetup repair <device>
Note, not all problems are possible to repair and if keyslot or some header
parameters are overwritten, device is lost permanently.
* Fix header check to support old (cryptsetup 1.0.0) header alignment.
(Regression in 1.4.0)
* Allow to specify --align-payload only for luksFormat.
* Add --master-key-file option to luksOpen (open using volume key).
* Support UUID=<LUKS_UUID> format for device specification.
You can open device by UUID (only shortcut to /dev/disk/by-uuid/ symlinks).
* Support password verification with quiet flag if possible. (1.2.0)
Password verification can be still possible if input is terminal.
* Fix retry if entered passphrases (with verify option) do not match.
(It should retry if requested, not fail.)
* Fix use of empty keyfile.
* Fix error message for luksClose and detached LUKS header.
* Allow --header for status command to get full info with detached header.

62
docs/v1.4.3-ReleaseNotes Normal file
View File

@ -0,0 +1,62 @@
Cryptsetup 1.4.3 Release Notes
==============================
Changes since version 1.4.2
* Fix readonly activation if underlying device is readonly (1.4.0).
* Fix loop mapping on readonly file.
* Include stddef.h in libdevmapper.h (size_t definition).
* Fix keyslot removal for device with 4k hw block (1.4.0).
(Wipe keyslot failed in this case.)
* Relax --shared flag to allow mapping even for overlapping segments.
The --shared flag (and API CRYPT_ACTIVATE_SHARED flag) is now able
to map arbitrary overlapping area. From API it is even usable
for LUKS devices.
It is user responsibility to not cause data corruption though.
This allows e.g. scubed to work again and also allows some
tricky extensions later.
* Allow empty cipher (cipher_null) for testing.
You can now use "null" (or directly cipher_null-ecb) in cryptsetup.
This means no encryption, useful for performance tests
(measure dm-crypt layer overhead).
* Switch on retry on device remove for libdevmapper.
Device-mapper now retry removal if device is busy.
* Allow "private" activation (skip some udev global rules) flag.
Cryptsetup library API now allows to specify CRYPT_ACTIVATE_PRIVATE,
which means that some udev rules are not processed.
(Used for temporary devices, like internal keyslot mappings where
it is not desirable to run any device scans.)
* This release also includes some Red Hat/Fedora specific extensions
related to FIPS140-2 compliance.
In fact, all these patches are more formal changes and are just subset
of building blocks for FIPS certification. See FAQ for more details
about FIPS.
FIPS extensions are enabled by using --enable-fips configure switch.
In FIPS mode (kernel booted with fips=1 and gcrypt in FIPS mode)
- it provides library and binary integrity verification using
libfipscheck (requires pre-generated checksums)
- it uses FIPS approved RNG for encryption key and salt generation
(note that using /dev/random is not formally FIPS compliant RNG).
- only gcrypt crypto backend is currently supported in FIPS mode.
The FIPS RNG requirement for salt comes from NIST SP 800-132 recommendation.
(Recommendation for Password-Based Key Derivation. Part 1: Storage Applications.
http://csrc.nist.gov/publications/nistpubs/800-132/nist-sp800-132.pdf)
LUKS should be aligned to this recommendation otherwise.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

605
docs/v2.0.0-ReleaseNotes Normal file
View File

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

109
docs/v2.0.1-ReleaseNotes Normal file
View File

@ -0,0 +1,109 @@
Cryptsetup 2.0.1 Release Notes
==============================
Stable and bug-fix release with experimental features.
This version introduces a new on-disk LUKS2 format.
The legacy LUKS (referenced as LUKS1) will be fully supported
forever as well as a traditional and fully backward compatible format.
Please note that authenticated disk encryption, non-cryptographic
data integrity protection (dm-integrity), use of Argon2 Password-Based
Key Derivation Function and the LUKS2 on-disk format itself are new
features and can contain some bugs.
To provide all security features of authenticated encryption we need
a better nonce-reuse resistant algorithm in the kernel (see note below).
For now, please use authenticated encryption as an experimental feature.
Please do not use LUKS2 without properly configured backup or in
production systems that need to be compatible with older systems.
Changes since version 2.0.0
~~~~~~~~~~~~~~~~~~~~~~~~~~~
* To store volume key into kernel keyring, kernel 4.15 with dm-crypt 1.18.1
is required. If a volume key is stored in keyring (LUKS2 only),
the dm-crypt v1.15.0 through v1.18.0 contains a serious bug that may cause
data corruption for ciphers with ESSIV.
(The key for ESSIV is zeroed because of code misplacement.)
This bug is not present for LUKS1 or any other IVs used in LUKS modes.
This change is not visible to the user (except dmsetup output).
* Increase maximum allowed PBKDF memory-cost limit to 4 GiB.
The Argon2 PBKDF uses 1GiB by default; this is also limited by the amount
of physical memory available (maximum is half of the physical memory).
* Use /run/cryptsetup as default for cryptsetup locking dir.
There were problems with sharing /run/lock with lockdev, and in the early
boot, the directory was missing.
The directory can be changed with --with-luks2-lock-path and
--with-luks2-lock-dir-perms configure switches.
* Introduce new 64-bit byte-offset *keyfile_device_offset functions.
The keyfile interface was designed, well, for keyfiles. Unfortunately,
there are user cases where a keyfile can be placed on a device, and
size_t offset can overflow on 32-bit systems.
New set of functions that allow 64-bit offsets even on 32bit systems
are now available:
- crypt_resume_by_keyfile_device_offset
- crypt_keyslot_add_by_keyfile_device_offset
- crypt_activate_by_keyfile_device_offset
- crypt_keyfile_device_read
The new functions have added the _device_ in name.
Old functions are just internal wrappers around these.
Also cryptsetup --keyfile-offset and --new-keyfile-offset now allows
64-bit offsets as parameters.
* Add error hint for wrongly formatted cipher strings in LUKS1 and
properly fail in luksFormat if cipher format is missing required IV.
For now, crypto API quietly used cipher without IV if a cipher
algorithm without IV specification was used (e.g., aes-xts).
This caused fail later during activation.
* Configure check for a recent Argon2 lib to support mandatory Argon2id.
* Fix for the cryptsetup-reencrypt static build if pwquality is enabled.
* Update LUKS1 standard doc (https links in the bibliography).
Unfinished things & TODO for next releases
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* There will be better documentation and examples.
* There will be some more formal definition of the threat model for integrity
protection. (And a link to some papers discussing integrity protection,
once it is, hopefully, accepted and published.)
* Offline re-encrypt tool LUKS2 support is currently limited.
There will be online LUKS2 re-encryption tool in future.
* Authenticated encryption will use new algorithms from CAESAR competition
(https://competitions.cr.yp.to/caesar.html) once these algorithms are
available in the kernel (more on this later).
NOTE: Currently available authenticated modes (GCM, Chacha20-poly1305)
in the kernel have too small 96-bit nonces that are problematic with
randomly generated IVs (the collision probability is not negligible).
For the GCM, nonce collision is a fatal problem.
* Authenticated encryption do not set encryption for a dm-integrity journal.
While it does not influence data confidentiality or integrity protection,
an attacker can get some more information from data journal or cause that
system will corrupt sectors after journal replay. (That corruption will be
detected though.)
* There are examples of user-defined tokens inside misc/luks2_keyslot_example
directory (like a simple external program that uses libssh to unlock LUKS2
using remote keyfile).
* The python binding (pycryptsetup) contains only basic functionality for LUKS1
(it is not updated for new features) and will be deprecated soon in favor
of python bindings to the libblockdev library (that can already handle LUKS1
devices).

93
docs/v2.0.2-ReleaseNotes Normal file
View File

@ -0,0 +1,93 @@
Cryptsetup 2.0.2 Release Notes
==============================
Stable and bug-fix release with experimental features.
Cryptsetup 2.x version introduces a new on-disk LUKS2 format.
The legacy LUKS (referenced as LUKS1) will be fully supported
forever as well as a traditional and fully backward compatible format.
Please note that authenticated disk encryption, non-cryptographic
data integrity protection (dm-integrity), use of Argon2 Password-Based
Key Derivation Function and the LUKS2 on-disk format itself are new
features and can contain some bugs.
To provide all security features of authenticated encryption, we need
a better nonce-reuse resistant algorithm in the kernel (see note below).
For now, please use authenticated encryption as an experimental feature.
Please do not use LUKS2 without properly configured backup or in
production systems that need to be compatible with older systems.
Changes since version 2.0.1
~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Fix a regression in early detection of inactive keyslot for luksKillSlot.
It tried to ask for passphrase even for already erased keyslot.
* Fix a regression in loopaesOpen processing for keyfile on standard input.
Use of "-" argument was not working properly.
* Add LUKS2 specific options for cryptsetup-reencrypt.
Tokens and persistent flags are now transferred during reencryption;
change of PBKDF keyslot parameters is now supported and allows
to set precalculated values (no benchmarks).
* Do not allow LUKS2 --persistent and --test-passphrase cryptsetup flags
combination. Persistent flags are now stored only if the device was
successfully activated with the specified flags.
* Fix integritysetup format after recent Linux kernel changes that
requires to setup key for HMAC in all cases.
Previously integritysetup allowed HMAC with zero key that behaves
like a plain hash.
* Fix VeraCrypt PIM handling that modified internal iteration counts
even for subsequent activations. The PIM count is no longer printed
in debug log as it is sensitive information.
Also, the code now skips legacy TrueCrypt algorithms if a PIM
is specified (they cannot be used with PIM anyway).
* PBKDF values cannot be set (even with force parameters) below
hardcoded minimums. For PBKDF2 is it 1000 iterations, for Argon2
it is 4 iterations and 32 KiB of memory cost.
* Introduce new crypt_token_is_assigned() API function for reporting
the binding between token and keyslots.
* Allow crypt_token_json_set() API function to create internal token types.
Do not allow unknown fields in internal token objects.
* Print message in cryptsetup that about was aborted if a user did not
answer YES in a query.
Unfinished things & TODO for next releases
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* There will be better documentation and examples.
* There will be some more formal definition of the threat model for integrity
protection. (And a link to some papers discussing integrity protection,
once it is, hopefully, accepted and published.)
* Authenticated encryption will use new algorithms from CAESAR competition
https://competitions.cr.yp.to/caesar-submissions.html.
We plan to use AEGIS and MORUS, as CAESAR finalists.
NOTE: Currently available authenticated modes (GCM, Chacha20-poly1305)
in the kernel have too small 96-bit nonces that are problematic with
randomly generated IVs (the collision probability is not negligible).
* Authenticated encryption do not set encryption for a dm-integrity journal.
While it does not influence data confidentiality or integrity protection,
an attacker can get some more information from data journal or cause that
system will corrupt sectors after journal replay. (That corruption will be
detected though.)
* There are examples of user-defined tokens inside misc/luks2_keyslot_example
directory (like a simple external program that uses libssh to unlock LUKS2
using remote keyfile).
* The python binding (pycryptsetup) contains only basic functionality for LUKS1
(it is not updated for new features) and will be deprecated in version 2.1
in favor of python bindings to the libblockdev library.

121
docs/v2.0.3-ReleaseNotes Normal file
View File

@ -0,0 +1,121 @@
Cryptsetup 2.0.3 Release Notes
==============================
Stable bug-fix release with new features.
Cryptsetup 2.x version introduces a new on-disk LUKS2 format.
The legacy LUKS (referenced as LUKS1) will be fully supported
forever as well as a traditional and fully backward compatible format.
Please note that authenticated disk encryption, non-cryptographic
data integrity protection (dm-integrity), use of Argon2 Password-Based
Key Derivation Function and the LUKS2 on-disk format itself are new
features and can contain some bugs.
To provide all security features of authenticated encryption, we need
a better nonce-reuse resistant algorithm in the kernel (see note below).
For now, please use authenticated encryption as an experimental feature.
Please do not use LUKS2 without properly configured backup or in
production systems that need to be compatible with older systems.
Changes since version 2.0.2
~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Expose interface to unbound LUKS2 keyslots.
Unbound LUKS2 keyslot allows storing a key material that is independent
of master volume key (it is not bound to encrypted data segment).
* New API extensions for unbound keyslots (LUKS2 only)
crypt_keyslot_get_key_size() and crypt_volume_key_get()
These functions allow to get key and key size for unbound keyslots.
* New enum value CRYPT_SLOT_UNBOUND for keyslot status (LUKS2 only).
* Add --unbound keyslot option to the cryptsetup luksAddKey command.
* Add crypt_get_active_integrity_failures() call to get integrity
failure count for dm-integrity devices.
* Add crypt_get_pbkdf_default() function to get per-type PBKDF default
setting.
* Add new flag to crypt_keyslot_add_by_key() to force update device
volume key. This call is mainly intended for a wrapped key change.
* Allow volume key store in a file with cryptsetup.
The --dump-master-key together with --master-key-file allows cryptsetup
to store the binary volume key to a file instead of standard output.
* Add support detached header for cryptsetup-reencrypt command.
* Fix VeraCrypt PIM handling - use proper iterations count formula
for PBKDF2-SHA512 and PBKDF2-Whirlpool used in system volumes.
* Fix cryptsetup tcryptDump for VeraCrypt PIM (support --veracrypt-pim).
* Add --with-default-luks-format configure time option.
(Option to override default LUKS format version.)
* Fix LUKS version conversion for detached (and trimmed) LUKS headers.
* Add luksConvertKey cryptsetup command that converts specific keyslot
from one PBKDF to another.
* Do not allow conversion to LUKS2 if LUKSMETA (external tool metadata)
header is detected.
* More cleanup and hardening of LUKS2 keyslot specific validation options.
Add more checks for cipher validity before writing metadata on-disk.
* Do not allow LUKS1 version downconversion if the header contains tokens.
* Add "paes" family ciphers (AES wrapped key scheme for mainframes)
to allowed ciphers.
Specific wrapped ley configuration logic must be done by 3rd party tool,
LUKS2 stores only keyslot material and allow activation of the device.
* Add support for --check-at-most-once option (kernel 4.17) to veritysetup.
This flag can be dangerous; if you can control underlying device
(you can change its content after it was verified) it will no longer
prevent reading tampered data and also it does not prevent silent
data corruptions that appear after the block was once read.
* Fix return code (EPERM instead of EINVAL) and retry count for bad
passphrase on non-tty input.
* Enable support for FEC decoding in veritysetup to check dm-verity devices
with additional Reed-Solomon code in userspace (verify command).
Unfinished things & TODO for next releases
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* There will be better documentation and examples (planned for 2.0.4).
* There will be some more formal definition of the threat model for integrity
protection. (And a link to some papers discussing integrity protection,
once it is, hopefully, accepted and published.)
* Authenticated encryption will use new algorithms from CAESAR competition
https://competitions.cr.yp.to/caesar-submissions.html.
We plan to use AEGIS and MORUS, as CAESAR finalists.
NOTE: Currently available authenticated modes (GCM, Chacha20-poly1305)
in the kernel have too small 96-bit nonces that are problematic with
randomly generated IVs (the collision probability is not negligible).
* Authenticated encryption do not set encryption for a dm-integrity journal.
While it does not influence data confidentiality or integrity protection,
an attacker can get some more information from data journal or cause that
system will corrupt sectors after journal replay. (That corruption will be
detected though.)
* There are examples of user-defined tokens inside misc/luks2_keyslot_example
directory (like a simple external program that uses libssh to unlock LUKS2
using remote keyfile).
* The python binding (pycryptsetup) contains only basic functionality for LUKS1
(it is not updated for new features) and will be REMOVED in version 2.1
in favor of python bindings to the libblockdev library.
See https://github.com/storaged-project/libblockdev/releases/tag/2.17-1 that
already supports LUKS2 and VeraCrypt devices handling through libcryptsetup.

119
docs/v2.0.4-ReleaseNotes Normal file
View File

@ -0,0 +1,119 @@
Cryptsetup 2.0.4 Release Notes
==============================
Stable bug-fix release with new features.
Cryptsetup 2.x version introduces a new on-disk LUKS2 format.
The legacy LUKS (referenced as LUKS1) will be fully supported
forever as well as a traditional and fully backward compatible format.
Please note that authenticated disk encryption, non-cryptographic
data integrity protection (dm-integrity), use of Argon2 Password-Based
Key Derivation Function and the LUKS2 on-disk format itself are new
features and can contain some bugs.
To provide all security features of authenticated encryption, we need
a better nonce-reuse resistant algorithm in the kernel (see note below).
For now, please use authenticated encryption as an experimental feature.
Please do not use LUKS2 without properly configured backup or in
production systems that need to be compatible with older systems.
Changes since version 2.0.3
~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Use the libblkid (blockid) library to detect foreign signatures
on a device before LUKS format and LUKS2 auto-recovery.
This change fixes an unexpected recovery using the secondary
LUKS2 header after a device was already overwritten with
another format (filesystem or LVM physical volume).
LUKS2 will not recreate a primary header if it detects a valid
foreign signature. In this situation, a user must always
use cryptsetup repair command for the recovery.
Note that libcryptsetup and utilities are now linked to libblkid
as a new dependence.
To compile code without blockid support (strongly discouraged),
use --disable-blkid configure switch.
* Add prompt for format and repair actions in cryptsetup and
integritysetup if foreign signatures are detected on the device
through the blockid library.
After the confirmation, all known signatures are then wiped as
part of the format or repair procedure.
* Print consistent verbose message about keyslot and token numbers.
For keyslot actions: Key slot <number> unlocked/created/removed.
For token actions: Token <number> created/removed.
* Print error, if a non-existent token is tried to be removed.
* Add support for LUKS2 token definition export and import.
The token command now can export/import customized token JSON file
directly from command line. See the man page for more details.
* Add support for new dm-integrity superblock version 2.
* Add an error message when nothing was read from a key file.
* Update cryptsetup man pages, including --type option usage.
* Add a snapshot of LUKS2 format specification to documentation
and accordingly fix supported secondary header offsets.
* Add bundled optimized Argon2 SSE (X86_64 platform) code.
If the bundled Argon2 code is used and the new configure switch
--enable-internal-sse-argon2 option is present, and compiler flags
support required optimization, the code will try to use optimized
and faster variant.
Always use the shared library (--enable-libargon2) if possible.
This option was added because an enterprise distribution
rejected to support the shared Argon2 library and native support
in generic cryptographic libraries is not ready yet.
* Fix compilation with crypto backend for LibreSSL >= 2.7.0.
LibreSSL introduced OpenSSL 1.1.x API functions, so compatibility
wrapper must be commented out.
* Fix on-disk header size calculation for LUKS2 format if a specific
data alignment is requested. Until now, the code used default size
that could be wrong for converted devices.
Unfinished things & TODO for next releases
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Authenticated encryption will use new algorithms from CAESAR competition
https://competitions.cr.yp.to/caesar-submissions.html.
We plan to use AEGIS and MORUS (in kernel 4.18), as CAESAR finalists.
NOTE: Currently available authenticated modes (GCM, Chacha20-poly1305)
in the kernel have too small 96-bit nonces that are problematic with
randomly generated IVs (the collision probability is not negligible).
For more info about LUKS2 authenticated encryption, please see our paper
https://arxiv.org/abs/1807.00309
* Authenticated encryption do not set encryption for a dm-integrity journal.
While it does not influence data confidentiality or integrity protection,
an attacker can get some more information from data journal or cause that
system will corrupt sectors after journal replay. (That corruption will be
detected though.)
* There are examples of user-defined tokens inside misc/luks2_keyslot_example
directory (like a simple external program that uses libssh to unlock LUKS2
using remote keyfile).
* The python binding (pycryptsetup) contains only basic functionality for LUKS1
(it is not updated for new features) and will be REMOVED in version 2.1
in favor of python bindings to the libblockdev library.
See https://github.com/storaged-project/libblockdev/releases that
already supports LUKS2 and VeraCrypt devices handling through libcryptsetup.

102
docs/v2.0.5-ReleaseNotes Normal file
View File

@ -0,0 +1,102 @@
Cryptsetup 2.0.5 Release Notes
==============================
Stable bug-fix release with new features.
Cryptsetup 2.x version introduces a new on-disk LUKS2 format.
The legacy LUKS (referenced as LUKS1) will be fully supported
forever as well as a traditional and fully backward compatible format.
Please note that authenticated disk encryption, non-cryptographic
data integrity protection (dm-integrity), use of Argon2 Password-Based
Key Derivation Function and the LUKS2 on-disk format itself are new
features and can contain some bugs.
Please do not use LUKS2 without properly configured backup or in
production systems that need to be compatible with older systems.
Changes since version 2.0.4
~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Wipe full header areas (including unused) during LUKS format.
Since this version, the whole area up to the data offset is zeroed,
and subsequently, all keyslots areas are wiped with random data.
This ensures that no remaining old data remains in the LUKS header
areas, but it could slow down format operation on some devices.
Previously only first 4k (or 32k for LUKS2) and the used keyslot
was overwritten in the format operation.
* Several fixes to error messages that were unintentionally replaced
in previous versions with a silent exit code.
More descriptive error messages were added, including error
messages if
- a device is unusable (not a block device, no access, etc.),
- a LUKS device is not detected,
- LUKS header load code detects unsupported version,
- a keyslot decryption fails (also happens in the cipher check),
- converting an inactive keyslot.
* Device activation fails if data area overlaps with LUKS header.
* Code now uses explicit_bzero to wipe memory if available
(instead of own implementation).
* Additional VeraCrypt modes are now supported, including Camellia
and Kuznyechik symmetric ciphers (and cipher chains) and Streebog
hash function. These were introduced in a recent VeraCrypt upstream.
Note that Kuznyechik requires out-of-tree kernel module and
Streebog hash function is available only with the gcrypt cryptographic
backend for now.
* Fixes static build for integritysetup if the pwquality library is used.
* Allows passphrase change for unbound keyslots.
* Fixes removed keyslot number in verbose message for luksKillSlot,
luksRemoveKey and erase command.
* Adds blkid scan when attempting to open a plain device and warn the user
about existing device signatures in a ciphertext device.
* Remove LUKS header signature if luksFormat fails to add the first keyslot.
* Remove O_SYNC from device open and use fsync() to speed up
wipe operation considerably.
* Create --master-key-file in luksDump and fail if the file already exists.
* Fixes a bug when LUKS2 authenticated encryption with a detached header
wiped the header device instead of dm-integrity data device area (causing
unnecessary LUKS2 header auto recovery).
Unfinished things & TODO for next releases
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Authenticated encryption should use new algorithms from CAESAR competition
https://competitions.cr.yp.to/caesar-submissions.html.
AEGIS and MORUS are already available in kernel 4.18.
For more info about LUKS2 authenticated encryption, please see our paper
https://arxiv.org/abs/1807.00309
Please note that authenticated encryption is still an experimental feature
and can have performance problems for hish-speed devices and device
with larger IO blocks (like RAID).
* Authenticated encryption do not set encryption for a dm-integrity journal.
While it does not influence data confidentiality or integrity protection,
an attacker can get some more information from data journal or cause that
system will corrupt sectors after journal replay. (That corruption will be
detected though.)
* There are examples of user-defined tokens inside misc/luks2_keyslot_example
directory (like a simple external program that uses libssh to unlock LUKS2
using remote keyfile).
* The python binding (pycryptsetup) contains only basic functionality for LUKS1
(it is not updated for new features) and will be REMOVED in version 2.1
in favor of python bindings to the libblockdev library.
See https://github.com/storaged-project/libblockdev/releases that
already supports LUKS2 and VeraCrypt devices handling through libcryptsetup.

97
docs/v2.0.6-ReleaseNotes Normal file
View File

@ -0,0 +1,97 @@
Cryptsetup 2.0.6 Release Notes
==============================
Stable bug-fix release.
All users of cryptsetup 2.0.x should upgrade to this version.
Cryptsetup 2.x version introduces a new on-disk LUKS2 format.
The legacy LUKS (referenced as LUKS1) will be fully supported
forever as well as a traditional and fully backward compatible format.
Please note that authenticated disk encryption, non-cryptographic
data integrity protection (dm-integrity), use of Argon2 Password-Based
Key Derivation Function and the LUKS2 on-disk format itself are new
features and can contain some bugs.
Please do not use LUKS2 without properly configured backup or in
production systems that need to be compatible with older systems.
Changes since version 2.0.5
~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Fix support of larger metadata areas in LUKS2 header.
This release properly supports all specified metadata areas, as documented
in LUKS2 format description (see docs/on-disk-format-luks2.pdf in archive).
Currently, only default metadata area size is used (in format or convert).
Later cryptsetup versions will allow increasing this metadata area size.
* If AEAD (authenticated encryption) is used, cryptsetup now tries to check
if the requested AEAD algorithm with specified key size is available
in kernel crypto API.
This change avoids formatting a device that cannot be later activated.
For this function, the kernel must be compiled with the
CONFIG_CRYPTO_USER_API_AEAD option enabled.
Note that kernel user crypto API options (CONFIG_CRYPTO_USER_API and
CONFIG_CRYPTO_USER_API_SKCIPHER) are already mandatory for LUKS2.
* Fix setting of integrity no-journal flag.
Now you can store this flag to metadata using --persistent option.
* Fix cryptsetup-reencrypt to not keep temporary reencryption headers
if interrupted during initial password prompt.
* Adds early check to plain and LUKS2 formats to disallow device format
if device size is not aligned to requested sector size.
Previously it was possible, and the device was rejected to activate by
kernel later.
* Fix checking of hash algorithms availability for PBKDF early.
Previously LUKS2 format allowed non-existent hash algorithm with
invalid keyslot preventing the device from activation.
* Allow Adiantum cipher construction (a non-authenticated length-preserving
fast encryption scheme), so it can be used both for data encryption and
keyslot encryption in LUKS1/2 devices.
For benchmark, use:
# cryptsetup benchmark -c xchacha12,aes-adiantum
# cryptsetup benchmark -c xchacha20,aes-adiantum
For LUKS format:
# cryptsetup luksFormat -c xchacha20,aes-adiantum-plain64 -s 256 <device>
The support for Adiantum will be merged in Linux kernel 4.21.
For more info see the paper https://eprint.iacr.org/2018/720.
Unfinished things & TODO for next releases
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Authenticated encryption should use new algorithms from CAESAR competition
https://competitions.cr.yp.to/caesar-submissions.html.
AEGIS and MORUS are already available in kernel 4.18.
For more info about LUKS2 authenticated encryption, please see our paper
https://arxiv.org/abs/1807.00309
Please note that authenticated encryption is still an experimental feature
and can have performance problems for high-speed devices and device
with larger IO blocks (like RAID).
* Authenticated encryption do not set encryption for a dm-integrity journal.
While it does not influence data confidentiality or integrity protection,
an attacker can get some more information from data journal or cause that
system will corrupt sectors after journal replay. (That corruption will be
detected though.)
* There are examples of user-defined tokens inside misc/luks2_keyslot_example
directory (like a simple external program that uses libssh to unlock LUKS2
using remote keyfile).
* The python binding (pycryptsetup) contains only basic functionality for LUKS1
(it is not updated for new features) and will be REMOVED in version 2.1
in favor of python bindings to the libblockdev library.
See https://github.com/storaged-project/libblockdev/releases that
already supports LUKS2 and VeraCrypt devices handling through libcryptsetup.

210
docs/v2.1.0-ReleaseNotes Normal file
View File

@ -0,0 +1,210 @@
Cryptsetup 2.1.0 Release Notes
==============================
Stable release with new features and bug fixes.
Cryptsetup 2.1 version uses a new on-disk LUKS2 format as the default
LUKS format and increases default LUKS2 header size.
The legacy LUKS (referenced as LUKS1) will be fully supported forever
as well as a traditional and fully backward compatible format.
When upgrading a stable distribution, please use configure option
--with-default-luks-format=LUKS1 to maintain backward compatibility.
This release also switches to OpenSSL as a default cryptographic
backend for LUKS header processing. Use --with-crypto_backend=gcrypt
configure option if you need to preserve legacy libgcrypt backend.
Please do not use LUKS2 without properly configured backup or
in production systems that need to be compatible with older systems.
Changes since version 2.0.6
~~~~~~~~~~~~~~~~~~~~~~~~~~~
* The default for cryptsetup LUKS format action is now LUKS2.
You can use LUKS1 with cryptsetup option --type luks1.
* The default size of the LUKS2 header is increased to 16 MB.
It includes metadata and the area used for binary keyslots;
it means that LUKS header backup is now 16MB in size.
Note, that used keyslot area is much smaller, but this increase
of reserved space allows implementation of later extensions
(like online reencryption).
It is fully compatible with older cryptsetup 2.0.x versions.
If you require to create LUKS2 header with the same size as
in the 2.0.x version, use --offset 8192 option for luksFormat
(units are in 512-bytes sectors; see notes below).
* Cryptsetup now doubles LUKS default key size if XTS mode is used
(XTS mode uses two internal keys). This does not apply if key size
is explicitly specified on the command line and it does not apply
for the plain mode.
This fixes a confusion with AES and 256bit key in XTS mode where
code used AES128 and not AES256 as often expected.
Also, the default keyslot encryption algorithm (if cannot be derived
from data encryption algorithm) is now available as configure
options --with-luks2-keyslot-cipher and --with-luks2-keyslot-keybits.
The default is aes-xts-plain64 with 2 * 256-bits key.
* Default cryptographic backend used for LUKS header processing is now
OpenSSL. For years, OpenSSL provided better performance for PBKDF.
NOTE: Cryptsetup/libcryptsetup supports several cryptographic
library backends. The fully supported are libgcrypt, OpenSSL and
kernel crypto API. FIPS mode extensions are maintained only for
libgcrypt and OpenSSL. Nettle and NSS are usable only for some
subset of algorithms and cannot provide full backward compatibility.
You can always switch to other backends by using a configure switch,
for libgcrypt (compatibility for older distributions) use:
--with-crypto_backend=gcrypt
* The Python bindings are no longer supported and the code was removed
from cryptsetup distribution. Please use the libblockdev project
that already covers most of the libcryptsetup functionality
including LUKS2.
* Cryptsetup now allows using --offset option also for luksFormat.
It means that the specified offset value is used for data offset.
LUKS2 header areas are automatically adjusted according to this value.
(Note units are in 512-byte sectors due to the previous definition
of this option in plain mode.)
This option can replace --align-payload with absolute alignment value.
* Cryptsetup now supports new refresh action (that is the alias for
"open --refresh").
It allows changes of parameters for an active device (like root
device mapping), for example, it can enable or disable TRIM support
on-the-fly.
It is supported for LUKS1, LUKS2, plain and loop-AES devices.
* Integritysetup now supports mode with detached data device through
new --data-device option.
Since kernel 4.18 there is a possibility to specify external data
device for dm-integrity that stores all integrity tags.
* Integritysetup now supports automatic integrity recalculation
through new --integrity-recalculate option.
Linux kernel since version 4.18 supports automatic background
recalculation of integrity tags for dm-integrity.
Other changes and fixes
~~~~~~~~~~~~~~~~~~~~~~~
* Fix for crypt_wipe call to allocate space if the header is backed
by a file. This means that if you use detached header file, it will
now have always the full size after luksFormat, even if only
a few keyslots are used.
* Fixes to offline cryptsetup-reencrypt to preserve LUKS2 keyslots
area sizes after reencryption and fixes for some other issues when
creating temporary reencryption headers.
* Added some FIPS mode workarounds. We cannot (yet) use Argon2 in
FIPS mode, libcryptsetup now fallbacks to use PBKDF2 in FIPS mode.
* Rejects conversion to LUKS1 if PBKDF2 hash algorithms
in keyslots differ.
* The hash setting on command line now applies also to LUKS2 PBKDF2
digest. In previous versions, the LUKS2 key digest used PBKDF2-SHA256
(except for converted headers).
* Allow LUKS2 keyslots area to increase if data offset allows it.
Cryptsetup can fine-tune LUKS2 metadata area sizes through
--luks2-metadata-size=BYTES and --luks2-keyslots-size=BYTES.
Please DO NOT use these low-level options until you need it for
some very specific additional feature.
Also, the code now prints these LUKS2 header area sizes in dump
command.
* For LUKS2, keyslot can use different encryption that data with
new options --keyslot-key-size=BITS and --keyslot-cipher=STRING
in all commands that create new LUKS keyslot.
Please DO NOT use these low-level options until you need it for
some very specific additional feature.
* Code now avoids data flush when reading device status through
device-mapper.
* The Nettle crypto backend and the userspace kernel crypto API
backend were enhanced to allow more available hash functions
(like SHA3 variants).
* Upstream code now does not require libgcrypt-devel
for autoconfigure, because OpenSSL is the default.
The libgcrypt does not use standard pkgconfig detection and
requires specific macro (part of libgcrypt development files)
to be always present during autoconfigure.
With other crypto backends, like OpenSSL, this makes no sense,
so this part of autoconfigure is now optional.
* Cryptsetup now understands new --debug-json option that allows
an additional dump of some JSON information. These are no longer
present in standard debug output because it could contain some
specific LUKS header parameters.
* The luksDump contains the hash algorithm used in Anti-Forensic
function.
* All debug messages are now sent through configured log callback
functions, so an application can easily use own debug messages
handling. In previous versions debug messages were printed directly
to standard output.)
Libcryptsetup API additions
~~~~~~~~~~~~~~~~~~~~~~~~~~~
These new calls are now exported, for details see libcryptsetup.h:
* crypt_init_data_device
* crypt_get_metadata_device_name
functions to init devices with separate metadata and data device
before a format function is called.
* crypt_set_data_offset
sets the data offset for LUKS to the specified value
in 512-byte sectors.
It should replace alignment calculation in LUKS param structures.
* crypt_get_metadata_size
* crypt_set_metadata_size
allows to set/get area sizes in LUKS header
(according to specification).
* crypt_get_default_type
get default compiled-in LUKS type (version).
* crypt_get_pbkdf_type_params
allows to get compiled-in PBKDF parameters.
* crypt_keyslot_set_encryption
* crypt_keyslot_get_encryption
allows to set/get per-keyslot encryption algorithm for LUKS2.
* crypt_keyslot_get_pbkdf
allows to get PBKDF parameters per-keyslot.
and these new defines:
* CRYPT_LOG_DEBUG_JSON (message type for JSON debug)
* CRYPT_DEBUG_JSON (log level for JSON debug)
* CRYPT_ACTIVATE_RECALCULATE (dm-integrity recalculate flag)
* CRYPT_ACTIVATE_REFRESH (new open with refresh flag)
All existing API calls should remain backward compatible.
Unfinished things & TODO for next releases
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Optional authenticated encryption is still an experimental feature
and can have performance problems for high-speed devices and device
with larger IO blocks (like RAID).
* Authenticated encryption does not use encryption for a dm-integrity
journal. While it does not influence data confidentiality or
integrity protection, an attacker can get some more information
from data journal or cause that system will corrupt sectors after
journal replay. (That corruption will be detected though.)
* The LUKS2 metadata area increase is mainly needed for the new online
reencryption as the major feature for the next release.

279
docs/v2.2.0-ReleaseNotes Normal file
View File

@ -0,0 +1,279 @@
Cryptsetup 2.2.0 Release Notes
==============================
Stable release with new experimental features and bug fixes.
Cryptsetup 2.2 version introduces a new LUKS2 online reencryption
extension that allows reencryption of mounted LUKS2 devices
(device in use) in the background.
Online reencryption is a complex feature. Please be sure you
have a full data backup before using this feature.
Changes since version 2.1.0
~~~~~~~~~~~~~~~~~~~~~~~~~~~
LUKS2 online reencryption
~~~~~~~~~~~~~~~~~~~~~~~~~
The reencryption is intended to provide a reliable way to change
volume key or an algorithm change while the encrypted device is still
in use.
It is based on userspace-only approach (no kernel changes needed)
that uses the device-mapper subsystem to remap active devices on-the-fly
dynamically. The device is split into several segments (encrypted by old
key, new key and so-called hotzone, where reencryption is actively running).
The flexible LUKS2 metadata format is used to store intermediate states
(segment mappings) and both version of keyslots (old and new keys).
Also, it provides a binary area (in the unused keyslot area space)
to provide recovery metadata in the case of unexpected failure during
reencryption. LUKS2 header is during the reencryption marked with
"online-reencryption" keyword. After the reencryption is finished,
this keyword is removed, and the device is backward compatible with all
older cryptsetup tools (that support LUKS2).
The recovery supports three resilience modes:
- checksum: default mode, where individual checksums of ciphertext hotzone
sectors are stored, so the recovery process can detect which sectors were
already reencrypted. It requires that the device sector write is atomic.
- journal: the hotzone is journaled in the binary area
(so the data are written twice)
- none: performance mode; there is no protection
(similar to old offline reencryption)
These resilience modes are not available if reencryption uses data shift.
Note: until we have full documentation (both of the process and metadata),
please refer to Ondrej's slides (some slight details are no longer relevant)
https://okozina.fedorapeople.org/online-disk-reencryption-with-luks2-compact.pdf
The offline reencryption tool (cryptsetup-reencrypt) is still supported
for both LUKS1 and LUKS2 format.
Cryptsetup examples for reencryption
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The reencryption feature is integrated directly into cryptsetup utility
as the new "reencrypt" action (command).
There are three basic modes - to perform reencryption (change of already
existing LUKS2 device), to add encryption to plaintext device and to remove
encryption from a device (decryption).
In all cases, if existing LUKS2 metadata contains information about
the ongoing reencryption process, following reencrypt command continues
with the ongoing reencryption process until it is finished.
You can activate a device with ongoing reencryption as the standard LUKS2
device, but the reencryption process will not continue until the cryptsetup
reencrypt command is issued.
1) Reencryption
~~~~~~~~~~~~~~~
This mode is intended to change any attribute of the data encryption
(change of the volume key, algorithm or sector size).
Note that authenticated encryption is not yet supported.
You can start the reencryption process by specifying a LUKS2 device or with
a detached LUKS2 header.
The code should automatically recognize if the device is in use (and if it
should use online mode of reencryption).
If you do not specify parameters, only volume key is changed
(a new random key is generated).
# cryptsetup reencrypt <device> [--header <hdr>]
You can also start reencryption using active mapped device name:
# cryptsetup reencrypt --active-name <name>
You can also specify the resilience mode (none, checksum, journal) with
--resilience=<mode> option, for checksum mode also the hash algorithm with
--resilience-hash=<alg> (only hash algorithms supported by cryptographic
backend are available).
The maximal size of reencryption hotzone can be limited by
--hotzone-size=<size> option and applies to all reencryption modes.
Note that for checksum and journal mode hotzone size is also limited
by available space in binary keyslot area.
2) Encryption
~~~~~~~~~~~~~
This mode provides a way to encrypt a plaintext device to LUKS2 format.
This option requires reduction of device size (for LUKS2 header) or new
detached header.
# cryptsetup reencrypt <device> --encrypt --reduce-device-size <size>
Or with detached header:
# cryptsetup reencrypt <device> --encrypt --header <hdr>
3) Decryption
~~~~~~~~~~~~~
This mode provides the removal of existing LUKS2 encryption and replacing
a device with plaintext content only.
For now, we support only decryption with a detached header.
# cryptsetup reencrypt <device> --decrypt --header <hdr>
For all three modes, you can split the process to metadata initialization
(prepare keyslots and segments but do not run reencryption yet) and the data
reencryption step by using --init-only option.
Prepares metadata:
# cryptsetup reencrypt --init-only <parameters>
Starts the data processing:
# cryptsetup reencrypt <device>
Please note, that due to the Linux kernel limitation, the encryption or
decryption process cannot be run entirely online - there must be at least
short offline window where operation adds/removes device-mapper crypt (LUKS2) layer.
This step should also include modification of /etc/crypttab and fstab UUIDs,
but it is out of the scope of cryptsetup tools.
Limitations
~~~~~~~~~~~
Most of these limitations will be (hopefully) fixed in next versions.
* Only one active keyslot is supported (all old keyslots will be removed
after reencryption).
* Only block devices are now supported as parameters. As a workaround
for images in a file, please explicitly map a loop device over the image
and use the loop device as the parameter.
* Devices with authenticated encryption are not supported. (Later it will
be limited by the fixed per-sector metadata, per-sector metadata size
cannot be changed without a new device format operation.)
* The reencryption uses userspace crypto library, with fallback to
the kernel (if available). There can be some specific configurations
where the fallback does not provide optimal performance.
* There are no translations of error messages until the final release
(some messages can be rephrased as well).
* The repair command is not finished; the recovery of interrupted
reencryption is made automatically on the first device activation.
* Reencryption triggers too many udev scans on metadata updates (on closing
write enabled file descriptors). This has a negative performance impact on the whole
reencryption and generates excessive I/O load on the system.
New libcryptsetup reencryption API
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The libcryptsetup contains new API calls that are used to setup and
run the reencryption.
Note that there can be some changes in API implementation of these functions
and/or some new function can be introduced in final cryptsetup 2.2 release.
New API symbols (see documentation in libcryptsetup.h)
* struct crypt_params_reencrypt - reencryption parameters
* crypt_reencrypt_init_by_passphrase
* crypt_reencrypt_init_by_keyring
- function to configure LUKS2 metadata for reencryption;
if metadata already exists, it configures the context from this metadata
* crypt_reencrypt
- run the reencryption process (processing the data)
- the optional callback function can be used to interrupt the reencryption
or report the progress.
* crypt_reencrypt_status
- function to query LUKS2 metadata about the reencryption state
Other changes and fixes
~~~~~~~~~~~~~~~~~~~~~~~
* Add optional global serialization lock for memory hard PBKDF.
(The --serialize-memory-hard-pbkdf option in cryptsetup and
CRYPT_ACTIVATE_SERIALIZE_MEMORY_HARD_PBKDF in activation flag.)
This is an "ugly" optional workaround for a situation when multiple devices
are being activated in parallel (like systemd crypttab activation).
The system instead of returning ENOMEM (no memory available) starts
out-of-memory (OOM) killer to kill processes randomly.
Until we find a reliable way how to work with memory-hard function
in these situations, cryptsetup provide a way how to serialize memory-hard
unlocking among parallel cryptsetup instances to workaround this problem.
This flag is intended to be used only in very specific situations,
never use it directly :-)
* Abort conversion to LUKS1 with incompatible sector size that is
not supported in LUKS1.
* Report error (-ENOENT) if no LUKS keyslots are available. User can now
distinguish between a wrong passphrase and no keyslot available.
* Fix a possible segfault in detached header handling (double free).
* Add integritysetup support for bitmap mode introduced in Linux kernel 5.2.
Integritysetup now supports --integrity-bitmap-mode option and
--bitmap-sector-per-bit and --bitmap-flush-time commandline options.
In the bitmap operation mode, if a bit in the bitmap is 1, the corresponding
region's data and integrity tags are not synchronized - if the machine
crashes, the unsynchronized regions will be recalculated.
The bitmap mode is faster than the journal mode because we don't have
to write the data twice, but it is also less reliable, because if data
corruption happens when the machine crashes, it may not be detected.
This can be used only for standalone devices, not with dm-crypt.
* The libcryptsetup now keeps all file descriptors to underlying device
open during the whole lifetime of crypt device context to avoid excessive
scanning in udev (udev run scan on every descriptor close).
* The luksDump command now prints more info for reencryption keyslot
(when a device is in-reencryption).
* New --device-size parameter is supported for LUKS2 reencryption.
It may be used to encrypt/reencrypt only the initial part of the data
device if the user is aware that the rest of the device is empty.
Note: This change causes API break since the last rc0 release
(crypt_params_reencrypt structure contains additional field).
* New --resume-only parameter is supported for LUKS2 reencryption.
This flag resumes reencryption process if it exists (not starting
new reencryption).
* The repair command now tries LUKS2 reencryption recovery if needed.
* If reencryption device is a file image, an interactive dialog now
asks if reencryption should be run safely in offline mode
(if autodetection of active devices failed).
* Fix activation through a token where dm-crypt volume key was not
set through keyring (but using old device-mapper table parameter mode).
* Online reencryption can now retain all keyslots (if all passphrases
are provided). Note that keyslot numbers will change in this case.
* Allow volume key file to be used if no LUKS2 keyslots are present.
If all keyslots are removed, LUKS2 has no longer information about
the volume key size (there is only key digest present).
Please use --key-size option to open the device or add a new keyslot
in these cases.
* Print a warning if online reencrypt is called over LUKS1 (not supported).
* Fix TCRYPT KDF failure in FIPS mode.
Some crypto backends support plain hash in FIPS mode but not for PBKDF2.
* Remove FIPS mode restriction for crypt_volume_key_get.
It is an application responsibility to use this API in the proper context.
* Reduce keyslots area size in luksFormat when the header device is too small.
Unless user explicitly asks for keyslots areas size (either via
--luks2-keyslots-size or --offset) reduce keyslots size so that it fits
in metadata device.
* Make resize action accept --device-size parameter (supports units suffix).

36
docs/v2.2.1-ReleaseNotes Normal file
View File

@ -0,0 +1,36 @@
Cryptsetup 2.2.1 Release Notes
==============================
Stable bug-fix release.
This version contains a fix for a possible data corruption bug
on 32-bit platforms.
All users of cryptsetup 2.1 and 2.2 should upgrade to this version.
Changes since version 2.2.0
~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Fix possible data length and IV offset overflow on 32bit architectures.
Other 64-bit architectures are not affected.
The flawed helper function prototypes (introduced in version 2.1.0) used
size_t type, that is 32-bit integer on 32-bit systems.
This patch fixes the problem to properly use 64-bit types.
If the offset parameter addresses devices larger than 2TB, the value
overflows and stores incorrect information in the metadata.
For example, integrity device is smaller than expected size if used
over large disk on 32-bit architecture.
This issue is not present with the standard LUKS1/LUKS2 devices without
integrity extensions.
* Fix a regression in TrueCrypt/VeraCrypt system partition activation.
* Reinstate missing backing file hint for loop device.
If the encrypted device is backed by a file (loopback), cryptsetup now
shows the path to the backing file in passphrase query (as in 1.x version).
* LUKS2 reencryption block size is now aligned to reported optimal IO size.
This change eliminates possible non-aligned device warnings in kernel log
during reencryption.

56
docs/v2.2.2-ReleaseNotes Normal file
View File

@ -0,0 +1,56 @@
Cryptsetup 2.2.2 Release Notes
==============================
Stable bug-fix release.
All users of cryptsetup 2.1 and 2.2 should upgrade to this version.
Changes since version 2.2.1
~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Print error message if a keyslot open failed for a different reason
than wrong passwords (for example there is not enough memory).
Only an exit code was present in this case.
* The progress function switches unit sizes (B/s to GiB/s) according
to the actual speed. Also, it properly calculates speed in the case
of a resumed reencryption operation.
* The --version now supports short -V short option and better handles
common option priorities.
* If cryptsetup wipes signatures during format actions through blkid,
it also prints signature device offsets.
* Compilation now properly uses LTLIBINTL gettext setting in Makefiles.
* Device-mapper backend now supports new DM_GET_TARGET_VERSION ioctl
(available since Linux kernel 5.4).
This should help to detect some kernel/userspace incompatibilities
earlier later after a failed device activation.
* Fixes LUKS2 reencryption on systems without kernel keyring.
* Fixes unlocking prompt for partitions mapped through loop devices
(to properly show the backing device).
* For LUKS2 decryption, a device is now marked for deferred removal
to be automatically deactivated.
* Reencryption now limits hotzone size to be maximal 1 GiB or 1/4
system memory (if lower).
* Reencryption now retains activation flags during online reencryption.
* Reencryption now allows LUKS2 device to activate device right after
LUKS2 encryption is initialized through optional active device name
for cryptsetup reencrypt --encrypt command.
This could help with automated encryption during boot.
NOTE: It means that part of the device is still not encrypted during
activation. Use with care!
* Fixes failure in resize and plain format activation if activated device
size was not aligned to underlying logical device size.
* Fixes conversion to LUKS2 format with detached header if a detached
header size was smaller than the expected aligned LUKS1 header size.

110
lib/Makemodule.am Normal file
View File

@ -0,0 +1,110 @@
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = lib/libcryptsetup.pc
lib_LTLIBRARIES = libcryptsetup.la
noinst_LTLIBRARIES += libutils_io.la
include_HEADERS = lib/libcryptsetup.h
EXTRA_DIST += lib/libcryptsetup.pc.in lib/libcryptsetup.sym
libutils_io_la_CFLAGS = $(AM_CFLAGS)
libutils_io_la_SOURCES = \
lib/utils_io.c \
lib/utils_io.h
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
libcryptsetup_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined \
-Wl,--version-script=$(top_srcdir)/lib/libcryptsetup.sym \
-version-info @LIBCRYPTSETUP_VERSION_INFO@
libcryptsetup_la_CFLAGS = $(AM_CFLAGS) @CRYPTO_CFLAGS@
libcryptsetup_la_LIBADD = \
@UUID_LIBS@ \
@DEVMAPPER_LIBS@ \
@CRYPTO_LIBS@ \
@LIBARGON2_LIBS@ \
@JSON_C_LIBS@ \
@BLKID_LIBS@ \
libcrypto_backend.la \
libutils_io.la
libcryptsetup_la_SOURCES = \
lib/setup.c \
lib/internal.h \
lib/bitops.h \
lib/nls.h \
lib/libcryptsetup.h \
lib/utils.c \
lib/utils_benchmark.c \
lib/utils_crypt.c \
lib/utils_crypt.h \
lib/utils_loop.c \
lib/utils_loop.h \
lib/utils_devpath.c \
lib/utils_wipe.c \
lib/utils_fips.c \
lib/utils_fips.h \
lib/utils_device.c \
lib/utils_keyring.c \
lib/utils_keyring.h \
lib/utils_device_locking.c \
lib/utils_device_locking.h \
lib/utils_pbkdf.c \
lib/utils_storage_wrappers.c \
lib/utils_storage_wrappers.h \
lib/libdevmapper.c \
lib/utils_dm.h \
lib/volumekey.c \
lib/random.c \
lib/crypt_plain.c \
lib/base64.h \
lib/base64.c \
lib/integrity/integrity.h \
lib/integrity/integrity.c \
lib/loopaes/loopaes.h \
lib/loopaes/loopaes.c \
lib/tcrypt/tcrypt.h \
lib/tcrypt/tcrypt.c \
lib/luks1/af.h \
lib/luks1/af.c \
lib/luks1/keyencryption.c \
lib/luks1/keymanage.c \
lib/luks1/luks.h \
lib/verity/verity_hash.c \
lib/verity/verity_fec.c \
lib/verity/verity.c \
lib/verity/verity.h \
lib/verity/rs_encode_char.c \
lib/verity/rs_decode_char.c \
lib/verity/rs.h \
lib/luks2/luks2_disk_metadata.c \
lib/luks2/luks2_json_format.c \
lib/luks2/luks2_json_metadata.c \
lib/luks2/luks2_luks1_convert.c \
lib/luks2/luks2_digest.c \
lib/luks2/luks2_digest_pbkdf2.c \
lib/luks2/luks2_keyslot.c \
lib/luks2/luks2_keyslot_luks2.c \
lib/luks2/luks2_keyslot_reenc.c \
lib/luks2/luks2_reencrypt.c \
lib/luks2/luks2_segment.c \
lib/luks2/luks2_token_keyring.c \
lib/luks2/luks2_token.c \
lib/luks2/luks2_internal.h \
lib/luks2/luks2.h \
lib/utils_blkid.c \
lib/utils_blkid.h

605
lib/base64.c Normal file
View File

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

68
lib/base64.h Normal file
View File

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

123
lib/bitops.h Normal file
View File

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

117
lib/crypt_plain.c Normal file
View File

@ -0,0 +1,117 @@
/*
* cryptsetup plain device helper functions
*
* Copyright (C) 2004 Jana Saout <jana@saout.de>
* 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
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include "libcryptsetup.h"
#include "internal.h"
static int hash(const char *hash_name, size_t key_size, char *key,
size_t passphrase_size, const char *passphrase)
{
struct crypt_hash *md = NULL;
size_t len;
int round, i, r = 0;
if (crypt_hash_init(&md, hash_name))
return -ENOENT;
len = crypt_hash_size(hash_name);
for(round = 0; key_size && !r; round++) {
/* hack from hashalot to avoid null bytes in key */
for(i = 0; i < round; i++)
if (crypt_hash_write(md, "A", 1))
r = 1;
if (crypt_hash_write(md, passphrase, passphrase_size))
r = 1;
if (len > key_size)
len = key_size;
if (crypt_hash_final(md, key, len))
r = 1;
key += len;
key_size -= len;
}
crypt_hash_destroy(md);
return r;
}
#define PLAIN_HASH_LEN_MAX 256
int crypt_plain_hash(struct crypt_device *cd,
const char *hash_name,
char *key, size_t key_size,
const char *passphrase, size_t passphrase_size)
{
char hash_name_buf[PLAIN_HASH_LEN_MAX], *s;
size_t hash_size, pad_size;
int r;
log_dbg(cd, "Plain: hashing passphrase using %s.", hash_name);
if (strlen(hash_name) >= PLAIN_HASH_LEN_MAX)
return -EINVAL;
strncpy(hash_name_buf, hash_name, PLAIN_HASH_LEN_MAX);
hash_name_buf[PLAIN_HASH_LEN_MAX - 1] = '\0';
/* hash[:hash_length] */
if ((s = strchr(hash_name_buf, ':'))) {
*s = '\0';
s++;
if (!*s || sscanf(s, "%zd", &hash_size) != 1) {
log_dbg(cd, "Hash length is not a number");
return -EINVAL;
}
if (hash_size > key_size) {
log_dbg(cd, "Hash length %zd > key length %zd",
hash_size, key_size);
return -EINVAL;
}
pad_size = key_size - hash_size;
} else {
hash_size = key_size;
pad_size = 0;
}
/* No hash, copy passphrase directly */
if (!strcmp(hash_name_buf, "plain")) {
if (passphrase_size < hash_size) {
log_dbg(cd, "Too short plain passphrase.");
return -EINVAL;
}
memcpy(key, passphrase, hash_size);
r = 0;
} else
r = hash(hash_name_buf, hash_size, key, passphrase_size, passphrase);
if (r == 0 && pad_size)
memset(key + hash_size, 0, pad_size);
return r;
}

View File

@ -0,0 +1,39 @@
noinst_LTLIBRARIES += libcrypto_backend.la
libcrypto_backend_la_CFLAGS = $(AM_CFLAGS) @CRYPTO_CFLAGS@
libcrypto_backend_la_SOURCES = \
lib/crypto_backend/crypto_backend.h \
lib/crypto_backend/crypto_backend_internal.h \
lib/crypto_backend/crypto_cipher_kernel.c \
lib/crypto_backend/crypto_storage.c \
lib/crypto_backend/pbkdf_check.c \
lib/crypto_backend/crc32.c \
lib/crypto_backend/argon2_generic.c \
lib/crypto_backend/cipher_generic.c \
lib/crypto_backend/cipher_check.c
if CRYPTO_BACKEND_GCRYPT
libcrypto_backend_la_SOURCES += lib/crypto_backend/crypto_gcrypt.c
endif
if CRYPTO_BACKEND_OPENSSL
libcrypto_backend_la_SOURCES += lib/crypto_backend/crypto_openssl.c
endif
if CRYPTO_BACKEND_NSS
libcrypto_backend_la_SOURCES += lib/crypto_backend/crypto_nss.c
endif
if CRYPTO_BACKEND_KERNEL
libcrypto_backend_la_SOURCES += lib/crypto_backend/crypto_kernel.c
endif
if CRYPTO_BACKEND_NETTLE
libcrypto_backend_la_SOURCES += lib/crypto_backend/crypto_nettle.c
endif
if CRYPTO_INTERNAL_PBKDF2
libcrypto_backend_la_SOURCES += lib/crypto_backend/pbkdf2_generic.c
endif
if CRYPTO_INTERNAL_ARGON2
libcrypto_backend_la_DEPENDENCIES = libargon2.la
libcrypto_backend_la_LIBADD = libargon2.la
endif

View File

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

View File

@ -0,0 +1,30 @@
noinst_LTLIBRARIES += libargon2.la
libargon2_la_CFLAGS = $(AM_CFLAGS) -std=c89 -pthread -O3
libargon2_la_CPPFLAGS = $(AM_CPPFLAGS) \
-I lib/crypto_backend/argon2 \
-I lib/crypto_backend/argon2/blake2
libargon2_la_SOURCES = \
lib/crypto_backend/argon2/blake2/blake2b.c \
lib/crypto_backend/argon2/blake2/blake2.h \
lib/crypto_backend/argon2/blake2/blake2-impl.h \
lib/crypto_backend/argon2/argon2.c \
lib/crypto_backend/argon2/argon2.h \
lib/crypto_backend/argon2/core.c \
lib/crypto_backend/argon2/core.h \
lib/crypto_backend/argon2/encoding.c \
lib/crypto_backend/argon2/encoding.h \
lib/crypto_backend/argon2/thread.c \
lib/crypto_backend/argon2/thread.h
if CRYPTO_INTERNAL_SSE_ARGON2
libargon2_la_SOURCES += lib/crypto_backend/argon2/blake2/blamka-round-opt.h \
lib/crypto_backend/argon2/opt.c
else
libargon2_la_SOURCES += lib/crypto_backend/argon2/blake2/blamka-round-ref.h \
lib/crypto_backend/argon2/ref.c
endif
EXTRA_DIST += lib/crypto_backend/argon2/LICENSE
EXTRA_DIST += lib/crypto_backend/argon2/README

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,471 @@
/*
* Argon2 reference source code package - reference C implementations
*
* Copyright 2015
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
*
* You may use this work under the terms of a Creative Commons CC0 1.0
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
* these licenses can be found at:
*
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
*
* You should have received a copy of both of these licenses along with this
* software. If not, they may be obtained at the above URLs.
*/
#ifndef BLAKE_ROUND_MKA_OPT_H
#define BLAKE_ROUND_MKA_OPT_H
#include "blake2-impl.h"
#include <emmintrin.h>
#if defined(__SSSE3__)
#include <tmmintrin.h> /* for _mm_shuffle_epi8 and _mm_alignr_epi8 */
#endif
#if defined(__XOP__) && (defined(__GNUC__) || defined(__clang__))
#include <x86intrin.h>
#endif
#if !defined(__AVX512F__)
#if !defined(__AVX2__)
#if !defined(__XOP__)
#if defined(__SSSE3__)
#define r16 \
(_mm_setr_epi8(2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9))
#define r24 \
(_mm_setr_epi8(3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10))
#define _mm_roti_epi64(x, c) \
(-(c) == 32) \
? _mm_shuffle_epi32((x), _MM_SHUFFLE(2, 3, 0, 1)) \
: (-(c) == 24) \
? _mm_shuffle_epi8((x), r24) \
: (-(c) == 16) \
? _mm_shuffle_epi8((x), r16) \
: (-(c) == 63) \
? _mm_xor_si128(_mm_srli_epi64((x), -(c)), \
_mm_add_epi64((x), (x))) \
: _mm_xor_si128(_mm_srli_epi64((x), -(c)), \
_mm_slli_epi64((x), 64 - (-(c))))
#else /* defined(__SSE2__) */
#define _mm_roti_epi64(r, c) \
_mm_xor_si128(_mm_srli_epi64((r), -(c)), _mm_slli_epi64((r), 64 - (-(c))))
#endif
#else
#endif
static BLAKE2_INLINE __m128i fBlaMka(__m128i x, __m128i y) {
const __m128i z = _mm_mul_epu32(x, y);
return _mm_add_epi64(_mm_add_epi64(x, y), _mm_add_epi64(z, z));
}
#define G1(A0, B0, C0, D0, A1, B1, C1, D1) \
do { \
A0 = fBlaMka(A0, B0); \
A1 = fBlaMka(A1, B1); \
\
D0 = _mm_xor_si128(D0, A0); \
D1 = _mm_xor_si128(D1, A1); \
\
D0 = _mm_roti_epi64(D0, -32); \
D1 = _mm_roti_epi64(D1, -32); \
\
C0 = fBlaMka(C0, D0); \
C1 = fBlaMka(C1, D1); \
\
B0 = _mm_xor_si128(B0, C0); \
B1 = _mm_xor_si128(B1, C1); \
\
B0 = _mm_roti_epi64(B0, -24); \
B1 = _mm_roti_epi64(B1, -24); \
} while ((void)0, 0)
#define G2(A0, B0, C0, D0, A1, B1, C1, D1) \
do { \
A0 = fBlaMka(A0, B0); \
A1 = fBlaMka(A1, B1); \
\
D0 = _mm_xor_si128(D0, A0); \
D1 = _mm_xor_si128(D1, A1); \
\
D0 = _mm_roti_epi64(D0, -16); \
D1 = _mm_roti_epi64(D1, -16); \
\
C0 = fBlaMka(C0, D0); \
C1 = fBlaMka(C1, D1); \
\
B0 = _mm_xor_si128(B0, C0); \
B1 = _mm_xor_si128(B1, C1); \
\
B0 = _mm_roti_epi64(B0, -63); \
B1 = _mm_roti_epi64(B1, -63); \
} while ((void)0, 0)
#if defined(__SSSE3__)
#define DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
do { \
__m128i t0 = _mm_alignr_epi8(B1, B0, 8); \
__m128i t1 = _mm_alignr_epi8(B0, B1, 8); \
B0 = t0; \
B1 = t1; \
\
t0 = C0; \
C0 = C1; \
C1 = t0; \
\
t0 = _mm_alignr_epi8(D1, D0, 8); \
t1 = _mm_alignr_epi8(D0, D1, 8); \
D0 = t1; \
D1 = t0; \
} while ((void)0, 0)
#define UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
do { \
__m128i t0 = _mm_alignr_epi8(B0, B1, 8); \
__m128i t1 = _mm_alignr_epi8(B1, B0, 8); \
B0 = t0; \
B1 = t1; \
\
t0 = C0; \
C0 = C1; \
C1 = t0; \
\
t0 = _mm_alignr_epi8(D0, D1, 8); \
t1 = _mm_alignr_epi8(D1, D0, 8); \
D0 = t1; \
D1 = t0; \
} while ((void)0, 0)
#else /* SSE2 */
#define DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
do { \
__m128i t0 = D0; \
__m128i t1 = B0; \
D0 = C0; \
C0 = C1; \
C1 = D0; \
D0 = _mm_unpackhi_epi64(D1, _mm_unpacklo_epi64(t0, t0)); \
D1 = _mm_unpackhi_epi64(t0, _mm_unpacklo_epi64(D1, D1)); \
B0 = _mm_unpackhi_epi64(B0, _mm_unpacklo_epi64(B1, B1)); \
B1 = _mm_unpackhi_epi64(B1, _mm_unpacklo_epi64(t1, t1)); \
} while ((void)0, 0)
#define UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
do { \
__m128i t0, t1; \
t0 = C0; \
C0 = C1; \
C1 = t0; \
t0 = B0; \
t1 = D0; \
B0 = _mm_unpackhi_epi64(B1, _mm_unpacklo_epi64(B0, B0)); \
B1 = _mm_unpackhi_epi64(t0, _mm_unpacklo_epi64(B1, B1)); \
D0 = _mm_unpackhi_epi64(D0, _mm_unpacklo_epi64(D1, D1)); \
D1 = _mm_unpackhi_epi64(D1, _mm_unpacklo_epi64(t1, t1)); \
} while ((void)0, 0)
#endif
#define BLAKE2_ROUND(A0, A1, B0, B1, C0, C1, D0, D1) \
do { \
G1(A0, B0, C0, D0, A1, B1, C1, D1); \
G2(A0, B0, C0, D0, A1, B1, C1, D1); \
\
DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1); \
\
G1(A0, B0, C0, D0, A1, B1, C1, D1); \
G2(A0, B0, C0, D0, A1, B1, C1, D1); \
\
UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1); \
} while ((void)0, 0)
#else /* __AVX2__ */
#include <immintrin.h>
#define rotr32(x) _mm256_shuffle_epi32(x, _MM_SHUFFLE(2, 3, 0, 1))
#define rotr24(x) _mm256_shuffle_epi8(x, _mm256_setr_epi8(3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10, 3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10))
#define rotr16(x) _mm256_shuffle_epi8(x, _mm256_setr_epi8(2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9, 2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9))
#define rotr63(x) _mm256_xor_si256(_mm256_srli_epi64((x), 63), _mm256_add_epi64((x), (x)))
#define G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
do { \
__m256i ml = _mm256_mul_epu32(A0, B0); \
ml = _mm256_add_epi64(ml, ml); \
A0 = _mm256_add_epi64(A0, _mm256_add_epi64(B0, ml)); \
D0 = _mm256_xor_si256(D0, A0); \
D0 = rotr32(D0); \
\
ml = _mm256_mul_epu32(C0, D0); \
ml = _mm256_add_epi64(ml, ml); \
C0 = _mm256_add_epi64(C0, _mm256_add_epi64(D0, ml)); \
\
B0 = _mm256_xor_si256(B0, C0); \
B0 = rotr24(B0); \
\
ml = _mm256_mul_epu32(A1, B1); \
ml = _mm256_add_epi64(ml, ml); \
A1 = _mm256_add_epi64(A1, _mm256_add_epi64(B1, ml)); \
D1 = _mm256_xor_si256(D1, A1); \
D1 = rotr32(D1); \
\
ml = _mm256_mul_epu32(C1, D1); \
ml = _mm256_add_epi64(ml, ml); \
C1 = _mm256_add_epi64(C1, _mm256_add_epi64(D1, ml)); \
\
B1 = _mm256_xor_si256(B1, C1); \
B1 = rotr24(B1); \
} while((void)0, 0);
#define G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
do { \
__m256i ml = _mm256_mul_epu32(A0, B0); \
ml = _mm256_add_epi64(ml, ml); \
A0 = _mm256_add_epi64(A0, _mm256_add_epi64(B0, ml)); \
D0 = _mm256_xor_si256(D0, A0); \
D0 = rotr16(D0); \
\
ml = _mm256_mul_epu32(C0, D0); \
ml = _mm256_add_epi64(ml, ml); \
C0 = _mm256_add_epi64(C0, _mm256_add_epi64(D0, ml)); \
B0 = _mm256_xor_si256(B0, C0); \
B0 = rotr63(B0); \
\
ml = _mm256_mul_epu32(A1, B1); \
ml = _mm256_add_epi64(ml, ml); \
A1 = _mm256_add_epi64(A1, _mm256_add_epi64(B1, ml)); \
D1 = _mm256_xor_si256(D1, A1); \
D1 = rotr16(D1); \
\
ml = _mm256_mul_epu32(C1, D1); \
ml = _mm256_add_epi64(ml, ml); \
C1 = _mm256_add_epi64(C1, _mm256_add_epi64(D1, ml)); \
B1 = _mm256_xor_si256(B1, C1); \
B1 = rotr63(B1); \
} while((void)0, 0);
#define DIAGONALIZE_1(A0, B0, C0, D0, A1, B1, C1, D1) \
do { \
B0 = _mm256_permute4x64_epi64(B0, _MM_SHUFFLE(0, 3, 2, 1)); \
C0 = _mm256_permute4x64_epi64(C0, _MM_SHUFFLE(1, 0, 3, 2)); \
D0 = _mm256_permute4x64_epi64(D0, _MM_SHUFFLE(2, 1, 0, 3)); \
\
B1 = _mm256_permute4x64_epi64(B1, _MM_SHUFFLE(0, 3, 2, 1)); \
C1 = _mm256_permute4x64_epi64(C1, _MM_SHUFFLE(1, 0, 3, 2)); \
D1 = _mm256_permute4x64_epi64(D1, _MM_SHUFFLE(2, 1, 0, 3)); \
} while((void)0, 0);
#define DIAGONALIZE_2(A0, A1, B0, B1, C0, C1, D0, D1) \
do { \
__m256i tmp1 = _mm256_blend_epi32(B0, B1, 0xCC); \
__m256i tmp2 = _mm256_blend_epi32(B0, B1, 0x33); \
B1 = _mm256_permute4x64_epi64(tmp1, _MM_SHUFFLE(2,3,0,1)); \
B0 = _mm256_permute4x64_epi64(tmp2, _MM_SHUFFLE(2,3,0,1)); \
\
tmp1 = C0; \
C0 = C1; \
C1 = tmp1; \
\
tmp1 = _mm256_blend_epi32(D0, D1, 0xCC); \
tmp2 = _mm256_blend_epi32(D0, D1, 0x33); \
D0 = _mm256_permute4x64_epi64(tmp1, _MM_SHUFFLE(2,3,0,1)); \
D1 = _mm256_permute4x64_epi64(tmp2, _MM_SHUFFLE(2,3,0,1)); \
} while(0);
#define UNDIAGONALIZE_1(A0, B0, C0, D0, A1, B1, C1, D1) \
do { \
B0 = _mm256_permute4x64_epi64(B0, _MM_SHUFFLE(2, 1, 0, 3)); \
C0 = _mm256_permute4x64_epi64(C0, _MM_SHUFFLE(1, 0, 3, 2)); \
D0 = _mm256_permute4x64_epi64(D0, _MM_SHUFFLE(0, 3, 2, 1)); \
\
B1 = _mm256_permute4x64_epi64(B1, _MM_SHUFFLE(2, 1, 0, 3)); \
C1 = _mm256_permute4x64_epi64(C1, _MM_SHUFFLE(1, 0, 3, 2)); \
D1 = _mm256_permute4x64_epi64(D1, _MM_SHUFFLE(0, 3, 2, 1)); \
} while((void)0, 0);
#define UNDIAGONALIZE_2(A0, A1, B0, B1, C0, C1, D0, D1) \
do { \
__m256i tmp1 = _mm256_blend_epi32(B0, B1, 0xCC); \
__m256i tmp2 = _mm256_blend_epi32(B0, B1, 0x33); \
B0 = _mm256_permute4x64_epi64(tmp1, _MM_SHUFFLE(2,3,0,1)); \
B1 = _mm256_permute4x64_epi64(tmp2, _MM_SHUFFLE(2,3,0,1)); \
\
tmp1 = C0; \
C0 = C1; \
C1 = tmp1; \
\
tmp1 = _mm256_blend_epi32(D0, D1, 0x33); \
tmp2 = _mm256_blend_epi32(D0, D1, 0xCC); \
D0 = _mm256_permute4x64_epi64(tmp1, _MM_SHUFFLE(2,3,0,1)); \
D1 = _mm256_permute4x64_epi64(tmp2, _MM_SHUFFLE(2,3,0,1)); \
} while((void)0, 0);
#define BLAKE2_ROUND_1(A0, A1, B0, B1, C0, C1, D0, D1) \
do{ \
G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
\
DIAGONALIZE_1(A0, B0, C0, D0, A1, B1, C1, D1) \
\
G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
\
UNDIAGONALIZE_1(A0, B0, C0, D0, A1, B1, C1, D1) \
} while((void)0, 0);
#define BLAKE2_ROUND_2(A0, A1, B0, B1, C0, C1, D0, D1) \
do{ \
G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
\
DIAGONALIZE_2(A0, A1, B0, B1, C0, C1, D0, D1) \
\
G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
\
UNDIAGONALIZE_2(A0, A1, B0, B1, C0, C1, D0, D1) \
} while((void)0, 0);
#endif /* __AVX2__ */
#else /* __AVX512F__ */
#include <immintrin.h>
#define ror64(x, n) _mm512_ror_epi64((x), (n))
static __m512i muladd(__m512i x, __m512i y)
{
__m512i z = _mm512_mul_epu32(x, y);
return _mm512_add_epi64(_mm512_add_epi64(x, y), _mm512_add_epi64(z, z));
}
#define G1(A0, B0, C0, D0, A1, B1, C1, D1) \
do { \
A0 = muladd(A0, B0); \
A1 = muladd(A1, B1); \
\
D0 = _mm512_xor_si512(D0, A0); \
D1 = _mm512_xor_si512(D1, A1); \
\
D0 = ror64(D0, 32); \
D1 = ror64(D1, 32); \
\
C0 = muladd(C0, D0); \
C1 = muladd(C1, D1); \
\
B0 = _mm512_xor_si512(B0, C0); \
B1 = _mm512_xor_si512(B1, C1); \
\
B0 = ror64(B0, 24); \
B1 = ror64(B1, 24); \
} while ((void)0, 0)
#define G2(A0, B0, C0, D0, A1, B1, C1, D1) \
do { \
A0 = muladd(A0, B0); \
A1 = muladd(A1, B1); \
\
D0 = _mm512_xor_si512(D0, A0); \
D1 = _mm512_xor_si512(D1, A1); \
\
D0 = ror64(D0, 16); \
D1 = ror64(D1, 16); \
\
C0 = muladd(C0, D0); \
C1 = muladd(C1, D1); \
\
B0 = _mm512_xor_si512(B0, C0); \
B1 = _mm512_xor_si512(B1, C1); \
\
B0 = ror64(B0, 63); \
B1 = ror64(B1, 63); \
} while ((void)0, 0)
#define DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
do { \
B0 = _mm512_permutex_epi64(B0, _MM_SHUFFLE(0, 3, 2, 1)); \
B1 = _mm512_permutex_epi64(B1, _MM_SHUFFLE(0, 3, 2, 1)); \
\
C0 = _mm512_permutex_epi64(C0, _MM_SHUFFLE(1, 0, 3, 2)); \
C1 = _mm512_permutex_epi64(C1, _MM_SHUFFLE(1, 0, 3, 2)); \
\
D0 = _mm512_permutex_epi64(D0, _MM_SHUFFLE(2, 1, 0, 3)); \
D1 = _mm512_permutex_epi64(D1, _MM_SHUFFLE(2, 1, 0, 3)); \
} while ((void)0, 0)
#define UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
do { \
B0 = _mm512_permutex_epi64(B0, _MM_SHUFFLE(2, 1, 0, 3)); \
B1 = _mm512_permutex_epi64(B1, _MM_SHUFFLE(2, 1, 0, 3)); \
\
C0 = _mm512_permutex_epi64(C0, _MM_SHUFFLE(1, 0, 3, 2)); \
C1 = _mm512_permutex_epi64(C1, _MM_SHUFFLE(1, 0, 3, 2)); \
\
D0 = _mm512_permutex_epi64(D0, _MM_SHUFFLE(0, 3, 2, 1)); \
D1 = _mm512_permutex_epi64(D1, _MM_SHUFFLE(0, 3, 2, 1)); \
} while ((void)0, 0)
#define BLAKE2_ROUND(A0, B0, C0, D0, A1, B1, C1, D1) \
do { \
G1(A0, B0, C0, D0, A1, B1, C1, D1); \
G2(A0, B0, C0, D0, A1, B1, C1, D1); \
\
DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1); \
\
G1(A0, B0, C0, D0, A1, B1, C1, D1); \
G2(A0, B0, C0, D0, A1, B1, C1, D1); \
\
UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1); \
} while ((void)0, 0)
#define SWAP_HALVES(A0, A1) \
do { \
__m512i t0, t1; \
t0 = _mm512_shuffle_i64x2(A0, A1, _MM_SHUFFLE(1, 0, 1, 0)); \
t1 = _mm512_shuffle_i64x2(A0, A1, _MM_SHUFFLE(3, 2, 3, 2)); \
A0 = t0; \
A1 = t1; \
} while((void)0, 0)
#define SWAP_QUARTERS(A0, A1) \
do { \
SWAP_HALVES(A0, A1); \
A0 = _mm512_permutexvar_epi64(_mm512_setr_epi64(0, 1, 4, 5, 2, 3, 6, 7), A0); \
A1 = _mm512_permutexvar_epi64(_mm512_setr_epi64(0, 1, 4, 5, 2, 3, 6, 7), A1); \
} while((void)0, 0)
#define UNSWAP_QUARTERS(A0, A1) \
do { \
A0 = _mm512_permutexvar_epi64(_mm512_setr_epi64(0, 1, 4, 5, 2, 3, 6, 7), A0); \
A1 = _mm512_permutexvar_epi64(_mm512_setr_epi64(0, 1, 4, 5, 2, 3, 6, 7), A1); \
SWAP_HALVES(A0, A1); \
} while((void)0, 0)
#define BLAKE2_ROUND_1(A0, C0, B0, D0, A1, C1, B1, D1) \
do { \
SWAP_HALVES(A0, B0); \
SWAP_HALVES(C0, D0); \
SWAP_HALVES(A1, B1); \
SWAP_HALVES(C1, D1); \
BLAKE2_ROUND(A0, B0, C0, D0, A1, B1, C1, D1); \
SWAP_HALVES(A0, B0); \
SWAP_HALVES(C0, D0); \
SWAP_HALVES(A1, B1); \
SWAP_HALVES(C1, D1); \
} while ((void)0, 0)
#define BLAKE2_ROUND_2(A0, A1, B0, B1, C0, C1, D0, D1) \
do { \
SWAP_QUARTERS(A0, A1); \
SWAP_QUARTERS(B0, B1); \
SWAP_QUARTERS(C0, C1); \
SWAP_QUARTERS(D0, D1); \
BLAKE2_ROUND(A0, B0, C0, D0, A1, B1, C1, D1); \
UNSWAP_QUARTERS(A0, A1); \
UNSWAP_QUARTERS(B0, B1); \
UNSWAP_QUARTERS(C0, C1); \
UNSWAP_QUARTERS(D0, D1); \
} while ((void)0, 0)
#endif /* __AVX512F__ */
#endif /* BLAKE_ROUND_MKA_OPT_H */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,283 @@
/*
* Argon2 reference source code package - reference C implementations
*
* Copyright 2015
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
*
* You may use this work under the terms of a Creative Commons CC0 1.0
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
* these licenses can be found at:
*
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
*
* You should have received a copy of both of these licenses along with this
* software. If not, they may be obtained at the above URLs.
*/
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include "argon2.h"
#include "core.h"
#include "blake2/blake2.h"
#include "blake2/blamka-round-opt.h"
/*
* Function fills a new memory block and optionally XORs the old block over the new one.
* Memory must be initialized.
* @param state Pointer to the just produced block. Content will be updated(!)
* @param ref_block Pointer to the reference block
* @param next_block Pointer to the block to be XORed over. May coincide with @ref_block
* @param with_xor Whether to XOR into the new block (1) or just overwrite (0)
* @pre all block pointers must be valid
*/
#if defined(__AVX512F__)
static void fill_block(__m512i *state, const block *ref_block,
block *next_block, int with_xor) {
__m512i block_XY[ARGON2_512BIT_WORDS_IN_BLOCK];
unsigned int i;
if (with_xor) {
for (i = 0; i < ARGON2_512BIT_WORDS_IN_BLOCK; i++) {
state[i] = _mm512_xor_si512(
state[i], _mm512_loadu_si512((const __m512i *)ref_block->v + i));
block_XY[i] = _mm512_xor_si512(
state[i], _mm512_loadu_si512((const __m512i *)next_block->v + i));
}
} else {
for (i = 0; i < ARGON2_512BIT_WORDS_IN_BLOCK; i++) {
block_XY[i] = state[i] = _mm512_xor_si512(
state[i], _mm512_loadu_si512((const __m512i *)ref_block->v + i));
}
}
for (i = 0; i < 2; ++i) {
BLAKE2_ROUND_1(
state[8 * i + 0], state[8 * i + 1], state[8 * i + 2], state[8 * i + 3],
state[8 * i + 4], state[8 * i + 5], state[8 * i + 6], state[8 * i + 7]);
}
for (i = 0; i < 2; ++i) {
BLAKE2_ROUND_2(
state[2 * 0 + i], state[2 * 1 + i], state[2 * 2 + i], state[2 * 3 + i],
state[2 * 4 + i], state[2 * 5 + i], state[2 * 6 + i], state[2 * 7 + i]);
}
for (i = 0; i < ARGON2_512BIT_WORDS_IN_BLOCK; i++) {
state[i] = _mm512_xor_si512(state[i], block_XY[i]);
_mm512_storeu_si512((__m512i *)next_block->v + i, state[i]);
}
}
#elif defined(__AVX2__)
static void fill_block(__m256i *state, const block *ref_block,
block *next_block, int with_xor) {
__m256i block_XY[ARGON2_HWORDS_IN_BLOCK];
unsigned int i;
if (with_xor) {
for (i = 0; i < ARGON2_HWORDS_IN_BLOCK; i++) {
state[i] = _mm256_xor_si256(
state[i], _mm256_loadu_si256((const __m256i *)ref_block->v + i));
block_XY[i] = _mm256_xor_si256(
state[i], _mm256_loadu_si256((const __m256i *)next_block->v + i));
}
} else {
for (i = 0; i < ARGON2_HWORDS_IN_BLOCK; i++) {
block_XY[i] = state[i] = _mm256_xor_si256(
state[i], _mm256_loadu_si256((const __m256i *)ref_block->v + i));
}
}
for (i = 0; i < 4; ++i) {
BLAKE2_ROUND_1(state[8 * i + 0], state[8 * i + 4], state[8 * i + 1], state[8 * i + 5],
state[8 * i + 2], state[8 * i + 6], state[8 * i + 3], state[8 * i + 7]);
}
for (i = 0; i < 4; ++i) {
BLAKE2_ROUND_2(state[ 0 + i], state[ 4 + i], state[ 8 + i], state[12 + i],
state[16 + i], state[20 + i], state[24 + i], state[28 + i]);
}
for (i = 0; i < ARGON2_HWORDS_IN_BLOCK; i++) {
state[i] = _mm256_xor_si256(state[i], block_XY[i]);
_mm256_storeu_si256((__m256i *)next_block->v + i, state[i]);
}
}
#else
static void fill_block(__m128i *state, const block *ref_block,
block *next_block, int with_xor) {
__m128i block_XY[ARGON2_OWORDS_IN_BLOCK];
unsigned int i;
if (with_xor) {
for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) {
state[i] = _mm_xor_si128(
state[i], _mm_loadu_si128((const __m128i *)ref_block->v + i));
block_XY[i] = _mm_xor_si128(
state[i], _mm_loadu_si128((const __m128i *)next_block->v + i));
}
} else {
for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) {
block_XY[i] = state[i] = _mm_xor_si128(
state[i], _mm_loadu_si128((const __m128i *)ref_block->v + i));
}
}
for (i = 0; i < 8; ++i) {
BLAKE2_ROUND(state[8 * i + 0], state[8 * i + 1], state[8 * i + 2],
state[8 * i + 3], state[8 * i + 4], state[8 * i + 5],
state[8 * i + 6], state[8 * i + 7]);
}
for (i = 0; i < 8; ++i) {
BLAKE2_ROUND(state[8 * 0 + i], state[8 * 1 + i], state[8 * 2 + i],
state[8 * 3 + i], state[8 * 4 + i], state[8 * 5 + i],
state[8 * 6 + i], state[8 * 7 + i]);
}
for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) {
state[i] = _mm_xor_si128(state[i], block_XY[i]);
_mm_storeu_si128((__m128i *)next_block->v + i, state[i]);
}
}
#endif
static void next_addresses(block *address_block, block *input_block) {
/*Temporary zero-initialized blocks*/
#if defined(__AVX512F__)
__m512i zero_block[ARGON2_512BIT_WORDS_IN_BLOCK];
__m512i zero2_block[ARGON2_512BIT_WORDS_IN_BLOCK];
#elif defined(__AVX2__)
__m256i zero_block[ARGON2_HWORDS_IN_BLOCK];
__m256i zero2_block[ARGON2_HWORDS_IN_BLOCK];
#else
__m128i zero_block[ARGON2_OWORDS_IN_BLOCK];
__m128i zero2_block[ARGON2_OWORDS_IN_BLOCK];
#endif
memset(zero_block, 0, sizeof(zero_block));
memset(zero2_block, 0, sizeof(zero2_block));
/*Increasing index counter*/
input_block->v[6]++;
/*First iteration of G*/
fill_block(zero_block, input_block, address_block, 0);
/*Second iteration of G*/
fill_block(zero2_block, address_block, address_block, 0);
}
void fill_segment(const argon2_instance_t *instance,
argon2_position_t position) {
block *ref_block = NULL, *curr_block = NULL;
block address_block, input_block;
uint64_t pseudo_rand, ref_index, ref_lane;
uint32_t prev_offset, curr_offset;
uint32_t starting_index, i;
#if defined(__AVX512F__)
__m512i state[ARGON2_512BIT_WORDS_IN_BLOCK];
#elif defined(__AVX2__)
__m256i state[ARGON2_HWORDS_IN_BLOCK];
#else
__m128i state[ARGON2_OWORDS_IN_BLOCK];
#endif
int data_independent_addressing;
if (instance == NULL) {
return;
}
data_independent_addressing =
(instance->type == Argon2_i) ||
(instance->type == Argon2_id && (position.pass == 0) &&
(position.slice < ARGON2_SYNC_POINTS / 2));
if (data_independent_addressing) {
init_block_value(&input_block, 0);
input_block.v[0] = position.pass;
input_block.v[1] = position.lane;
input_block.v[2] = position.slice;
input_block.v[3] = instance->memory_blocks;
input_block.v[4] = instance->passes;
input_block.v[5] = instance->type;
}
starting_index = 0;
if ((0 == position.pass) && (0 == position.slice)) {
starting_index = 2; /* we have already generated the first two blocks */
/* Don't forget to generate the first block of addresses: */
if (data_independent_addressing) {
next_addresses(&address_block, &input_block);
}
}
/* Offset of the current block */
curr_offset = position.lane * instance->lane_length +
position.slice * instance->segment_length + starting_index;
if (0 == curr_offset % instance->lane_length) {
/* Last block in this lane */
prev_offset = curr_offset + instance->lane_length - 1;
} else {
/* Previous block */
prev_offset = curr_offset - 1;
}
memcpy(state, ((instance->memory + prev_offset)->v), ARGON2_BLOCK_SIZE);
for (i = starting_index; i < instance->segment_length;
++i, ++curr_offset, ++prev_offset) {
/*1.1 Rotating prev_offset if needed */
if (curr_offset % instance->lane_length == 1) {
prev_offset = curr_offset - 1;
}
/* 1.2 Computing the index of the reference block */
/* 1.2.1 Taking pseudo-random value from the previous block */
if (data_independent_addressing) {
if (i % ARGON2_ADDRESSES_IN_BLOCK == 0) {
next_addresses(&address_block, &input_block);
}
pseudo_rand = address_block.v[i % ARGON2_ADDRESSES_IN_BLOCK];
} else {
pseudo_rand = instance->memory[prev_offset].v[0];
}
/* 1.2.2 Computing the lane of the reference block */
ref_lane = ((pseudo_rand >> 32)) % instance->lanes;
if ((position.pass == 0) && (position.slice == 0)) {
/* Can not reference other lanes yet */
ref_lane = position.lane;
}
/* 1.2.3 Computing the number of possible reference block within the
* lane.
*/
position.index = i;
ref_index = index_alpha(instance, &position, pseudo_rand & 0xFFFFFFFF,
ref_lane == position.lane);
/* 2 Creating a new block */
ref_block =
instance->memory + instance->lane_length * ref_lane + ref_index;
curr_block = instance->memory + curr_offset;
if (ARGON2_VERSION_10 == instance->version) {
/* version 1.2.1 and earlier: overwrite, not XOR */
fill_block(state, ref_block, curr_block, 0);
} else {
if(0 == position.pass) {
fill_block(state, ref_block, curr_block, 0);
} else {
fill_block(state, ref_block, curr_block, 1);
}
}
}
}

View File

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

View File

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

View File

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

View File

@ -0,0 +1,79 @@
/*
* Argon2 PBKDF2 library wrapper
*
* 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
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this file; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <errno.h>
#include "crypto_backend_internal.h"
#if HAVE_ARGON2_H
#include <argon2.h>
#else
#include "argon2/argon2.h"
#endif
#define CONST_CAST(x) (x)(uintptr_t)
int argon2(const char *type, const char *password, size_t password_length,
const char *salt, size_t salt_length,
char *key, size_t key_length,
uint32_t iterations, uint32_t memory, uint32_t parallel)
{
#if !USE_INTERNAL_ARGON2 && !HAVE_ARGON2_H
return -EINVAL;
#else
argon2_type atype;
argon2_context context = {
.flags = ARGON2_DEFAULT_FLAGS,
.version = ARGON2_VERSION_NUMBER,
.t_cost = (uint32_t)iterations,
.m_cost = (uint32_t)memory,
.lanes = (uint32_t)parallel,
.threads = (uint32_t)parallel,
.out = (uint8_t *)key,
.outlen = (uint32_t)key_length,
.pwd = CONST_CAST(uint8_t *)password,
.pwdlen = (uint32_t)password_length,
.salt = CONST_CAST(uint8_t *)salt,
.saltlen = (uint32_t)salt_length,
};
int r;
if (!strcmp(type, "argon2i"))
atype = Argon2_i;
else if(!strcmp(type, "argon2id"))
atype = Argon2_id;
else
return -EINVAL;
switch (argon2_ctx(&context, atype)) {
case ARGON2_OK:
r = 0;
break;
case ARGON2_MEMORY_ALLOCATION_ERROR:
case ARGON2_FREE_MEMORY_CBK_NULL:
case ARGON2_ALLOCATE_MEMORY_CBK_NULL:
r = -ENOMEM;
break;
default:
r = -EINVAL;
}
return r;
#endif
}

View File

@ -0,0 +1,157 @@
/*
* Cipher performance check
*
* 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
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this file; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <errno.h>
#include <time.h>
#include "crypto_backend_internal.h"
/*
* This is not simulating storage, so using disk block causes extreme overhead.
* Let's use some fixed block size where results are more reliable...
*/
#define CIPHER_BLOCK_BYTES 65536
/*
* If the measured value is lower, encrypted buffer is probably too small
* and calculated values are not reliable.
*/
#define CIPHER_TIME_MIN_MS 0.001
/*
* The whole test depends on Linux kernel usermode crypto API for now.
* (The same implementations are used in dm-crypt though.)
*/
static int time_ms(struct timespec *start, struct timespec *end, double *ms)
{
double start_ms, end_ms;
start_ms = start->tv_sec * 1000.0 + start->tv_nsec / (1000.0 * 1000);
end_ms = end->tv_sec * 1000.0 + end->tv_nsec / (1000.0 * 1000);
*ms = end_ms - start_ms;
return 0;
}
static int cipher_perf_one(const char *name, const char *mode, char *buffer, size_t buffer_size,
const char *key, size_t key_size, const char *iv, size_t iv_size, int enc)
{
struct crypt_cipher_kernel cipher;
size_t done = 0, block = CIPHER_BLOCK_BYTES;
int r;
if (buffer_size < block)
block = buffer_size;
r = crypt_cipher_init_kernel(&cipher, name, mode, key, key_size);
if (r < 0)
return r;
while (done < buffer_size) {
if ((done + block) > buffer_size)
block = buffer_size - done;
if (enc)
r = crypt_cipher_encrypt_kernel(&cipher, &buffer[done], &buffer[done],
block, iv, iv_size);
else
r = crypt_cipher_decrypt_kernel(&cipher, &buffer[done], &buffer[done],
block, iv, iv_size);
if (r < 0)
break;
done += block;
}
crypt_cipher_destroy_kernel(&cipher);
return r;
}
static int cipher_measure(const char *name, const char *mode, char *buffer, size_t buffer_size,
const char *key, size_t key_size, const char *iv, size_t iv_size,
int encrypt, double *ms)
{
struct timespec start, end;
int r;
/*
* Using getrusage would be better here but the precision
* is not adequate, so better stick with CLOCK_MONOTONIC
*/
if (clock_gettime(CLOCK_MONOTONIC_RAW, &start) < 0)
return -EINVAL;
r = cipher_perf_one(name, mode, buffer, buffer_size, key, key_size, iv, iv_size, encrypt);
if (r < 0)
return r;
if (clock_gettime(CLOCK_MONOTONIC_RAW, &end) < 0)
return -EINVAL;
r = time_ms(&start, &end, ms);
if (r < 0)
return r;
if (*ms < CIPHER_TIME_MIN_MS)
return -ERANGE;
return 0;
}
static double speed_mbs(unsigned long bytes, double ms)
{
double speed = bytes, s = ms / 1000.;
return speed / (1024 * 1024) / s;
}
int crypt_cipher_perf_kernel(const char *name, const char *mode, char *buffer, size_t buffer_size,
const char *key, size_t key_size, const char *iv, size_t iv_size,
double *encryption_mbs, double *decryption_mbs)
{
double ms_enc, ms_dec, ms;
int r, repeat_enc, repeat_dec;
ms_enc = 0.0;
repeat_enc = 1;
while (ms_enc < 1000.0) {
r = cipher_measure(name, mode, buffer, buffer_size, key, key_size, iv, iv_size, 1, &ms);
if (r < 0)
return r;
ms_enc += ms;
repeat_enc++;
}
ms_dec = 0.0;
repeat_dec = 1;
while (ms_dec < 1000.0) {
r = cipher_measure(name, mode, buffer, buffer_size, key, key_size, iv, iv_size, 0, &ms);
if (r < 0)
return r;
ms_dec += ms;
repeat_dec++;
}
*encryption_mbs = speed_mbs(buffer_size * repeat_enc, ms_enc);
*decryption_mbs = speed_mbs(buffer_size * repeat_dec, ms_dec);
return 0;
}

View File

@ -0,0 +1,83 @@
/*
* Linux kernel cipher generic utilities
*
* 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
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this file; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <string.h>
#include <stdbool.h>
#include <errno.h>
#include "crypto_backend.h"
struct cipher_alg {
const char *name;
const char *mode;
int blocksize;
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 },
{ "serpent", NULL, 16, false },
{ "twofish", NULL, 16, false },
{ "anubis", NULL, 16, false },
{ "blowfish", NULL, 8, false },
{ "camellia", NULL, 16, false },
{ "cast5", NULL, 8, false },
{ "cast6", NULL, 16, false },
{ "des", NULL, 8, false },
{ "des3_ede", NULL, 8, false },
{ "khazad", NULL, 8, false },
{ "seed", NULL, 16, false },
{ "tea", NULL, 8, false },
{ "xtea", NULL, 8, false },
{ "paes", NULL, 16, true }, /* protected AES, s390 wrapped key scheme */
{ "xchacha12,aes", "adiantum", 32, false },
{ "xchacha20,aes", "adiantum", 32, false },
{ NULL, NULL, 0, false }
};
static const struct cipher_alg *_get_alg(const char *name, const char *mode)
{
int i = 0;
while (name && cipher_algs[i].name) {
if (!strcasecmp(name, cipher_algs[i].name))
if (!mode || !cipher_algs[i].mode ||
!strncasecmp(mode, cipher_algs[i].mode, strlen(cipher_algs[i].mode)))
return &cipher_algs[i];
i++;
}
return NULL;
}
int crypt_cipher_ivsize(const char *name, const char *mode)
{
const struct cipher_alg *ca = _get_alg(name, mode);
return ca ? ca->blocksize : -EINVAL;
}
int crypt_cipher_wrapped_key(const char *name, const char *mode)
{
const struct cipher_alg *ca = _get_alg(name, mode);
return ca ? (int)ca->wrapped_key : 0;
}

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

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

View File

@ -0,0 +1,133 @@
/*
* crypto backend implementation
*
* 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
* 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 _CRYPTO_BACKEND_H
#define _CRYPTO_BACKEND_H
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
struct crypt_device;
struct crypt_hash;
struct crypt_hmac;
struct crypt_cipher;
struct crypt_storage;
int crypt_backend_init(struct crypt_device *ctx);
void crypt_backend_destroy(void);
#define CRYPT_BACKEND_KERNEL (1 << 0) /* Crypto uses kernel part, for benchmark */
uint32_t crypt_backend_flags(void);
const char *crypt_backend_version(void);
/* HASH */
int crypt_hash_size(const char *name);
int crypt_hash_init(struct crypt_hash **ctx, const char *name);
int crypt_hash_write(struct crypt_hash *ctx, const char *buffer, size_t length);
int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length);
void crypt_hash_destroy(struct crypt_hash *ctx);
/* HMAC */
int crypt_hmac_size(const char *name);
int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
const void *key, size_t key_length);
int crypt_hmac_write(struct crypt_hmac *ctx, const char *buffer, size_t length);
int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length);
void crypt_hmac_destroy(struct crypt_hmac *ctx);
/* RNG (if fips parameter set, must provide FIPS compliance) */
enum { CRYPT_RND_NORMAL = 0, CRYPT_RND_KEY = 1, CRYPT_RND_SALT = 2 };
int crypt_backend_rng(char *buffer, size_t length, int quality, int fips);
/* PBKDF*/
struct crypt_pbkdf_limits {
uint32_t min_iterations, max_iterations;
uint32_t min_memory, max_memory;
uint32_t min_parallel, max_parallel;
};
int crypt_pbkdf_get_limits(const char *kdf, struct crypt_pbkdf_limits *l);
int crypt_pbkdf(const char *kdf, const char *hash,
const char *password, size_t password_length,
const char *salt, size_t salt_length,
char *key, size_t key_length,
uint32_t iterations, uint32_t memory, uint32_t parallel);
int crypt_pbkdf_perf(const char *kdf, const char *hash,
const char *password, size_t password_size,
const char *salt, size_t salt_size,
size_t volume_key_size, uint32_t time_ms,
uint32_t max_memory_kb, uint32_t parallel_threads,
uint32_t *iterations_out, uint32_t *memory_out,
int (*progress)(uint32_t time_ms, void *usrptr), void *usrptr);
/* CRC32 */
uint32_t crypt_crc32(uint32_t seed, const unsigned char *buf, size_t len);
/* Block ciphers */
int crypt_cipher_ivsize(const char *name, const char *mode);
int crypt_cipher_wrapped_key(const char *name, const char *mode);
int crypt_cipher_init(struct crypt_cipher **ctx, const char *name,
const char *mode, const void *key, size_t key_length);
void crypt_cipher_destroy(struct crypt_cipher *ctx);
int crypt_cipher_encrypt(struct crypt_cipher *ctx,
const char *in, char *out, size_t length,
const char *iv, size_t iv_length);
int crypt_cipher_decrypt(struct crypt_cipher *ctx,
const char *in, char *out, size_t length,
const char *iv, size_t iv_length);
bool crypt_cipher_kernel_only(struct crypt_cipher *ctx);
/* Benchmark of kernel cipher performance */
int crypt_cipher_perf_kernel(const char *name, const char *mode, char *buffer, size_t buffer_size,
const char *key, size_t key_size, const char *iv, size_t iv_size,
double *encryption_mbs, double *decryption_mbs);
/* Check availability of a cipher (in kernel only) */
int crypt_cipher_check_kernel(const char *name, const char *mode,
const char *integrity, size_t key_length);
/* 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);
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);
int crypt_storage_encrypt(struct crypt_storage *ctx, uint64_t iv_offset,
uint64_t length, char *buffer);
bool crypt_storage_kernel_only(struct crypt_storage *ctx);
/* Memzero helper (memset on stack can be optimized out) */
static inline void crypt_backend_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
}
#endif /* _CRYPTO_BACKEND_H */

View File

@ -0,0 +1,59 @@
/*
* crypto backend implementation
*
* 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
* 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 _CRYPTO_BACKEND_INTERNAL_H
#define _CRYPTO_BACKEND_INTERNAL_H
#include "crypto_backend.h"
#if USE_INTERNAL_PBKDF2
/* internal PBKDF2 implementation */
int pkcs5_pbkdf2(const char *hash,
const char *P, size_t Plen,
const char *S, size_t Slen,
unsigned int c,
unsigned int dkLen, char *DK,
unsigned int hash_block_size);
#endif
/* Argon2 implementation wrapper */
int argon2(const char *type, const char *password, size_t password_length,
const char *salt, size_t salt_length,
char *key, size_t key_length,
uint32_t iterations, uint32_t memory, uint32_t parallel);
/* Block ciphers: fallback to kernel crypto API */
struct crypt_cipher_kernel {
int tfmfd;
int opfd;
};
int crypt_cipher_init_kernel(struct crypt_cipher_kernel *ctx, const char *name,
const char *mode, const void *key, size_t key_length);
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);
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);
#endif /* _CRYPTO_BACKEND_INTERNAL_H */

View File

@ -0,0 +1,283 @@
/*
* Linux kernel userspace API crypto backend implementation (skcipher)
*
* 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
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this file; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <errno.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include "crypto_backend_internal.h"
#ifdef ENABLE_AF_ALG
#include <linux/if_alg.h>
#ifndef AF_ALG
#define AF_ALG 38
#endif
#ifndef SOL_ALG
#define SOL_ALG 279
#endif
/*
* ciphers
*
* ENOENT - algorithm not available
* ENOTSUP - AF_ALG family not available
* (but cannot check specifically for skcipher API)
*/
static int _crypt_cipher_init(struct crypt_cipher_kernel *ctx,
const void *key, size_t key_length,
struct sockaddr_alg *sa)
{
if (!ctx)
return -EINVAL;
ctx->opfd = -1;
ctx->tfmfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
if (ctx->tfmfd < 0) {
crypt_cipher_destroy_kernel(ctx);
return -ENOTSUP;
}
if (bind(ctx->tfmfd, (struct sockaddr *)sa, sizeof(*sa)) < 0) {
crypt_cipher_destroy_kernel(ctx);
return -ENOENT;
}
if (setsockopt(ctx->tfmfd, SOL_ALG, ALG_SET_KEY, key, key_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);
return -EINVAL;
}
return 0;
}
int crypt_cipher_init_kernel(struct crypt_cipher_kernel *ctx, const char *name,
const char *mode, const void *key, size_t key_length)
{
struct sockaddr_alg sa = {
.salg_family = AF_ALG,
.salg_type = "skcipher",
};
if (!strcmp(name, "cipher_null"))
key_length = 0;
snprintf((char *)sa.salg_name, sizeof(sa.salg_name), "%s(%s)", mode, name);
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, char *out, size_t length,
const char *iv, size_t iv_length,
uint32_t direction)
{
int r = 0;
ssize_t len;
struct af_alg_iv *alg_iv;
struct cmsghdr *header;
uint32_t *type;
struct iovec iov = {
.iov_base = (void*)(uintptr_t)in,
.iov_len = length,
};
int iv_msg_size = iv ? CMSG_SPACE(sizeof(*alg_iv) + iv_length) : 0;
char buffer[CMSG_SPACE(sizeof(*type)) + iv_msg_size];
struct msghdr msg = {
.msg_control = buffer,
.msg_controllen = sizeof(buffer),
.msg_iov = &iov,
.msg_iovlen = 1,
};
if (!in || !out || !length)
return -EINVAL;
if ((!iv && iv_length) || (iv && !iv_length))
return -EINVAL;
memset(buffer, 0, sizeof(buffer));
/* Set encrypt/decrypt operation */
header = CMSG_FIRSTHDR(&msg);
if (!header)
return -EINVAL;
header->cmsg_level = SOL_ALG;
header->cmsg_type = ALG_SET_OP;
header->cmsg_len = CMSG_LEN(sizeof(*type));
type = (void*)CMSG_DATA(header);
*type = direction;
/* Set IV */
if (iv) {
header = CMSG_NXTHDR(&msg, header);
header->cmsg_level = SOL_ALG;
header->cmsg_type = ALG_SET_IV;
header->cmsg_len = iv_msg_size;
alg_iv = (void*)CMSG_DATA(header);
alg_iv->ivlen = iv_length;
memcpy(alg_iv->iv, iv, iv_length);
}
len = sendmsg(ctx->opfd, &msg, 0);
if (len != (ssize_t)length) {
r = -EIO;
goto bad;
}
len = read(ctx->opfd, out, length);
if (len != (ssize_t)length)
r = -EIO;
bad:
crypt_backend_memzero(buffer, sizeof(buffer));
return r;
}
int crypt_cipher_encrypt_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, out, length,
iv, iv_length, ALG_OP_ENCRYPT);
}
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, out, length,
iv, iv_length, ALG_OP_DECRYPT);
}
void crypt_cipher_destroy_kernel(struct crypt_cipher_kernel *ctx)
{
if (ctx->tfmfd >= 0)
close(ctx->tfmfd);
if (ctx->opfd >= 0)
close(ctx->opfd);
ctx->tfmfd = -1;
ctx->opfd = -1;
}
int crypt_cipher_check_kernel(const char *name, const char *mode,
const char *integrity, size_t key_length)
{
struct crypt_cipher_kernel c;
char mode_name[64], tmp_salg_name[180], *real_mode = NULL, *cipher_iv = NULL, *key;
const char *salg_type;
bool aead;
int r;
struct sockaddr_alg sa = {
.salg_family = AF_ALG,
};
aead = integrity && strcmp(integrity, "none");
/* Remove IV if present */
if (mode) {
strncpy(mode_name, mode, sizeof(mode_name));
mode_name[sizeof(mode_name) - 1] = 0;
cipher_iv = strchr(mode_name, '-');
if (cipher_iv) {
*cipher_iv = '\0';
real_mode = mode_name;
}
}
salg_type = aead ? "aead" : "skcipher";
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 */
if (aead && !strcmp(integrity, "poly1305"))
r = snprintf(tmp_salg_name, sizeof(tmp_salg_name), "rfc7539(%s,%s)", name, integrity);
else if (!real_mode)
r = snprintf(tmp_salg_name, sizeof(tmp_salg_name), "%s", name);
else if (aead && !strcmp(real_mode, "ccm"))
r = snprintf(tmp_salg_name, sizeof(tmp_salg_name), "rfc4309(%s(%s))", real_mode, name);
else
r = snprintf(tmp_salg_name, sizeof(tmp_salg_name), "%s(%s)", real_mode, name);
if (r <= 0 || r > (int)(sizeof(sa.salg_name) - 1))
return -EINVAL;
memcpy(sa.salg_name, tmp_salg_name, sizeof(sa.salg_name));
key = malloc(key_length);
if (!key)
return -ENOMEM;
/* We cannot use RNG yet, any key works here, tweak the first part if it is split key (XTS). */
memset(key, 0xab, key_length);
*key = 0xef;
r = _crypt_cipher_init(&c, key, key_length, &sa);
crypt_cipher_destroy_kernel(&c);
free(key);
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)
{
return -ENOTSUP;
}
void crypt_cipher_destroy_kernel(struct crypt_cipher_kernel *ctx)
{
return;
}
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 -EINVAL;
}
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 -EINVAL;
}
int crypt_cipher_check_kernel(const char *name, const char *mode,
const char *integrity, size_t key_length)
{
/* Cannot check, expect success. */
return 0;
}
#endif

View File

@ -0,0 +1,481 @@
/*
* GCRYPT crypto backend implementation
*
* 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
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this file; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <assert.h>
#include <gcrypt.h>
#include "crypto_backend_internal.h"
static int crypto_backend_initialised = 0;
static int crypto_backend_secmem = 1;
static int crypto_backend_whirlpool_bug = -1;
static char version[64];
struct crypt_hash {
gcry_md_hd_t hd;
int hash_id;
int hash_len;
};
struct crypt_hmac {
gcry_md_hd_t hd;
int hash_id;
int hash_len;
};
struct crypt_cipher {
bool use_kernel;
union {
struct crypt_cipher_kernel kernel;
gcry_cipher_hd_t hd;
} u;
};
/*
* Test for wrong Whirlpool variant,
* Ref: http://lists.gnupg.org/pipermail/gcrypt-devel/2014-January/002889.html
*/
static void crypt_hash_test_whirlpool_bug(void)
{
struct crypt_hash *h;
char buf[2] = "\0\0", hash_out1[64], hash_out2[64];
int r;
if (crypto_backend_whirlpool_bug >= 0)
return;
crypto_backend_whirlpool_bug = 0;
if (crypt_hash_init(&h, "whirlpool"))
return;
/* One shot */
if ((r = crypt_hash_write(h, &buf[0], 2)) ||
(r = crypt_hash_final(h, hash_out1, 64))) {
crypt_hash_destroy(h);
return;
}
/* Split buf (crypt_hash_final resets hash state) */
if ((r = crypt_hash_write(h, &buf[0], 1)) ||
(r = crypt_hash_write(h, &buf[1], 1)) ||
(r = crypt_hash_final(h, hash_out2, 64))) {
crypt_hash_destroy(h);
return;
}
crypt_hash_destroy(h);
if (memcmp(hash_out1, hash_out2, 64))
crypto_backend_whirlpool_bug = 1;
}
int crypt_backend_init(struct crypt_device *ctx)
{
if (crypto_backend_initialised)
return 0;
if (!gcry_control (GCRYCTL_INITIALIZATION_FINISHED_P)) {
if (!gcry_check_version (GCRYPT_REQ_VERSION)) {
return -ENOSYS;
}
/* 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
* and it locks its memory space anyway.
*/
#if 0
gcry_control (GCRYCTL_DISABLE_SECMEM);
crypto_backend_secmem = 0;
#else
gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
gcry_control (GCRYCTL_RESUME_SECMEM_WARN);
#endif
gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
}
crypto_backend_initialised = 1;
crypt_hash_test_whirlpool_bug();
snprintf(version, 64, "gcrypt %s%s%s",
gcry_check_version(NULL),
crypto_backend_secmem ? "" : ", secmem disabled",
crypto_backend_whirlpool_bug > 0 ? ", flawed whirlpool" : ""
);
return 0;
}
void crypt_backend_destroy(void)
{
if (crypto_backend_initialised)
gcry_control(GCRYCTL_TERM_SECMEM);
crypto_backend_initialised = 0;
}
const char *crypt_backend_version(void)
{
return crypto_backend_initialised ? version : "";
}
uint32_t crypt_backend_flags(void)
{
return 0;
}
static const char *crypt_hash_compat_name(const char *name, unsigned int *flags)
{
const char *hash_name = name;
/* "whirlpool_gcryptbug" is out shortcut to flawed whirlpool
* in libgcrypt < 1.6.0 */
if (name && !strcasecmp(name, "whirlpool_gcryptbug")) {
#if GCRYPT_VERSION_NUMBER >= 0x010601
if (flags)
*flags |= GCRY_MD_FLAG_BUGEMU1;
#endif
hash_name = "whirlpool";
}
return hash_name;
}
/* HASH */
int crypt_hash_size(const char *name)
{
int hash_id;
assert(crypto_backend_initialised);
hash_id = gcry_md_map_name(crypt_hash_compat_name(name, NULL));
if (!hash_id)
return -EINVAL;
return gcry_md_get_algo_dlen(hash_id);
}
int crypt_hash_init(struct crypt_hash **ctx, const char *name)
{
struct crypt_hash *h;
unsigned int flags = 0;
assert(crypto_backend_initialised);
h = malloc(sizeof(*h));
if (!h)
return -ENOMEM;
h->hash_id = gcry_md_map_name(crypt_hash_compat_name(name, &flags));
if (!h->hash_id) {
free(h);
return -EINVAL;
}
if (gcry_md_open(&h->hd, h->hash_id, flags)) {
free(h);
return -EINVAL;
}
h->hash_len = gcry_md_get_algo_dlen(h->hash_id);
*ctx = h;
return 0;
}
static void crypt_hash_restart(struct crypt_hash *ctx)
{
gcry_md_reset(ctx->hd);
}
int crypt_hash_write(struct crypt_hash *ctx, const char *buffer, size_t length)
{
gcry_md_write(ctx->hd, buffer, length);
return 0;
}
int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length)
{
unsigned char *hash;
if (length > (size_t)ctx->hash_len)
return -EINVAL;
hash = gcry_md_read(ctx->hd, ctx->hash_id);
if (!hash)
return -EINVAL;
memcpy(buffer, hash, length);
crypt_hash_restart(ctx);
return 0;
}
void crypt_hash_destroy(struct crypt_hash *ctx)
{
gcry_md_close(ctx->hd);
memset(ctx, 0, sizeof(*ctx));
free(ctx);
}
/* HMAC */
int crypt_hmac_size(const char *name)
{
return crypt_hash_size(name);
}
int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
const void *key, size_t key_length)
{
struct crypt_hmac *h;
unsigned int flags = GCRY_MD_FLAG_HMAC;
assert(crypto_backend_initialised);
h = malloc(sizeof(*h));
if (!h)
return -ENOMEM;
h->hash_id = gcry_md_map_name(crypt_hash_compat_name(name, &flags));
if (!h->hash_id) {
free(h);
return -EINVAL;
}
if (gcry_md_open(&h->hd, h->hash_id, flags)) {
free(h);
return -EINVAL;
}
if (gcry_md_setkey(h->hd, key, key_length)) {
gcry_md_close(h->hd);
free(h);
return -EINVAL;
}
h->hash_len = gcry_md_get_algo_dlen(h->hash_id);
*ctx = h;
return 0;
}
static void crypt_hmac_restart(struct crypt_hmac *ctx)
{
gcry_md_reset(ctx->hd);
}
int crypt_hmac_write(struct crypt_hmac *ctx, const char *buffer, size_t length)
{
gcry_md_write(ctx->hd, buffer, length);
return 0;
}
int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length)
{
unsigned char *hash;
if (length > (size_t)ctx->hash_len)
return -EINVAL;
hash = gcry_md_read(ctx->hd, ctx->hash_id);
if (!hash)
return -EINVAL;
memcpy(buffer, hash, length);
crypt_hmac_restart(ctx);
return 0;
}
void crypt_hmac_destroy(struct crypt_hmac *ctx)
{
gcry_md_close(ctx->hd);
memset(ctx, 0, sizeof(*ctx));
free(ctx);
}
/* RNG */
int crypt_backend_rng(char *buffer, size_t length, int quality, int fips)
{
switch(quality) {
case CRYPT_RND_NORMAL:
gcry_randomize(buffer, length, GCRY_STRONG_RANDOM);
break;
case CRYPT_RND_SALT:
case CRYPT_RND_KEY:
default:
gcry_randomize(buffer, length, GCRY_VERY_STRONG_RANDOM);
break;
}
return 0;
}
static int pbkdf2(const char *hash,
const char *password, size_t password_length,
const char *salt, size_t salt_length,
char *key, size_t key_length,
uint32_t iterations)
{
const char *hash_name = crypt_hash_compat_name(hash, NULL);
#if USE_INTERNAL_PBKDF2
return pkcs5_pbkdf2(hash_name, password, password_length, salt, salt_length,
iterations, key_length, key, 0);
#else /* USE_INTERNAL_PBKDF2 */
int hash_id = gcry_md_map_name(hash_name);
if (!hash_id)
return -EINVAL;
if (gcry_kdf_derive(password, password_length, GCRY_KDF_PBKDF2, hash_id,
salt, salt_length, iterations, key_length, key))
return -EINVAL;
return 0;
#endif /* USE_INTERNAL_PBKDF2 */
}
/* PBKDF */
int crypt_pbkdf(const char *kdf, const char *hash,
const char *password, size_t password_length,
const char *salt, size_t salt_length,
char *key, size_t key_length,
uint32_t iterations, uint32_t memory, uint32_t parallel)
{
if (!kdf)
return -EINVAL;
if (!strcmp(kdf, "pbkdf2"))
return pbkdf2(hash, password, password_length, salt, salt_length,
key, key_length, iterations);
else if (!strncmp(kdf, "argon2", 6))
return argon2(kdf, password, password_length, salt, salt_length,
key, key_length, iterations, memory, parallel);
return -EINVAL;
}
/* Block ciphers */
static int _cipher_init(gcry_cipher_hd_t *hd, const char *name,
const char *mode, const void *buffer, size_t length)
{
int cipher_id, mode_id;
cipher_id = gcry_cipher_map_name(name);
if (cipher_id == GCRY_CIPHER_MODE_NONE)
return -ENOENT;
if (!strcmp(mode, "ecb"))
mode_id = GCRY_CIPHER_MODE_ECB;
else if (!strcmp(mode, "cbc"))
mode_id = GCRY_CIPHER_MODE_CBC;
#if HAVE_DECL_GCRY_CIPHER_MODE_XTS
else if (!strcmp(mode, "xts"))
mode_id = GCRY_CIPHER_MODE_XTS;
#endif
else
return -ENOENT;
if (gcry_cipher_open(hd, cipher_id, mode_id, 0))
return -EINVAL;
if (gcry_cipher_setkey(*hd, buffer, length)) {
gcry_cipher_close(*hd);
return -EINVAL;
}
return 0;
}
int crypt_cipher_init(struct crypt_cipher **ctx, const char *name,
const char *mode, const void *key, size_t key_length)
{
struct crypt_cipher *h;
int r;
h = malloc(sizeof(*h));
if (!h)
return -ENOMEM;
if (!_cipher_init(&h->u.hd, name, mode, key, key_length)) {
h->use_kernel = false;
*ctx = h;
return 0;
}
r = crypt_cipher_init_kernel(&h->u.kernel, name, mode, key, key_length);
if (r < 0) {
free(h);
return r;
}
h->use_kernel = true;
*ctx = h;
return 0;
}
void crypt_cipher_destroy(struct crypt_cipher *ctx)
{
if (ctx->use_kernel)
crypt_cipher_destroy_kernel(&ctx->u.kernel);
else
gcry_cipher_close(ctx->u.hd);
free(ctx);
}
int crypt_cipher_encrypt(struct crypt_cipher *ctx,
const char *in, char *out, size_t length,
const char *iv, size_t iv_length)
{
if (ctx->use_kernel)
return crypt_cipher_encrypt_kernel(&ctx->u.kernel, in, out, length, iv, iv_length);
if (iv && gcry_cipher_setiv(ctx->u.hd, iv, iv_length))
return -EINVAL;
if (gcry_cipher_encrypt(ctx->u.hd, out, length, in, length))
return -EINVAL;
return 0;
}
int crypt_cipher_decrypt(struct crypt_cipher *ctx,
const char *in, char *out, size_t length,
const char *iv, size_t iv_length)
{
if (ctx->use_kernel)
return crypt_cipher_decrypt_kernel(&ctx->u.kernel, in, out, length, iv, iv_length);
if (iv && gcry_cipher_setiv(ctx->u.hd, iv, iv_length))
return -EINVAL;
if (gcry_cipher_decrypt(ctx->u.hd, out, length, in, length))
return -EINVAL;
return 0;
}
bool crypt_cipher_kernel_only(struct crypt_cipher *ctx)
{
return ctx->use_kernel;
}

View File

@ -0,0 +1,394 @@
/*
* Linux kernel userspace API crypto backend implementation
*
* 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
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this file; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/utsname.h>
#include <linux/if_alg.h>
#include "crypto_backend_internal.h"
/* FIXME: remove later */
#ifndef AF_ALG
#define AF_ALG 38
#endif
#ifndef SOL_ALG
#define SOL_ALG 279
#endif
static int crypto_backend_initialised = 0;
static char version[256];
struct hash_alg {
const char *name;
const char *kernel_name;
int length;
unsigned int block_length;
};
static struct hash_alg hash_algs[] = {
{ "sha1", "sha1", 20, 64 },
{ "sha224", "sha224", 28, 64 },
{ "sha256", "sha256", 32, 64 },
{ "sha384", "sha384", 48, 128 },
{ "sha512", "sha512", 64, 128 },
{ "ripemd160", "rmd160", 20, 64 },
{ "whirlpool", "wp512", 64, 64 },
{ "sha3-224", "sha3-224", 28, 144 },
{ "sha3-256", "sha3-256", 32, 136 },
{ "sha3-384", "sha3-384", 48, 104 },
{ "sha3-512", "sha3-512", 64, 72 },
{ "stribog256","streebog256", 32, 64 },
{ "stribog512","streebog512", 64, 64 },
{ "sm3", "sm3", 32, 64 },
{ NULL, NULL, 0, 0 }
};
struct crypt_hash {
int tfmfd;
int opfd;
int hash_len;
};
struct crypt_hmac {
int tfmfd;
int opfd;
int hash_len;
};
struct crypt_cipher {
struct crypt_cipher_kernel ck;
};
static int crypt_kernel_socket_init(struct sockaddr_alg *sa, int *tfmfd, int *opfd,
const void *key, size_t key_length)
{
*tfmfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
if (*tfmfd < 0)
return -ENOTSUP;
if (bind(*tfmfd, (struct sockaddr *)sa, sizeof(*sa)) < 0) {
close(*tfmfd);
*tfmfd = -1;
return -ENOENT;
}
if (key && setsockopt(*tfmfd, SOL_ALG, ALG_SET_KEY, key, key_length) < 0) {
close(*tfmfd);
*tfmfd = -1;
return -EINVAL;
}
*opfd = accept(*tfmfd, NULL, 0);
if (*opfd < 0) {
close(*tfmfd);
*tfmfd = -1;
return -EINVAL;
}
return 0;
}
int crypt_backend_init(struct crypt_device *ctx)
{
struct utsname uts;
struct sockaddr_alg sa = {
.salg_family = AF_ALG,
.salg_type = "hash",
.salg_name = "sha256",
};
int tfmfd = -1, opfd = -1;
if (crypto_backend_initialised)
return 0;
if (uname(&uts) == -1 || strcmp(uts.sysname, "Linux"))
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;
}
void crypt_backend_destroy(void)
{
crypto_backend_initialised = 0;
}
uint32_t crypt_backend_flags(void)
{
return CRYPT_BACKEND_KERNEL;
}
const char *crypt_backend_version(void)
{
return crypto_backend_initialised ? version : "";
}
static struct hash_alg *_get_alg(const char *name)
{
int i = 0;
while (name && hash_algs[i].name) {
if (!strcmp(name, hash_algs[i].name))
return &hash_algs[i];
i++;
}
return NULL;
}
/* HASH */
int crypt_hash_size(const char *name)
{
struct hash_alg *ha = _get_alg(name);
return ha ? ha->length : -EINVAL;
}
int crypt_hash_init(struct crypt_hash **ctx, const char *name)
{
struct crypt_hash *h;
struct hash_alg *ha;
struct sockaddr_alg sa = {
.salg_family = AF_ALG,
.salg_type = "hash",
};
h = malloc(sizeof(*h));
if (!h)
return -ENOMEM;
ha = _get_alg(name);
if (!ha) {
free(h);
return -EINVAL;
}
h->hash_len = ha->length;
strncpy((char *)sa.salg_name, ha->kernel_name, sizeof(sa.salg_name)-1);
if (crypt_kernel_socket_init(&sa, &h->tfmfd, &h->opfd, NULL, 0) < 0) {
free(h);
return -EINVAL;
}
*ctx = h;
return 0;
}
int crypt_hash_write(struct crypt_hash *ctx, const char *buffer, size_t length)
{
ssize_t r;
r = send(ctx->opfd, buffer, length, MSG_MORE);
if (r < 0 || (size_t)r < length)
return -EIO;
return 0;
}
int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length)
{
ssize_t r;
if (length > (size_t)ctx->hash_len)
return -EINVAL;
r = read(ctx->opfd, buffer, length);
if (r < 0)
return -EIO;
return 0;
}
void crypt_hash_destroy(struct crypt_hash *ctx)
{
if (ctx->tfmfd >= 0)
close(ctx->tfmfd);
if (ctx->opfd >= 0)
close(ctx->opfd);
memset(ctx, 0, sizeof(*ctx));
free(ctx);
}
/* HMAC */
int crypt_hmac_size(const char *name)
{
return crypt_hash_size(name);
}
int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
const void *key, size_t key_length)
{
struct crypt_hmac *h;
struct hash_alg *ha;
struct sockaddr_alg sa = {
.salg_family = AF_ALG,
.salg_type = "hash",
};
h = malloc(sizeof(*h));
if (!h)
return -ENOMEM;
ha = _get_alg(name);
if (!ha) {
free(h);
return -EINVAL;
}
h->hash_len = ha->length;
snprintf((char *)sa.salg_name, sizeof(sa.salg_name),
"hmac(%s)", ha->kernel_name);
if (crypt_kernel_socket_init(&sa, &h->tfmfd, &h->opfd, key, key_length) < 0) {
free(h);
return -EINVAL;
}
*ctx = h;
return 0;
}
int crypt_hmac_write(struct crypt_hmac *ctx, const char *buffer, size_t length)
{
ssize_t r;
r = send(ctx->opfd, buffer, length, MSG_MORE);
if (r < 0 || (size_t)r < length)
return -EIO;
return 0;
}
int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length)
{
ssize_t r;
if (length > (size_t)ctx->hash_len)
return -EINVAL;
r = read(ctx->opfd, buffer, length);
if (r < 0)
return -EIO;
return 0;
}
void crypt_hmac_destroy(struct crypt_hmac *ctx)
{
if (ctx->tfmfd >= 0)
close(ctx->tfmfd);
if (ctx->opfd >= 0)
close(ctx->opfd);
memset(ctx, 0, sizeof(*ctx));
free(ctx);
}
/* RNG - N/A */
int crypt_backend_rng(char *buffer, size_t length, int quality, int fips)
{
return -EINVAL;
}
/* PBKDF */
int crypt_pbkdf(const char *kdf, const char *hash,
const char *password, size_t password_length,
const char *salt, size_t salt_length,
char *key, size_t key_length,
uint32_t iterations, uint32_t memory, uint32_t parallel)
{
struct hash_alg *ha;
if (!kdf)
return -EINVAL;
if (!strcmp(kdf, "pbkdf2")) {
ha = _get_alg(hash);
if (!ha)
return -EINVAL;
return pkcs5_pbkdf2(hash, password, password_length, salt, salt_length,
iterations, key_length, key, ha->block_length);
} else if (!strncmp(kdf, "argon2", 6)) {
return argon2(kdf, password, password_length, salt, salt_length,
key, key_length, iterations, memory, parallel);
}
return -EINVAL;
}
/* Block ciphers */
int crypt_cipher_init(struct crypt_cipher **ctx, const char *name,
const char *mode, const void *key, size_t key_length)
{
struct crypt_cipher *h;
int r;
h = malloc(sizeof(*h));
if (!h)
return -ENOMEM;
r = crypt_cipher_init_kernel(&h->ck, name, mode, key, key_length);
if (r < 0) {
free(h);
return r;
}
*ctx = h;
return 0;
}
void crypt_cipher_destroy(struct crypt_cipher *ctx)
{
crypt_cipher_destroy_kernel(&ctx->ck);
free(ctx);
}
int crypt_cipher_encrypt(struct crypt_cipher *ctx,
const char *in, char *out, size_t length,
const char *iv, size_t iv_length)
{
return crypt_cipher_encrypt_kernel(&ctx->ck, in, out, length, iv, iv_length);
}
int crypt_cipher_decrypt(struct crypt_cipher *ctx,
const char *in, char *out, size_t length,
const char *iv, size_t iv_length)
{
return crypt_cipher_decrypt_kernel(&ctx->ck, in, out, length, iv, iv_length);
}
bool crypt_cipher_kernel_only(struct crypt_cipher *ctx)
{
return true;
}

View File

@ -0,0 +1,435 @@
/*
* Nettle crypto backend implementation
*
* 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
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this file; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <nettle/sha.h>
#include <nettle/sha3.h>
#include <nettle/hmac.h>
#include <nettle/pbkdf2.h>
#include "crypto_backend_internal.h"
#if HAVE_NETTLE_VERSION_H
#include <nettle/version.h>
#define VSTR(s) STR(s)
#define STR(s) #s
static const char *version = "Nettle "VSTR(NETTLE_VERSION_MAJOR)"."VSTR(NETTLE_VERSION_MINOR);
#else
static const char *version = "Nettle";
#endif
typedef void (*init_func) (void *);
typedef void (*update_func) (void *, size_t, const uint8_t *);
typedef void (*digest_func) (void *, size_t, uint8_t *);
typedef void (*set_key_func) (void *, size_t, const uint8_t *);
struct hash_alg {
const char *name;
int length;
init_func init;
update_func update;
digest_func digest;
update_func hmac_update;
digest_func hmac_digest;
set_key_func hmac_set_key;
};
/* Missing HMAC wrappers in Nettle */
#define HMAC_FCE(xxx) \
struct xhmac_##xxx##_ctx HMAC_CTX(struct xxx##_ctx); \
static void xhmac_##xxx##_set_key(struct xhmac_##xxx##_ctx *ctx, \
size_t key_length, const uint8_t *key) \
{HMAC_SET_KEY(ctx, &nettle_##xxx, key_length, key);} \
static void xhmac_##xxx##_update(struct xhmac_##xxx##_ctx *ctx, \
size_t length, const uint8_t *data) \
{xxx##_update(&ctx->state, length, data);} \
static void xhmac_##xxx##_digest(struct xhmac_##xxx##_ctx *ctx, \
size_t length, uint8_t *digest) \
{HMAC_DIGEST(ctx, &nettle_##xxx, length, digest);}
HMAC_FCE(sha3_224);
HMAC_FCE(sha3_256);
HMAC_FCE(sha3_384);
HMAC_FCE(sha3_512);
static struct hash_alg hash_algs[] = {
{ "sha1", SHA1_DIGEST_SIZE,
(init_func) sha1_init,
(update_func) sha1_update,
(digest_func) sha1_digest,
(update_func) hmac_sha1_update,
(digest_func) hmac_sha1_digest,
(set_key_func) hmac_sha1_set_key,
},
{ "sha224", SHA224_DIGEST_SIZE,
(init_func) sha224_init,
(update_func) sha224_update,
(digest_func) sha224_digest,
(update_func) hmac_sha224_update,
(digest_func) hmac_sha224_digest,
(set_key_func) hmac_sha224_set_key,
},
{ "sha256", SHA256_DIGEST_SIZE,
(init_func) sha256_init,
(update_func) sha256_update,
(digest_func) sha256_digest,
(update_func) hmac_sha256_update,
(digest_func) hmac_sha256_digest,
(set_key_func) hmac_sha256_set_key,
},
{ "sha384", SHA384_DIGEST_SIZE,
(init_func) sha384_init,
(update_func) sha384_update,
(digest_func) sha384_digest,
(update_func) hmac_sha384_update,
(digest_func) hmac_sha384_digest,
(set_key_func) hmac_sha384_set_key,
},
{ "sha512", SHA512_DIGEST_SIZE,
(init_func) sha512_init,
(update_func) sha512_update,
(digest_func) sha512_digest,
(update_func) hmac_sha512_update,
(digest_func) hmac_sha512_digest,
(set_key_func) hmac_sha512_set_key,
},
{ "ripemd160", RIPEMD160_DIGEST_SIZE,
(init_func) ripemd160_init,
(update_func) ripemd160_update,
(digest_func) ripemd160_digest,
(update_func) hmac_ripemd160_update,
(digest_func) hmac_ripemd160_digest,
(set_key_func) hmac_ripemd160_set_key,
},
/* Nettle prior to version 3.2 has incompatible SHA3 implementation */
#if NETTLE_SHA3_FIPS202
{ "sha3-224", SHA3_224_DIGEST_SIZE,
(init_func) sha3_224_init,
(update_func) sha3_224_update,
(digest_func) sha3_224_digest,
(update_func) xhmac_sha3_224_update,
(digest_func) xhmac_sha3_224_digest,
(set_key_func) xhmac_sha3_224_set_key,
},
{ "sha3-256", SHA3_256_DIGEST_SIZE,
(init_func) sha3_256_init,
(update_func) sha3_256_update,
(digest_func) sha3_256_digest,
(update_func) xhmac_sha3_256_update,
(digest_func) xhmac_sha3_256_digest,
(set_key_func) xhmac_sha3_256_set_key,
},
{ "sha3-384", SHA3_384_DIGEST_SIZE,
(init_func) sha3_384_init,
(update_func) sha3_384_update,
(digest_func) sha3_384_digest,
(update_func) xhmac_sha3_384_update,
(digest_func) xhmac_sha3_384_digest,
(set_key_func) xhmac_sha3_384_set_key,
},
{ "sha3-512", SHA3_512_DIGEST_SIZE,
(init_func) sha3_512_init,
(update_func) sha3_512_update,
(digest_func) sha3_512_digest,
(update_func) xhmac_sha3_512_update,
(digest_func) xhmac_sha3_512_digest,
(set_key_func) xhmac_sha3_512_set_key,
},
#endif
{ NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, }
};
struct crypt_hash {
const struct hash_alg *hash;
union {
struct sha1_ctx sha1;
struct sha224_ctx sha224;
struct sha256_ctx sha256;
struct sha384_ctx sha384;
struct sha512_ctx sha512;
struct ripemd160_ctx ripemd160;
struct sha3_224_ctx sha3_224;
struct sha3_256_ctx sha3_256;
struct sha3_384_ctx sha3_384;
struct sha3_512_ctx sha3_512;
} nettle_ctx;
};
struct crypt_hmac {
const struct hash_alg *hash;
union {
struct hmac_sha1_ctx sha1;
struct hmac_sha224_ctx sha224;
struct hmac_sha256_ctx sha256;
struct hmac_sha384_ctx sha384;
struct hmac_sha512_ctx sha512;
struct hmac_ripemd160_ctx ripemd160;
struct xhmac_sha3_224_ctx sha3_224;
struct xhmac_sha3_256_ctx sha3_256;
struct xhmac_sha3_384_ctx sha3_384;
struct xhmac_sha3_512_ctx sha3_512;
} nettle_ctx;
size_t key_length;
uint8_t *key;
};
struct crypt_cipher {
struct crypt_cipher_kernel ck;
};
uint32_t crypt_backend_flags(void)
{
return 0;
}
static struct hash_alg *_get_alg(const char *name)
{
int i = 0;
while (name && hash_algs[i].name) {
if (!strcmp(name, hash_algs[i].name))
return &hash_algs[i];
i++;
}
return NULL;
}
int crypt_backend_init(struct crypt_device *ctx)
{
return 0;
}
void crypt_backend_destroy(void)
{
return;
}
const char *crypt_backend_version(void)
{
return version;
}
/* HASH */
int crypt_hash_size(const char *name)
{
struct hash_alg *ha = _get_alg(name);
return ha ? ha->length : -EINVAL;
}
int crypt_hash_init(struct crypt_hash **ctx, const char *name)
{
struct crypt_hash *h;
h = malloc(sizeof(*h));
if (!h)
return -ENOMEM;
h->hash = _get_alg(name);
if (!h->hash) {
free(h);
return -EINVAL;
}
h->hash->init(&h->nettle_ctx);
*ctx = h;
return 0;
}
static void crypt_hash_restart(struct crypt_hash *ctx)
{
ctx->hash->init(&ctx->nettle_ctx);
}
int crypt_hash_write(struct crypt_hash *ctx, const char *buffer, size_t length)
{
ctx->hash->update(&ctx->nettle_ctx, length, (const uint8_t*)buffer);
return 0;
}
int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length)
{
if (length > (size_t)ctx->hash->length)
return -EINVAL;
ctx->hash->digest(&ctx->nettle_ctx, length, (uint8_t *)buffer);
crypt_hash_restart(ctx);
return 0;
}
void crypt_hash_destroy(struct crypt_hash *ctx)
{
memset(ctx, 0, sizeof(*ctx));
free(ctx);
}
/* HMAC */
int crypt_hmac_size(const char *name)
{
return crypt_hash_size(name);
}
int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
const void *key, size_t key_length)
{
struct crypt_hmac *h;
h = malloc(sizeof(*h));
if (!h)
return -ENOMEM;
memset(ctx, 0, sizeof(*ctx));
h->hash = _get_alg(name);
if (!h->hash)
goto bad;
h->key = malloc(key_length);
if (!h->key)
goto bad;
memcpy(h->key, key, key_length);
h->key_length = key_length;
h->hash->init(&h->nettle_ctx);
h->hash->hmac_set_key(&h->nettle_ctx, h->key_length, h->key);
*ctx = h;
return 0;
bad:
free(h);
return -EINVAL;
}
static void crypt_hmac_restart(struct crypt_hmac *ctx)
{
ctx->hash->hmac_set_key(&ctx->nettle_ctx, ctx->key_length, ctx->key);
}
int crypt_hmac_write(struct crypt_hmac *ctx, const char *buffer, size_t length)
{
ctx->hash->hmac_update(&ctx->nettle_ctx, length, (const uint8_t *)buffer);
return 0;
}
int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length)
{
if (length > (size_t)ctx->hash->length)
return -EINVAL;
ctx->hash->hmac_digest(&ctx->nettle_ctx, length, (uint8_t *)buffer);
crypt_hmac_restart(ctx);
return 0;
}
void crypt_hmac_destroy(struct crypt_hmac *ctx)
{
memset(ctx->key, 0, ctx->key_length);
free(ctx->key);
memset(ctx, 0, sizeof(*ctx));
free(ctx);
}
/* RNG - N/A */
int crypt_backend_rng(char *buffer, size_t length, int quality, int fips)
{
return -EINVAL;
}
/* PBKDF */
int crypt_pbkdf(const char *kdf, const char *hash,
const char *password, size_t password_length,
const char *salt, size_t salt_length,
char *key, size_t key_length,
uint32_t iterations, uint32_t memory, uint32_t parallel)
{
struct crypt_hmac *h;
int r;
if (!kdf)
return -EINVAL;
if (!strcmp(kdf, "pbkdf2")) {
r = crypt_hmac_init(&h, hash, password, password_length);
if (r < 0)
return r;
nettle_pbkdf2(&h->nettle_ctx, h->hash->hmac_update,
h->hash->hmac_digest, h->hash->length, iterations,
salt_length, (const uint8_t *)salt, key_length,
(uint8_t *)key);
crypt_hmac_destroy(h);
return 0;
} else if (!strncmp(kdf, "argon2", 6)) {
return argon2(kdf, password, password_length, salt, salt_length,
key, key_length, iterations, memory, parallel);
}
return -EINVAL;
}
/* Block ciphers */
int crypt_cipher_init(struct crypt_cipher **ctx, const char *name,
const char *mode, const void *key, size_t key_length)
{
struct crypt_cipher *h;
int r;
h = malloc(sizeof(*h));
if (!h)
return -ENOMEM;
r = crypt_cipher_init_kernel(&h->ck, name, mode, key, key_length);
if (r < 0) {
free(h);
return r;
}
*ctx = h;
return 0;
}
void crypt_cipher_destroy(struct crypt_cipher *ctx)
{
crypt_cipher_destroy_kernel(&ctx->ck);
free(ctx);
}
int crypt_cipher_encrypt(struct crypt_cipher *ctx,
const char *in, char *out, size_t length,
const char *iv, size_t iv_length)
{
return crypt_cipher_encrypt_kernel(&ctx->ck, in, out, length, iv, iv_length);
}
int crypt_cipher_decrypt(struct crypt_cipher *ctx,
const char *in, char *out, size_t length,
const char *iv, size_t iv_length)
{
return crypt_cipher_decrypt_kernel(&ctx->ck, in, out, length, iv, iv_length);
}
bool crypt_cipher_kernel_only(struct crypt_cipher *ctx)
{
return true;
}

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