mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-06 08:20:07 +01:00
Compare commits
301 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e0562f9708 | ||
|
|
6462ee55d3 | ||
|
|
91ba5742c6 | ||
|
|
667e469659 | ||
|
|
37cecb5a5b | ||
|
|
a47ebccf9a | ||
|
|
584d5b8d65 | ||
|
|
8eef5bde4f | ||
|
|
3532be48c7 | ||
|
|
5f7309bfa0 | ||
|
|
fa4a246744 | ||
|
|
321386db88 | ||
|
|
b99b4825a2 | ||
|
|
9b455125e9 | ||
|
|
adcb9bfb7d | ||
|
|
4abfd38169 | ||
|
|
b684fffdaf | ||
|
|
fb3b62ca02 | ||
|
|
c469e458b7 | ||
|
|
be5473f242 | ||
|
|
527c0fe4f9 | ||
|
|
0ec4d4c9cf | ||
|
|
28f860def2 | ||
|
|
42abcc0fac | ||
|
|
a38fcafcff | ||
|
|
c4a533c3d5 | ||
|
|
96f31a2cff | ||
|
|
8f4fb9303f | ||
|
|
336be2da96 | ||
|
|
e129bffce9 | ||
|
|
a9d9a2ad44 | ||
|
|
c0a5293435 | ||
|
|
b9ae00956d | ||
|
|
e37016bf64 | ||
|
|
104c7d6c4f | ||
|
|
b773823a1b | ||
|
|
0894814148 | ||
|
|
cc948df1dd | ||
|
|
35e3660c61 | ||
|
|
28c6901de1 | ||
|
|
dc067454c1 | ||
|
|
32c2bd4222 | ||
|
|
cd4ea1c348 | ||
|
|
8984e47414 | ||
|
|
491e79db4c | ||
|
|
8a1a0547a8 | ||
|
|
9d47892342 | ||
|
|
32cfb1ca25 | ||
|
|
810aef34ca | ||
|
|
b23b3c4dfe | ||
|
|
b9d99a1626 | ||
|
|
496a07ed4c | ||
|
|
fbba97552e | ||
|
|
0cefe2d107 | ||
|
|
768426ad99 | ||
|
|
5a48ff5eb2 | ||
|
|
96c8c7ba56 | ||
|
|
29c2281ab2 | ||
|
|
0d70651c5a | ||
|
|
b1fb2532e0 | ||
|
|
05b695d516 | ||
|
|
44c9b2fc68 | ||
|
|
018205a9a0 | ||
|
|
c333108c61 | ||
|
|
2fcb521c77 | ||
|
|
0dc87d45a8 | ||
|
|
03dc073f2b | ||
|
|
b402f087d7 | ||
|
|
656fbde7d1 | ||
|
|
a89e6c0ca6 | ||
|
|
d380da7a32 | ||
|
|
0de4b65ba6 | ||
|
|
5c7954a0c7 | ||
|
|
62f334cfa5 | ||
|
|
6d2c15ea79 | ||
|
|
4b8f91d0d9 | ||
|
|
c364290be9 | ||
|
|
a14aab5df7 | ||
|
|
47c5b5ed06 | ||
|
|
0eae181092 | ||
|
|
1cbc53e8ee | ||
|
|
7535fdb31b | ||
|
|
de9393879e | ||
|
|
db51a343de | ||
|
|
e2375c8368 | ||
|
|
697c6c9324 | ||
|
|
6d07be898d | ||
|
|
ade21e6c60 | ||
|
|
fcf5b414d6 | ||
|
|
92d1bebdac | ||
|
|
39a5408e98 | ||
|
|
937f969cc4 | ||
|
|
f4101d0f8b | ||
|
|
ce2218ed65 | ||
|
|
cdae1b4c60 | ||
|
|
c4b16923bb | ||
|
|
b016e65daa | ||
|
|
c35839afbc | ||
|
|
cd8826618d | ||
|
|
ab0f7346bc | ||
|
|
9fb8b816c5 | ||
|
|
0e79728f86 | ||
|
|
4b0b82adc5 | ||
|
|
850799802b | ||
|
|
ed1b59fd25 | ||
|
|
fa98297547 | ||
|
|
2949f37587 | ||
|
|
fca7296e6e | ||
|
|
6aa77550c5 | ||
|
|
23e1ac341c | ||
|
|
9ae7e122ac | ||
|
|
73493c1f44 | ||
|
|
65c4c62f78 | ||
|
|
aba52fa878 | ||
|
|
a5cc87b4a5 | ||
|
|
11ee2876a6 | ||
|
|
20eea64334 | ||
|
|
44165a1bbb | ||
|
|
e9bc8e1b35 | ||
|
|
5e52599326 | ||
|
|
4903b8120b | ||
|
|
d0c98af4e6 | ||
|
|
624157ef7b | ||
|
|
08da00c94a | ||
|
|
9910c7dcd0 | ||
|
|
9ff422374d | ||
|
|
5c49268c47 | ||
|
|
7df1d83ebb | ||
|
|
555d5f6e97 | ||
|
|
716e60729d | ||
|
|
65ba7c7f3f | ||
|
|
ed1ab3e498 | ||
|
|
dc371d7174 | ||
|
|
cf1e6fb847 | ||
|
|
45e0942755 | ||
|
|
0f4431d0bb | ||
|
|
54b21c6e46 | ||
|
|
c2a33b480f | ||
|
|
490c17b3cd | ||
|
|
f8aa0bc084 | ||
|
|
ba7d9967a8 | ||
|
|
adaf6d3eb4 | ||
|
|
bbc3339bda | ||
|
|
f720affe8c | ||
|
|
a718369374 | ||
|
|
4b6ec2a8c2 | ||
|
|
e48a808b5c | ||
|
|
f929abacab | ||
|
|
1562879369 | ||
|
|
e1d410953b | ||
|
|
8818eb2687 | ||
|
|
4320327383 | ||
|
|
5c4c3010fc | ||
|
|
c16ebd0aca | ||
|
|
d392737279 | ||
|
|
be204f8978 | ||
|
|
9391477be4 | ||
|
|
09fd551e03 | ||
|
|
ee8425b836 | ||
|
|
2499fa669d | ||
|
|
bd047d03ef | ||
|
|
9511c91a79 | ||
|
|
570b0ecd49 | ||
|
|
80290266e6 | ||
|
|
dc7f97ea5e | ||
|
|
c9279c9818 | ||
|
|
9341679b31 | ||
|
|
78cac9a97c | ||
|
|
075fb8d261 | ||
|
|
9bce441a1e | ||
|
|
5b41568e8f | ||
|
|
0becb1ac46 | ||
|
|
fff8b02b46 | ||
|
|
83564fbeb9 | ||
|
|
b30b53e4a7 | ||
|
|
60d60d971a | ||
|
|
5596294635 | ||
|
|
54bf872663 | ||
|
|
4b109507d8 | ||
|
|
625822e5a1 | ||
|
|
18c4896310 | ||
|
|
d542045645 | ||
|
|
2199076fef | ||
|
|
37902e1287 | ||
|
|
30f7e2310f | ||
|
|
89d9d25a2b | ||
|
|
0d766c5868 | ||
|
|
313e5564fe | ||
|
|
0e52cb902a | ||
|
|
3684a5d833 | ||
|
|
a5aa30be33 | ||
|
|
eb2b03699f | ||
|
|
3da3b415a7 | ||
|
|
03cc3383e1 | ||
|
|
4988c8beea | ||
|
|
3a0ac6c3d3 | ||
|
|
203f2e082d | ||
|
|
b4e2306da8 | ||
|
|
c0d55945d3 | ||
|
|
3a3ff16c39 | ||
|
|
774d1de56e | ||
|
|
01938e3cdd | ||
|
|
24213963fd | ||
|
|
6d8aeb1d58 | ||
|
|
6fe40949f9 | ||
|
|
c1b01c2dc7 | ||
|
|
a24d9cd9b5 | ||
|
|
1b982af46f | ||
|
|
66f042953d | ||
|
|
4f2d4f98e3 | ||
|
|
251c7f434f | ||
|
|
7835b365a7 | ||
|
|
4aee070173 | ||
|
|
ef078587cc | ||
|
|
6e119ab6cc | ||
|
|
c490ef638b | ||
|
|
f5d777e412 | ||
|
|
28eddd2f52 | ||
|
|
eb4720819e | ||
|
|
088a927c07 | ||
|
|
3c3e9570c4 | ||
|
|
b6e046835e | ||
|
|
158a5de3b4 | ||
|
|
02e36d7606 | ||
|
|
38ff882096 | ||
|
|
58a27a18ca | ||
|
|
94fb0b7781 | ||
|
|
c401fe3d04 | ||
|
|
3b10bf9558 | ||
|
|
d6016b1c2d | ||
|
|
9908cd4746 | ||
|
|
a24a594d1a | ||
|
|
56e73526ad | ||
|
|
e640f5e006 | ||
|
|
cb7fa0b9c7 | ||
|
|
60d59b0bc0 | ||
|
|
4f33a537ae | ||
|
|
96bddb363f | ||
|
|
dac000e1df | ||
|
|
be246c16ab | ||
|
|
cc3b39980b | ||
|
|
8c54d938ac | ||
|
|
d7960b9307 | ||
|
|
4e9fa4d2bb | ||
|
|
7a773f70f3 | ||
|
|
b72473eddf | ||
|
|
4d1b67eeb2 | ||
|
|
f54c7939f0 | ||
|
|
19bde65f5b | ||
|
|
d2fbc963ca | ||
|
|
61bec51be0 | ||
|
|
84ada5ddf6 | ||
|
|
7158c32b96 | ||
|
|
1a8bae8884 | ||
|
|
538169fb5b | ||
|
|
963ee0e6ee | ||
|
|
d20e2ff02d | ||
|
|
d5e48fcb00 | ||
|
|
4d99773009 | ||
|
|
f3ed801e8b | ||
|
|
1954792876 | ||
|
|
95009fff4b | ||
|
|
b8a7125225 | ||
|
|
6cede067a2 | ||
|
|
906c7897e1 | ||
|
|
c5b64b5479 | ||
|
|
4a295781d1 | ||
|
|
1f9efdf59a | ||
|
|
1f776bc979 | ||
|
|
104130c4c4 | ||
|
|
51d74c6029 | ||
|
|
7fe10e3d7b | ||
|
|
25c3271cd0 | ||
|
|
7665f8e805 | ||
|
|
6361e86daf | ||
|
|
3c5481709b | ||
|
|
c30fe505c5 | ||
|
|
a9ce2210bc | ||
|
|
e5244bc47c | ||
|
|
23e144daf4 | ||
|
|
03a8ba4d17 | ||
|
|
f80b506b65 | ||
|
|
f7f9e291f4 | ||
|
|
1bf26b9a90 | ||
|
|
261d0d05a5 | ||
|
|
9c71c74d59 | ||
|
|
39e6cfcb8a | ||
|
|
913ef7c07e | ||
|
|
69bd90055f | ||
|
|
7d496a6b69 | ||
|
|
642a838343 | ||
|
|
a1306ed01c | ||
|
|
790ef04304 | ||
|
|
d44d07c9eb | ||
|
|
5b8fb6f135 | ||
|
|
84079a1a49 | ||
|
|
1b7c97c333 | ||
|
|
96d67485d9 | ||
|
|
a5757c35f0 | ||
|
|
3f49ffd526 | ||
|
|
dfd018235b |
41
COPYING
41
COPYING
@@ -1,12 +1,12 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
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
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
@@ -15,7 +15,7 @@ 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 Library General Public License instead.) You can apply it to
|
||||
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
|
||||
@@ -55,8 +55,8 @@ 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
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
@@ -110,7 +110,7 @@ above, provided that you also meet all of these conditions:
|
||||
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
|
||||
@@ -168,7 +168,7 @@ 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
|
||||
@@ -225,7 +225,7 @@ 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
|
||||
@@ -255,7 +255,7 @@ 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
|
||||
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
|
||||
@@ -277,9 +277,9 @@ 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
|
||||
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
|
||||
@@ -303,17 +303,16 @@ the "copyright" line and a pointer to where the full notice is found.
|
||||
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
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 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.
|
||||
@@ -336,7 +335,7 @@ necessary. Here is a sample; alter the names:
|
||||
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 Library General
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
|
||||
-----
|
||||
|
||||
502
COPYING.LGPL
Normal file
502
COPYING.LGPL
Normal file
@@ -0,0 +1,502 @@
|
||||
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!
|
||||
144
ChangeLog
144
ChangeLog
@@ -1,3 +1,139 @@
|
||||
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.
|
||||
|
||||
@@ -363,7 +499,7 @@
|
||||
* configure.in (AC_OUTPUT): Add m4/Makefile.
|
||||
(AM_GNU_GETTEXT_VERSION): Bump to 0.15.
|
||||
|
||||
2006-10-22 David H<EFBFBD>rdeman <david@hardeman.nu>
|
||||
2006-10-22 David Härdeman <david@hardeman.nu>
|
||||
|
||||
* Allow hashing of keys passed through stdin.
|
||||
|
||||
@@ -430,7 +566,7 @@
|
||||
|
||||
2006-08-04 Clemens Fruhwirth <clemens@endorphin.org>
|
||||
|
||||
* lib/setup.c (get_key): Applied patch from David H<EFBFBD>rdeman
|
||||
* 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.
|
||||
|
||||
@@ -447,7 +583,7 @@
|
||||
|
||||
2006-07-23 Clemens Fruhwirth <clemens@endorphin.org>
|
||||
|
||||
* Applied patches from David H<EFBFBD>rdeman <david@2gen.com> to fix 64
|
||||
* Applied patches from David Härdeman <david@2gen.com> to fix 64
|
||||
bit compiler warning issues.
|
||||
|
||||
2006-05-19 Clemens Fruhwirth <clemens@endorphin.org>
|
||||
@@ -466,7 +602,7 @@
|
||||
|
||||
* configure.in: Release 1.0.3.
|
||||
|
||||
* Applied patch by Johannes Wei<EFBFBD>l for more meaningful exit codes
|
||||
* Applied patch by Johannes Weißl for more meaningful exit codes
|
||||
and password retries
|
||||
|
||||
2006-03-30 Clemens Fruhwirth <clemens@endorphin.org>
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
EXTRA_DIST = FAQ docs
|
||||
EXTRA_DIST = COPYING.LGPL FAQ docs misc
|
||||
SUBDIRS = \
|
||||
lib \
|
||||
src \
|
||||
man \
|
||||
python \
|
||||
tests \
|
||||
po
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
clean-local:
|
||||
-rm -rf docs/doxygen_api_docs
|
||||
|
||||
2
README
2
README
@@ -23,7 +23,7 @@ DOWNLOAD:
|
||||
SOURCE CODE:
|
||||
|
||||
URL: http://code.google.com/p/cryptsetup/source/browse/
|
||||
Checkout: svn checkout http://cryptsetup.googlecode.com/svn/trunk/ cryptsetup
|
||||
Checkout: git clone https://code.google.com/p/cryptsetup/
|
||||
|
||||
NLS (PO TRANSLATIONS):
|
||||
|
||||
|
||||
10
TODO
10
TODO
@@ -1,5 +1,7 @@
|
||||
Version 1.4.0:
|
||||
- Remove old API (all calls using crypt_options)
|
||||
- Support separation of metadata device
|
||||
- Wipe device flag
|
||||
Version 1.6.0:
|
||||
- Export wipe device functions
|
||||
- Support K/M suffixes for align payload (new switch?).
|
||||
- FIPS: move changekey to library
|
||||
- online reencryption api?
|
||||
- integrate more metadata formats
|
||||
- TRIM for keyslots
|
||||
|
||||
53
acinclude.m4
53
acinclude.m4
@@ -1,53 +0,0 @@
|
||||
dnl MODULE_HELPER(NAME, HELP, DEFAULT, COMMANDS)
|
||||
AC_DEFUN([MODULE_HELPER],[
|
||||
unset have_module
|
||||
AC_ARG_ENABLE([$1], [$2],,[
|
||||
if test "x${enable_all}" = "xdefault"; then
|
||||
enable_[$1]=[$3]
|
||||
else
|
||||
enable_[$1]="${enable_all}"
|
||||
fi
|
||||
])
|
||||
if test "x${enable_[$1]}" != "xno"; then
|
||||
$4
|
||||
AC_MSG_CHECKING([whether to build $1 module])
|
||||
if test -n "${have_module+set}"; then
|
||||
if test "x${enable_[$1]}" = "xauto"; then
|
||||
if test "x${enable_plugins}" != "xno"; then
|
||||
AC_MSG_RESULT([yes, as plugin])
|
||||
build_static=no
|
||||
build_shared=yes
|
||||
else
|
||||
AC_MSG_RESULT([yes])
|
||||
build_static=yes
|
||||
build_shared=no
|
||||
fi
|
||||
elif test "x${enable_[$1]}" = "xshared"; then
|
||||
if test "x${enable_plugins}" != "xno"; then
|
||||
AC_MSG_RESULT([yes, as plugin])
|
||||
build_static=no
|
||||
build_shared=yes
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
AC_MSG_ERROR([Can't build [$1] module, plugins are disabled])
|
||||
fi
|
||||
else
|
||||
AC_MSG_RESULT([yes])
|
||||
build_static=yes
|
||||
build_shared=no
|
||||
fi
|
||||
elif test "x${enable_[$1]}" != "xauto"; then
|
||||
AC_MSG_RESULT([no])
|
||||
AC_MSG_ERROR([Unable to build $1 plugin, see messages above])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
build_static=no
|
||||
build_shared=no
|
||||
fi
|
||||
else
|
||||
AC_MSG_CHECKING([whether to build $1 module])
|
||||
AC_MSG_RESULT([no])
|
||||
build_static=no
|
||||
build_shared=no
|
||||
fi
|
||||
])
|
||||
127
configure.in
127
configure.in
@@ -1,9 +1,11 @@
|
||||
AC_PREREQ([2.67])
|
||||
AC_INIT([cryptsetup],[1.3.1])
|
||||
AC_INIT([cryptsetup],[1.5.0])
|
||||
|
||||
dnl library version from <major>.<minor>.<release>[-<suffix>]
|
||||
LIBCRYPTSETUP_VERSION=$(echo $PACKAGE_VERSION | cut -f1 -d-)
|
||||
LIBCRYPTSETUP_VERSION_INFO=3:0:2
|
||||
LIBCRYPTSETUP_VERSION_INFO=7:0:3
|
||||
dnl library file name for FIPS selfcheck
|
||||
LIBCRYPTSETUP_VERSION_FIPS="libcryptsetup.so.4"
|
||||
|
||||
AC_CONFIG_SRCDIR(src/cryptsetup.c)
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
@@ -31,11 +33,11 @@ AC_HEADER_STDC
|
||||
AC_CHECK_HEADERS(fcntl.h malloc.h inttypes.h sys/ioctl.h sys/mman.h \
|
||||
ctype.h unistd.h locale.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_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.])])
|
||||
|
||||
saved_LIBS=$LIBS
|
||||
AC_CHECK_LIB(uuid, uuid_clear, ,[AC_MSG_ERROR('You need the uuid library')])
|
||||
AC_CHECK_LIB(uuid, uuid_clear, ,[AC_MSG_ERROR([You need the uuid library.])])
|
||||
AC_SUBST(UUID_LIBS, $LIBS)
|
||||
LIBS=$saved_LIBS
|
||||
|
||||
@@ -61,11 +63,44 @@ AC_CHECK_LIB(popt, poptConfigFileToString,,
|
||||
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]),
|
||||
[with_fips=$enableval],
|
||||
[with_fips=no])
|
||||
|
||||
if test "x$with_fips" = "xyes"; then
|
||||
AC_DEFINE(ENABLE_FIPS, 1, [Enable FIPS mode restrictions])
|
||||
AC_DEFINE_UNQUOTED(LIBCRYPTSETUP_VERSION_FIPS, ["$LIBCRYPTSETUP_VERSION_FIPS"],
|
||||
[library file name for FIPS selfcheck])
|
||||
|
||||
if test "x$enable_static" = "xyes" -o "x$enable_static_cryptsetup" = "xyes" ; then
|
||||
AC_MSG_ERROR([Static build is not compatible with FIPS.])
|
||||
fi
|
||||
|
||||
saved_LIBS=$LIBS
|
||||
AC_CHECK_LIB(fipscheck, FIPSCHECK_verify, ,[AC_MSG_ERROR([You need the fipscheck library.])])
|
||||
AC_SUBST(FIPSCHECK_LIBS, $LIBS)
|
||||
LIBS=$saved_LIBS
|
||||
|
||||
fi
|
||||
|
||||
AC_DEFUN([NO_FIPS], [
|
||||
if test "x$with_fips" = "xyes"; then
|
||||
AC_MSG_ERROR([This option is not compatible with FIPS.])
|
||||
fi
|
||||
])
|
||||
|
||||
dnl ==========================================================================
|
||||
dnl Crypto backend functions
|
||||
|
||||
AC_DEFUN([CONFIGURE_GCRYPT], [
|
||||
AM_PATH_LIBGCRYPT(1.1.42,,[AC_MSG_ERROR('You need the gcrypt library')])
|
||||
if test "x$with_fips" = "xyes"; then
|
||||
GCRYPT_REQ_VERSION=1.4.5
|
||||
else
|
||||
GCRYPT_REQ_VERSION=1.1.42
|
||||
fi
|
||||
AM_PATH_LIBGCRYPT($GCRYPT_REQ_VERSION,,[AC_MSG_ERROR([You need the gcrypt library.])])
|
||||
|
||||
if test x$enable_static_cryptsetup = xyes; then
|
||||
saved_LIBS=$LIBS
|
||||
@@ -80,11 +115,13 @@ AC_DEFUN([CONFIGURE_GCRYPT], [
|
||||
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'))
|
||||
AC_MSG_ERROR([You need openssl library.]))
|
||||
CRYPTO_CFLAGS=$OPENSSL_CFLAGS
|
||||
CRYPTO_LIBS=$OPENSSL_LIBS
|
||||
|
||||
@@ -95,43 +132,50 @@ AC_DEFUN([CONFIGURE_OPENSSL], [
|
||||
CRYPTO_STATIC_LIBS=$OPENSSL_LIBS
|
||||
PKG_CONFIG=$saved_PKG_CONFIG
|
||||
fi
|
||||
NO_FIPS([])
|
||||
])
|
||||
|
||||
AC_DEFUN([CONFIGURE_NSS], [
|
||||
if test x$enable_static_cryptsetup = xyes; then
|
||||
AC_MSG_ERROR([Static build of cryptsetup is not supported with NSS.]),
|
||||
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'))
|
||||
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
|
||||
NO_FIPS([])
|
||||
])
|
||||
|
||||
AC_DEFUN([CONFIGURE_KERNEL], [
|
||||
AC_CHECK_HEADERS(linux/if_alg.h,,
|
||||
[AC_MSG_ERROR('You need Linux kernel with userspace crypto interface.')])
|
||||
[AC_MSG_ERROR([You need Linux kernel with userspace crypto interface.])])
|
||||
# AC_CHECK_DECLS([AF_ALG],,
|
||||
# [AC_MSG_ERROR('You need Linux kernel with userspace crypto interface.')],
|
||||
# [AC_MSG_ERROR([You need Linux kernel with userspace crypto interface.])],
|
||||
# [#include <sys/socket.h>])
|
||||
|
||||
NO_FIPS([])
|
||||
])
|
||||
|
||||
AC_DEFUN([CONFIGURE_NETTLE], [
|
||||
AC_CHECK_HEADERS(nettle/sha.h,,
|
||||
[AC_MSG_ERROR('You need Nettle cryptographic library.')])
|
||||
[AC_MSG_ERROR([You need Nettle cryptographic library.])])
|
||||
|
||||
saved_LIBS=$LIBS
|
||||
AC_CHECK_LIB(nettle, nettle_sha512_init,,
|
||||
[AC_MSG_ERROR('You need Nettle library version 2.1 or more recent.')])
|
||||
AC_CHECK_LIB(nettle, nettle_ripemd160_init,,
|
||||
[AC_MSG_ERROR([You need Nettle library version 2.4 or more recent.])])
|
||||
CRYPTO_LIBS=$LIBS
|
||||
LIBS=$saved_LIBS
|
||||
|
||||
AC_MSG_WARN([Nettle backend does NOT provide backward compatibility (missing ripemd160 hash).])
|
||||
|
||||
CRYPTO_STATIC_LIBS=$CRYPTO_LIBS
|
||||
NO_FIPS([])
|
||||
])
|
||||
|
||||
dnl ==========================================================================
|
||||
@@ -146,7 +190,17 @@ if test x$enable_static_cryptsetup = xyes; then
|
||||
enable_static=yes
|
||||
fi
|
||||
fi
|
||||
AM_CONDITIONAL(STATIC_CRYPTSETUP, test x$enable_static_cryptsetup = xyes)
|
||||
AM_CONDITIONAL(STATIC_TOOLS, test x$enable_static_cryptsetup = xyes)
|
||||
|
||||
AC_ARG_ENABLE(veritysetup,
|
||||
AS_HELP_STRING([--disable-veritysetup],
|
||||
[disable veritysetup support]),[], [enable_veritysetup=yes])
|
||||
AM_CONDITIONAL(VERITYSETUP, test x$enable_veritysetup = xyes)
|
||||
|
||||
AC_ARG_ENABLE([cryptsetup-reencrypt],
|
||||
AS_HELP_STRING([--enable-cryptsetup-reencrypt],
|
||||
[enable cryptsetup-reencrypt tool]))
|
||||
AM_CONDITIONAL(REENCRYPT, test x$enable_cryptsetup_reencrypt = xyes)
|
||||
|
||||
AC_ARG_ENABLE(selinux,
|
||||
AS_HELP_STRING([--disable-selinux],
|
||||
@@ -168,6 +222,7 @@ LIBS=$saved_LIBS
|
||||
|
||||
LIBS="$LIBS $DEVMAPPER_LIBS"
|
||||
AC_CHECK_DECLS([dm_task_secure_data], [], [], [#include <libdevmapper.h>])
|
||||
AC_CHECK_DECLS([dm_task_retry_remove], [], [], [#include <libdevmapper.h>])
|
||||
AC_CHECK_DECLS([DM_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
|
||||
@@ -220,6 +275,11 @@ if test x$enable_static_cryptsetup = xyes; then
|
||||
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
|
||||
@@ -233,6 +293,7 @@ AC_SUBST([CRYPTO_STATIC_LIBS])
|
||||
|
||||
AC_SUBST([LIBCRYPTSETUP_VERSION])
|
||||
AC_SUBST([LIBCRYPTSETUP_VERSION_INFO])
|
||||
AC_SUBST([LIBCRYPTSETUP_VERSION_FIPS])
|
||||
|
||||
dnl ==========================================================================
|
||||
AC_ARG_ENABLE([dev-random], AS_HELP_STRING([--enable-dev-random],
|
||||
@@ -257,6 +318,25 @@ AC_DEFUN([CS_NUM_WITH], [AC_ARG_WITH([$1],
|
||||
[CS_DEFINE([$1], [$3], [$2])]
|
||||
)])
|
||||
|
||||
dnl ==========================================================================
|
||||
dnl Python bindings
|
||||
AC_ARG_ENABLE([python], AS_HELP_STRING([--enable-python],[enable Python bindings]),
|
||||
[with_python=$enableval],
|
||||
[with_python=no])
|
||||
|
||||
if test "x$with_python" = "xyes"; then
|
||||
AM_PATH_PYTHON([2.4])
|
||||
|
||||
if ! test -x "$PYTHON-config" ; then
|
||||
AC_MSG_ERROR([Cannot find python development packages to build bindings])
|
||||
fi
|
||||
|
||||
PYTHON_INCLUDES=$($PYTHON-config --includes)
|
||||
AC_SUBST(PYTHON_INCLUDES)
|
||||
fi
|
||||
AM_CONDITIONAL([PYTHON_CRYPTSETUP], [test "x$with_python" = "xyes"])
|
||||
|
||||
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])
|
||||
@@ -270,8 +350,13 @@ CS_NUM_WITH([luks1-keybits],[key length in bits for LUKS1], [256])
|
||||
CS_STR_WITH([loopaes-cipher], [cipher for loop-AES mode], [aes])
|
||||
CS_NUM_WITH([loopaes-keybits],[key length in bits for loop-AES mode], [256])
|
||||
|
||||
CS_NUM_WITH([keyfile-size-maxkb],[maximum keyfile size (in kilobytes)], [8192])
|
||||
CS_NUM_WITH([passphrase-size-max],[maximum keyfile size (in kilobytes)], [512])
|
||||
CS_NUM_WITH([keyfile-size-maxkb],[maximum keyfile size (in KiB)], [8192])
|
||||
CS_NUM_WITH([passphrase-size-max],[maximum keyfile size (in characters)], [512])
|
||||
|
||||
CS_STR_WITH([verity-hash], [hash function for verity mode], [sha256])
|
||||
CS_NUM_WITH([verity-data-block], [data block size for verity mode], [4096])
|
||||
CS_NUM_WITH([verity-hash-block], [hash block size for verity mode], [4096])
|
||||
CS_NUM_WITH([verity-salt-size], [salt size for verity mode], [32])
|
||||
|
||||
dnl ==========================================================================
|
||||
|
||||
@@ -281,9 +366,11 @@ lib/libcryptsetup.pc
|
||||
lib/crypto_backend/Makefile
|
||||
lib/luks1/Makefile
|
||||
lib/loopaes/Makefile
|
||||
lib/verity/Makefile
|
||||
src/Makefile
|
||||
po/Makefile.in
|
||||
man/Makefile
|
||||
tests/Makefile
|
||||
python/Makefile
|
||||
])
|
||||
AC_OUTPUT
|
||||
|
||||
280
docs/doxyfile
Normal file
280
docs/doxyfile
Normal file
@@ -0,0 +1,280 @@
|
||||
# Doxyfile 1.7.4
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# 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
|
||||
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 =
|
||||
OPTIMIZE_OUTPUT_FOR_C = YES
|
||||
OPTIMIZE_OUTPUT_JAVA = NO
|
||||
OPTIMIZE_FOR_FORTRAN = NO
|
||||
OPTIMIZE_OUTPUT_VHDL = NO
|
||||
EXTENSION_MAPPING =
|
||||
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
|
||||
TYPEDEF_HIDES_STRUCT = YES
|
||||
SYMBOL_CACHE_SIZE = 0
|
||||
#---------------------------------------------------------------------------
|
||||
# Build related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
EXTRACT_ALL = NO
|
||||
EXTRACT_PRIVATE = 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
|
||||
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_DIRECTORIES = NO
|
||||
SHOW_FILES = YES
|
||||
SHOW_NAMESPACES = YES
|
||||
FILE_VERSION_FILTER =
|
||||
LAYOUT_FILE =
|
||||
#---------------------------------------------------------------------------
|
||||
# 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" "../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 =
|
||||
#---------------------------------------------------------------------------
|
||||
# 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
|
||||
USE_HTAGS = NO
|
||||
VERBATIM_HEADERS = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# 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_FILES =
|
||||
HTML_COLORSTYLE_HUE = 220
|
||||
HTML_COLORSTYLE_SAT = 100
|
||||
HTML_COLORSTYLE_GAMMA = 80
|
||||
HTML_TIMESTAMP = YES
|
||||
HTML_ALIGN_MEMBERS = YES
|
||||
HTML_DYNAMIC_SECTIONS = NO
|
||||
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
|
||||
ENUM_VALUES_PER_LINE = 4
|
||||
GENERATE_TREEVIEW = NO
|
||||
USE_INLINE_TREES = NO
|
||||
TREEVIEW_WIDTH = 250
|
||||
EXT_LINKS_IN_WINDOW = NO
|
||||
FORMULA_FONTSIZE = 10
|
||||
FORMULA_TRANSPARENT = YES
|
||||
USE_MATHJAX = NO
|
||||
MATHJAX_RELPATH = http://www.mathjax.org/mathjax
|
||||
SEARCHENGINE = YES
|
||||
SERVER_BASED_SEARCH = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# 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 =
|
||||
PDF_HYPERLINKS = YES
|
||||
USE_PDFLATEX = YES
|
||||
LATEX_BATCHMODE = NO
|
||||
LATEX_HIDE_INDICES = NO
|
||||
LATEX_SOURCE_CODE = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# 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_LINKS = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the XML output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_XML = NO
|
||||
XML_OUTPUT = xml
|
||||
XML_SCHEMA =
|
||||
XML_DTD =
|
||||
XML_PROGRAMLISTING = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options for the AutoGen Definitions output
|
||||
#---------------------------------------------------------------------------
|
||||
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::additions related to external references
|
||||
#---------------------------------------------------------------------------
|
||||
TAGFILES =
|
||||
GENERATE_TAGFILE =
|
||||
ALLEXTERNALS = NO
|
||||
EXTERNAL_GROUPS = YES
|
||||
PERL_PATH =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the dot tool
|
||||
#---------------------------------------------------------------------------
|
||||
CLASS_DIAGRAMS = YES
|
||||
MSCGEN_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
|
||||
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
|
||||
DOT_PATH =
|
||||
DOTFILE_DIRS =
|
||||
MSCFILE_DIRS =
|
||||
DOT_GRAPH_MAX_NODES = 50
|
||||
MAX_DOT_GRAPH_DEPTH = 0
|
||||
DOT_TRANSPARENT = NO
|
||||
DOT_MULTI_TARGETS = NO
|
||||
GENERATE_LEGEND = YES
|
||||
DOT_CLEANUP = YES
|
||||
125
docs/doxygen_index
Normal file
125
docs/doxygen_index
Normal file
@@ -0,0 +1,125 @@
|
||||
/**
|
||||
* @mainpage Cryptsetup API
|
||||
*
|
||||
* The 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="http://upstream-tracker.org/versions/libcryptsetup.html">Upstream 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 bellow 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="http://code.google.com/p/cryptsetup/wiki/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
17
docs/examples/Makefile
Normal 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
|
||||
96
docs/examples/crypt_log_usage.c
Normal file
96
docs/examples/crypt_log_usage.c
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* An example of using logging through libcryptsetup API
|
||||
*
|
||||
* Copyright (C) 2011, 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 function that can be registered using crypt_set_log_callback API.
|
||||
*
|
||||
* Its prototype is void (*log)(int level, const char *msg, void *usrptr) as defined
|
||||
* in crypt_set_log_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 function 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 function */
|
||||
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;
|
||||
}
|
||||
294
docs/examples/crypt_luks_usage.c
Normal file
294
docs/examples/crypt_luks_usage.c
Normal file
@@ -0,0 +1,294 @@
|
||||
/*
|
||||
* An example of using LUKS device through libcryptsetup API
|
||||
*
|
||||
* Copyright (C) 2011, 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;
|
||||
struct crypt_params_luks1 params;
|
||||
int r;
|
||||
|
||||
/*
|
||||
* crypt_init() call precedes most of operations of cryptsetup API. The call is used
|
||||
* to initialize crypt device context stored in structure referenced by _cd_ in
|
||||
* the example. Second parameter is used to pass underlaying device path.
|
||||
*
|
||||
* Note:
|
||||
* If path refers to a regular file it'll be attached to a first free loop device.
|
||||
* crypt_init() operation fails in case there's no more loop device available.
|
||||
* Also, loop device will have the AUTOCLEAR flag set, so the file loopback 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 on your device. This will change with call of
|
||||
* crypt_format() only if you specify CRYPT_LUKS1 as device type.
|
||||
*/
|
||||
printf("Device %s will be formatted to LUKS device after 5 seconds.\n"
|
||||
"Press CTRL+C now if you want to cancel this operation.\n", path);
|
||||
sleep(5);
|
||||
|
||||
|
||||
/*
|
||||
* Prepare LUKS format parameters
|
||||
*
|
||||
* hash parameter defines PBKDF2 hash algorithm used in LUKS header.
|
||||
* For compatibility reason we use SHA1 here.
|
||||
*/
|
||||
params.hash = "sha1";
|
||||
|
||||
/*
|
||||
* data_alignment parameter is relevant only in case of the luks header
|
||||
* and the payload are both stored on same device.
|
||||
*
|
||||
* if you set data_alignment = 0, cryptsetup will autodetect
|
||||
* data_alignment according to underlaying device topology.
|
||||
*/
|
||||
params.data_alignment = 0;
|
||||
|
||||
/*
|
||||
* data_device parameter defines that no external device
|
||||
* for luks header will be used
|
||||
*/
|
||||
params.data_device = NULL;
|
||||
|
||||
/*
|
||||
* NULLs for uuid and volume_key means that these attributes will be
|
||||
* generated during crypt_format(). Volume key is generated with respect
|
||||
* to key size parameter passed to function.
|
||||
*
|
||||
* crypt_format() checks device size (LUKS header must fit there).
|
||||
*/
|
||||
r = crypt_format(cd, /* crypt context */
|
||||
CRYPT_LUKS1, /* LUKS1 is standard LUKS header */
|
||||
"aes", /* used cipher */
|
||||
"xts-plain64", /* used block mode and IV generator*/
|
||||
NULL, /* generate UUID */
|
||||
NULL, /* generate volume key from RNG */
|
||||
256 / 8, /* 256bit key - here AES-128 in XTS mode, size is in bytes */
|
||||
¶ms); /* parameters above */
|
||||
|
||||
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 LUKS1 header, but there is
|
||||
* no active keyslot with encrypted volume key yet.
|
||||
*/
|
||||
|
||||
/*
|
||||
* cryptt_kesylot_add_* call stores volume_key in encrypted form into keyslot.
|
||||
* Without keyslot you can't manipulate with LUKS device after the context will be freed.
|
||||
*
|
||||
* To create a new keyslot you need to supply the existing one (to get the volume key from) or
|
||||
* you need to supply the volume key.
|
||||
*
|
||||
* After format, we have volume key stored internally in context so add new keyslot
|
||||
* using this internal volume key.
|
||||
*/
|
||||
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 using the first keyslot.
|
||||
* It will decrypt volume key from the first keyslot and creates new one with another 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.
|
||||
* It's sequence of sub-steps: device initialization, LUKS header load
|
||||
* and the device activation itself.
|
||||
*/
|
||||
r = crypt_init(&cd, path);
|
||||
if (r < 0 ) {
|
||||
printf("crypt_init() failed for %s.\n", path);
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* crypt_load() is used to load the LUKS header from block device
|
||||
* into crypt_device context.
|
||||
*/
|
||||
r = crypt_load(cd, /* crypt context */
|
||||
CRYPT_LUKS1, /* requested 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 device-mapper devie mapping with name device_name.
|
||||
*/
|
||||
r = crypt_activate_by_passphrase(cd, /* crypt context */
|
||||
device_name, /* device name to activate */
|
||||
CRYPT_ANY_SLOT,/* which slot use (ANY - try all) */
|
||||
"foo", 3, /* passphrase */
|
||||
CRYPT_ACTIVATE_READONLY); /* flags */
|
||||
if (r < 0) {
|
||||
printf("Device %s activation failed.\n", device_name);
|
||||
crypt_free(cd);
|
||||
return r;
|
||||
}
|
||||
|
||||
printf("LUKS device %s/%s is active.\n", 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 active device (query DM backend)
|
||||
*/
|
||||
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 device context and loads LUKS header from backing device
|
||||
*/
|
||||
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 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;
|
||||
}
|
||||
BIN
docs/on-disk-format.pdf
Normal file
BIN
docs/on-disk-format.pdf
Normal file
Binary file not shown.
131
docs/v1.4.0-ReleaseNotes
Normal file
131
docs/v1.4.0-ReleaseNotes
Normal 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 suport 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
25
docs/v1.4.1-ReleaseNotes
Normal 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
44
docs/v1.4.2-ReleaseNotes
Normal 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
62
docs/v1.4.3-ReleaseNotes
Normal 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
241
docs/v1.5.0-ReleaseNotes
Normal file
@@ -0,0 +1,241 @@
|
||||
Cryptsetup 1.5.0 Release Notes
|
||||
==============================
|
||||
|
||||
This release covers mainly inclusion of:
|
||||
|
||||
* Veritysetup tool (and related libcryptsetup extensions for dm-verity).
|
||||
|
||||
* Experimental cryptsetup-reencrypt tool (LUKS offline reencryption).
|
||||
|
||||
Changes since version 1.5.0-rc2
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Add --device-size option for reencryption tool.
|
||||
|
||||
* Switch to use unit suffix for --reduce-device-size option.
|
||||
|
||||
* Remove open device debugging feature (no longer needed).
|
||||
|
||||
* Fix library name for FIPS check.
|
||||
|
||||
* Add example of using reencryption inside dracut (see misc/dracut).
|
||||
|
||||
Changes since version 1.5.0-rc1
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Introduce cryptsetup-reencrypt - experimental offline LUKS reencryption tool.
|
||||
|
||||
! cryptsetup-reencrypt tool is EXPERIMENTAL
|
||||
! ALWAYS BE SURE YOU HAVE RELIABLE BACKUP BEFORE USING THIS TOOL
|
||||
|
||||
This tool tries to simplify situation when you need to re-encrypt the whole
|
||||
LUKS device in situ (without need to move data elsewhere).
|
||||
|
||||
This can happen for example when you want to change volume (master) key,
|
||||
encryption algorithm, or other encryption parameter.
|
||||
|
||||
Cryptsetup-reencrypt can even optionally shift data on device
|
||||
(reducing data device size - you need some free space at the end of device).
|
||||
|
||||
In general, cryptsetup-reencrypt can be used to
|
||||
|
||||
- re-generate volume key
|
||||
- change arbitrary encryption parameters
|
||||
- add encryption to not yet encrypted drive
|
||||
|
||||
Side effect of reencryption is that final device will contain
|
||||
only ciphertext (for all sectors) so even if device was not properly
|
||||
wiped by random data, after reencryption you cannot distinguish
|
||||
which sectors are used.
|
||||
(Reecryption is done always for the whole device.)
|
||||
|
||||
There are for sure bugs, please TEST IT IN TEST ENVIRONMENT before
|
||||
use for your data.
|
||||
|
||||
This tool is not resistant to HW and kernel failures - hw crash
|
||||
will cause serious data corruption.
|
||||
|
||||
You can enable compilation of this tool with --enable-cryptsetup-reencrypt
|
||||
configure option (it is switched off by default).
|
||||
(Tool requires libcryptsetup 1.4.3 and later.)
|
||||
|
||||
You have to provide all keyslot passphrases or use --keyslot-option
|
||||
(then all other keyslots will be disabled).
|
||||
|
||||
EXAMPLES (from man page)
|
||||
|
||||
Reencrypt /dev/sdb1 (change volume key)
|
||||
# cryptsetup-reencrypt /dev/sdb1
|
||||
|
||||
Reencrypt and also change cipher and cipher mode
|
||||
# cryptsetup-reencrypt /dev/sdb1 -c aes-xts-plain64
|
||||
|
||||
Note: if you are changing key size, there must be enough space
|
||||
for keyslots in header or you have to use --reduce-device size and
|
||||
reduce fs in advance.
|
||||
|
||||
Add LUKS encryption to not yet encrypted device
|
||||
First, be sure you have space added to disk.
|
||||
Or, alternatively, shrink filesystem in advance.
|
||||
|
||||
Here we need 4096 512-bytes sectors (enough for 2x128 bit key).
|
||||
|
||||
# fdisk -u /dev/sdb # move sdb1 partition end + 4096 sectors
|
||||
|
||||
# cryptsetup-reencrypt /dev/sdb1 --new --reduce-device-size 4096
|
||||
|
||||
There are some options which can improve performance (depends on system),
|
||||
namely --use-directio (use direct IO for all operations) can be faster
|
||||
on some systems. See man page.
|
||||
|
||||
Progress and estimated time is printed during reencryption.
|
||||
|
||||
You can suspend reencryption (using ctrl+c or term signal).
|
||||
To continue reencryption you have to provide only
|
||||
the device parameter (offset is stored in temporary log file).
|
||||
|
||||
Please note LUKS device is marked invalid during reencryption and
|
||||
you have to retain tool temporary files until reencryption finishes.
|
||||
|
||||
Temporary files are LUKS-<uuid>.[log|org|new]
|
||||
|
||||
Other changes
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
* Fix luks-header-from-active script (do not use LUKS header on-disk, add UUID).
|
||||
|
||||
* Add --test-passphrase option for luksOpen (check passphrase only).
|
||||
|
||||
* Fix parsing of hexadecimal string (salt or root hash) in veritysetup.
|
||||
|
||||
Changes since version 1.4.3
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Introduce veritysetup tool for dm-verity target management.
|
||||
|
||||
The dm-verity device-mapper target was added to Linux kernel 3.4 and
|
||||
provides transparent integrity checking of block devices using a cryptographic
|
||||
digest provided by the kernel crypto API. This target is read-only.
|
||||
|
||||
It is meant to be setup as part of a verified boot path (it was originally
|
||||
developed by Chrome OS authors as part of verified boot infrastructure).
|
||||
|
||||
For deeper description please see http://code.google.com/p/cryptsetup/wiki/DMVerity
|
||||
and kernel dm-verity documentation.
|
||||
|
||||
The libcryptsetup library was extended to support manipulation
|
||||
with dm-verity kernel module and new veritysetup CLI tool is added.
|
||||
|
||||
There are no additional library requirements (it uses the same crypto
|
||||
backend as cryptsetup).
|
||||
|
||||
If you want compile cryptsetup without veritysetup tool,
|
||||
use --disable-veritysetup configure option.
|
||||
For other configuration option see configure --help and veritysetup --help
|
||||
(e.g. default parameters).
|
||||
|
||||
Supported libcryptsetup functions new CRYPT_VERITY type:
|
||||
crypt_init
|
||||
crypt_init_by_name
|
||||
crypt_set_data device
|
||||
crypt_get_type
|
||||
crypt_format
|
||||
crypt_load
|
||||
crypt_get_active_device
|
||||
crypt_activate_by_volume_key (volume key == root hash here)
|
||||
crypt_dump
|
||||
and new introduced function
|
||||
crypt_get_verity_info
|
||||
|
||||
Please see comments in libcryptsetup.h and veritysetup.c as an code example
|
||||
how to use CRYPT_VERITY API.
|
||||
|
||||
The veritysetup tool supports these operations:
|
||||
|
||||
veritysetup format <data_device> <hash_device>
|
||||
Formats <hash_device> (calculates all hash areas according to <data_device>).
|
||||
This is initial command to prepare device <hash_device> for later verification.
|
||||
|
||||
veritysetup create <name> <data_device> <hash_device> <root_hash>
|
||||
Creates (activates) a dm-verity mapping with <name> backed by device <data_device>
|
||||
and using <hash_device> for in-kernel verification.
|
||||
|
||||
veritysetup verify <data_device> <hash_device> <root_hash>
|
||||
Verifies data in userspace (no kernel device is activated).
|
||||
|
||||
veritysetup remove <name>
|
||||
Removes activated device from kernel (similar to dmsetup remove).
|
||||
|
||||
veritysetup status <name>
|
||||
Reports status for the active kernel dm-verity device.
|
||||
|
||||
veritysetup dump <hash_device>
|
||||
Reports parameters of verity device from on-disk stored superblock.
|
||||
|
||||
For more info see veritysetup --help and veritysetup man page.
|
||||
|
||||
Other changes
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
* Both data and header device can now be a file and
|
||||
loop device is automatically allocated.
|
||||
|
||||
* Require only up to last keyslot area for header device, previously
|
||||
backup (and activation) required device/file of size up to data start
|
||||
offset (data payload).
|
||||
|
||||
* Fix header backup and restore to work on files with large data offset.
|
||||
Backup and restore now works even if backup file is smaller than data offset.
|
||||
|
||||
Appendix: Examples of veritysetup use
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Format device using default parameters, info and final root hash is printed:
|
||||
# veritysetup format /dev/sdb /dev/sdc
|
||||
VERITY header information for /dev/sdc
|
||||
UUID: fad30431-0c59-4fa6-9b57-732a90501f75
|
||||
Hash type: 1
|
||||
Data blocks: 52224
|
||||
Data block size: 4096
|
||||
Hash block size: 4096
|
||||
Hash algorithm: sha256
|
||||
Salt: 5cc52759af76a092e0c21829cd0ef6938f69831bf86926525106f92a7e9e3aa9
|
||||
Root hash: 7aefa4506f7af497ac491a27f862cf8005ea782a5d97f6426945a6896ab557a1
|
||||
|
||||
Activation of device in-kernel:
|
||||
# veritysetup create vr /dev/sdb /dev/sdc 7aefa4506f7af497ac491a27f862cf8005ea782a5d97f6426945a6896ab557a1
|
||||
Note - if device is corrupted, kernel mapping is created but will report failure:
|
||||
Verity device detected corruption after activation.
|
||||
|
||||
Userspace verification:
|
||||
# veritysetup verify /dev/sdb /dev/sdc 7aefa4506f7af497ac491a27f862cf8005ea782a5d97f6426945a6896ab557a1
|
||||
Verification failed at position 8192.
|
||||
Verification of data area failed.
|
||||
|
||||
Active device status report:
|
||||
# veritysetup status vr
|
||||
/dev/mapper/vr is active.
|
||||
type: VERITY
|
||||
status: verified
|
||||
hash type: 1
|
||||
data block: 4096
|
||||
hash block: 4096
|
||||
hash name: sha256
|
||||
salt: 5cc52759af76a092e0c21829cd0ef6938f69831bf86926525106f92a7e9e3aa9
|
||||
data device: /dev/sdb
|
||||
size: 417792 sectors
|
||||
mode: readonly
|
||||
hash device: /dev/sdc
|
||||
hash offset: 8 sectors
|
||||
|
||||
Dump of on-disk superblock information:
|
||||
# veritysetup dump /dev/sdc
|
||||
VERITY header information for /dev/sdc
|
||||
UUID: fad30431-0c59-4fa6-9b57-732a90501f75
|
||||
Hash type: 1
|
||||
Data blocks: 52224
|
||||
Data block size: 4096
|
||||
Hash block size: 4096
|
||||
Hash algorithm: sha256
|
||||
Salt: 5cc52759af76a092e0c21829cd0ef6938f69831bf86926525106f92a7e9e3aa9
|
||||
|
||||
Remove mapping:
|
||||
# veritysetup remove vr
|
||||
@@ -1,4 +1,4 @@
|
||||
SUBDIRS = crypto_backend luks1 loopaes
|
||||
SUBDIRS = crypto_backend luks1 loopaes verity
|
||||
|
||||
moduledir = $(libdir)/cryptsetup
|
||||
|
||||
@@ -10,6 +10,7 @@ INCLUDES = \
|
||||
-I$(top_srcdir)/lib/crypto_backend \
|
||||
-I$(top_srcdir)/lib/luks1 \
|
||||
-I$(top_srcdir)/lib/loopaes \
|
||||
-I$(top_srcdir)/lib/verity \
|
||||
-DDATADIR=\""$(datadir)"\" \
|
||||
-DLIBDIR=\""$(libdir)"\" \
|
||||
-DPREFIX=\""$(prefix)"\" \
|
||||
@@ -24,7 +25,8 @@ lib_LTLIBRARIES = libcryptsetup.la
|
||||
common_ldadd = \
|
||||
crypto_backend/libcrypto_backend.la \
|
||||
luks1/libluks1.la \
|
||||
loopaes/libloopaes.la
|
||||
loopaes/libloopaes.la \
|
||||
verity/libverity.la
|
||||
|
||||
libcryptsetup_la_DEPENDENCIES = $(common_ldadd) libcryptsetup.sym
|
||||
|
||||
@@ -38,21 +40,25 @@ libcryptsetup_la_LIBADD = \
|
||||
@UUID_LIBS@ \
|
||||
@DEVMAPPER_LIBS@ \
|
||||
@CRYPTO_LIBS@ \
|
||||
@FIPSCHECK_LIBS@ \
|
||||
$(common_ldadd)
|
||||
|
||||
|
||||
libcryptsetup_la_SOURCES = \
|
||||
setup.c \
|
||||
internal.h \
|
||||
bitops.h \
|
||||
nls.h \
|
||||
libcryptsetup.h \
|
||||
utils.c \
|
||||
utils_crypt.c \
|
||||
utils_crypt.h \
|
||||
utils_debug.c \
|
||||
utils_loop.c \
|
||||
utils_loop.h \
|
||||
utils_devpath.c \
|
||||
utils_wipe.c \
|
||||
utils_fips.c \
|
||||
utils_fips.h \
|
||||
libdevmapper.c \
|
||||
utils_dm.h \
|
||||
volumekey.c \
|
||||
|
||||
83
lib/bitops.h
Normal file
83
lib/bitops.h
Normal file
@@ -0,0 +1,83 @@
|
||||
#ifndef BITOPS_H
|
||||
#define BITOPS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* Bit map related macros. Usually provided by libc.
|
||||
*/
|
||||
#include <sys/param.h>
|
||||
|
||||
#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
|
||||
|
||||
/*
|
||||
* Byte swab macros (based on linux/byteorder/swab.h)
|
||||
*/
|
||||
#define swab16(x) \
|
||||
((uint16_t)( \
|
||||
(((uint16_t)(x) & (uint16_t)0x00ffU) << 8) | \
|
||||
(((uint16_t)(x) & (uint16_t)0xff00U) >> 8) ))
|
||||
|
||||
#define swab32(x) \
|
||||
((uint32_t)( \
|
||||
(((uint32_t)(x) & (uint32_t)0x000000ffUL) << 24) | \
|
||||
(((uint32_t)(x) & (uint32_t)0x0000ff00UL) << 8) | \
|
||||
(((uint32_t)(x) & (uint32_t)0x00ff0000UL) >> 8) | \
|
||||
(((uint32_t)(x) & (uint32_t)0xff000000UL) >> 24) ))
|
||||
|
||||
#define swab64(x) \
|
||||
((uint64_t)( \
|
||||
(uint64_t)(((uint64_t)(x) & (uint64_t)0x00000000000000ffULL) << 56) | \
|
||||
(uint64_t)(((uint64_t)(x) & (uint64_t)0x000000000000ff00ULL) << 40) | \
|
||||
(uint64_t)(((uint64_t)(x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \
|
||||
(uint64_t)(((uint64_t)(x) & (uint64_t)0x00000000ff000000ULL) << 8) | \
|
||||
(uint64_t)(((uint64_t)(x) & (uint64_t)0x000000ff00000000ULL) >> 8) | \
|
||||
(uint64_t)(((uint64_t)(x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \
|
||||
(uint64_t)(((uint64_t)(x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \
|
||||
(uint64_t)(((uint64_t)(x) & (uint64_t)0xff00000000000000ULL) >> 56) ))
|
||||
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
|
||||
#define cpu_to_le16(x) swab16(x)
|
||||
#define cpu_to_le32(x) swab32(x)
|
||||
#define cpu_to_le64(x) swab64(x)
|
||||
#define cpu_to_be16(x) ((uint16_t)(x))
|
||||
#define cpu_to_be32(x) ((uint32_t)(x))
|
||||
#define cpu_to_be64(x) ((uint64_t)(x))
|
||||
|
||||
#define le16_to_cpu(x) swab16(x)
|
||||
#define le32_to_cpu(x) swab32(x)
|
||||
#define le64_to_cpu(x) swab64(x)
|
||||
#define be16_to_cpu(x) ((uint16_t)(x))
|
||||
#define be32_to_cpu(x) ((uint32_t)(x))
|
||||
#define be64_to_cpu(x) ((uint64_t)(x))
|
||||
|
||||
#else /* !WORDS_BIGENDIAN */
|
||||
|
||||
#define cpu_to_le16(x) ((uint16_t)(x))
|
||||
#define cpu_to_le32(x) ((uint32_t)(x))
|
||||
#define cpu_to_le64(x) ((uint64_t)(x))
|
||||
#define cpu_to_be16(x) swab16(x)
|
||||
#define cpu_to_be32(x) swab32(x)
|
||||
#define cpu_to_be64(x) swab64(x)
|
||||
|
||||
#define le16_to_cpu(x) ((uint16_t)(x))
|
||||
#define le32_to_cpu(x) ((uint32_t)(x))
|
||||
#define le64_to_cpu(x) ((uint64_t)(x))
|
||||
#define be16_to_cpu(x) swab16(x)
|
||||
#define be32_to_cpu(x) swab32(x)
|
||||
#define be64_to_cpu(x) swab64(x)
|
||||
|
||||
#endif /* WORDS_BIGENDIAN */
|
||||
|
||||
#endif /* BITOPS_H */
|
||||
@@ -15,15 +15,15 @@
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "libcryptsetup.h"
|
||||
#include "internal.h"
|
||||
#include "crypto_backend.h"
|
||||
|
||||
static int hash(const char *hash_name, size_t key_size, char *key,
|
||||
size_t passphrase_size, const char *passphrase)
|
||||
@@ -54,8 +54,6 @@ static int hash(const char *hash_name, size_t key_size, char *key,
|
||||
|
||||
key += len;
|
||||
key_size -= len;
|
||||
if (key_size && crypt_hash_restart(md))
|
||||
r = 1;
|
||||
}
|
||||
|
||||
crypt_hash_destroy(md);
|
||||
|
||||
@@ -1,9 +1,28 @@
|
||||
/*
|
||||
* crypto backend implementation
|
||||
*
|
||||
* Copyright (C) 2010-2012, Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
#ifndef _CRYPTO_BACKEND_H
|
||||
#define _CRYPTO_BACKEND_H
|
||||
|
||||
#include "libcryptsetup.h"
|
||||
#include "internal.h"
|
||||
#include <stdint.h>
|
||||
#include "config.h"
|
||||
|
||||
struct crypt_device;
|
||||
struct crypt_hash;
|
||||
struct crypt_hmac;
|
||||
|
||||
@@ -12,11 +31,11 @@ int crypt_backend_init(struct crypt_device *ctx);
|
||||
#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_restart(struct crypt_hash *ctx);
|
||||
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);
|
||||
int crypt_hash_destroy(struct crypt_hash *ctx);
|
||||
@@ -25,9 +44,12 @@ int crypt_hash_destroy(struct crypt_hash *ctx);
|
||||
int crypt_hmac_size(const char *name);
|
||||
int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
|
||||
const void *buffer, size_t length);
|
||||
int crypt_hmac_restart(struct crypt_hmac *ctx);
|
||||
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);
|
||||
int crypt_hmac_destroy(struct crypt_hmac *ctx);
|
||||
|
||||
/* RNG (if fips paramater 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);
|
||||
|
||||
#endif /* _CRYPTO_BACKEND_H */
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* GCRYPT crypto backend implementation
|
||||
*
|
||||
* Copyright (C) 2010-2011, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2010-2012, Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -14,18 +14,19 @@
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* 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.h"
|
||||
|
||||
#define GCRYPT_REQ_VERSION "1.1.42"
|
||||
|
||||
static int crypto_backend_initialised = 0;
|
||||
static int crypto_backend_secmem = 1;
|
||||
static char version[64];
|
||||
|
||||
struct crypt_hash {
|
||||
gcry_md_hd_t hd;
|
||||
@@ -39,12 +40,11 @@ struct crypt_hmac {
|
||||
int hash_len;
|
||||
};
|
||||
|
||||
int crypt_backend_init(struct crypt_device *ctx __attribute__((unused)))
|
||||
int crypt_backend_init(struct crypt_device *ctx)
|
||||
{
|
||||
if (crypto_backend_initialised)
|
||||
return 0;
|
||||
|
||||
log_dbg("Initialising gcrypt crypto backend.");
|
||||
if (!gcry_control (GCRYCTL_INITIALIZATION_FINISHED_P)) {
|
||||
if (!gcry_check_version (GCRYPT_REQ_VERSION)) {
|
||||
return -ENOSYS;
|
||||
@@ -57,8 +57,8 @@ int crypt_backend_init(struct crypt_device *ctx __attribute__((unused)))
|
||||
* and it locks its memory space anyway.
|
||||
*/
|
||||
#if 0
|
||||
log_dbg("Initializing crypto backend (secure memory disabled).");
|
||||
gcry_control (GCRYCTL_DISABLE_SECMEM);
|
||||
crypto_backend_secmem = 0;
|
||||
#else
|
||||
|
||||
gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
|
||||
@@ -68,10 +68,18 @@ int crypt_backend_init(struct crypt_device *ctx __attribute__((unused)))
|
||||
gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
|
||||
}
|
||||
|
||||
snprintf(version, 64, "gcrypt %s%s",
|
||||
gcry_check_version(NULL),
|
||||
crypto_backend_secmem ? "" : ", secmem disabled");
|
||||
crypto_backend_initialised = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *crypt_backend_version(void)
|
||||
{
|
||||
return crypto_backend_initialised ? version : "";
|
||||
}
|
||||
|
||||
uint32_t crypt_backend_flags(void)
|
||||
{
|
||||
return 0;
|
||||
@@ -117,10 +125,9 @@ int crypt_hash_init(struct crypt_hash **ctx, const char *name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crypt_hash_restart(struct crypt_hash *ctx)
|
||||
static void crypt_hash_restart(struct crypt_hash *ctx)
|
||||
{
|
||||
gcry_md_reset(ctx->hd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crypt_hash_write(struct crypt_hash *ctx, const char *buffer, size_t length)
|
||||
@@ -141,6 +148,8 @@ int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length)
|
||||
return -EINVAL;
|
||||
|
||||
memcpy(buffer, hash, length);
|
||||
crypt_hash_restart(ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -191,10 +200,9 @@ int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crypt_hmac_restart(struct crypt_hmac *ctx)
|
||||
static void crypt_hmac_restart(struct crypt_hmac *ctx)
|
||||
{
|
||||
gcry_md_reset(ctx->hd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crypt_hmac_write(struct crypt_hmac *ctx, const char *buffer, size_t length)
|
||||
@@ -215,6 +223,8 @@ int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length)
|
||||
return -EINVAL;
|
||||
|
||||
memcpy(buffer, hash, length);
|
||||
crypt_hmac_restart(ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -225,3 +235,19 @@ int crypt_hmac_destroy(struct crypt_hmac *ctx)
|
||||
free(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Linux kernel userspace API crypto backend implementation
|
||||
*
|
||||
* Copyright (C) 2010-2011, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2010-2012, Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
@@ -36,6 +36,7 @@
|
||||
#endif
|
||||
|
||||
static int crypto_backend_initialised = 0;
|
||||
static char version[64];
|
||||
|
||||
struct hash_alg {
|
||||
const char *name;
|
||||
@@ -93,7 +94,6 @@ bad:
|
||||
int crypt_backend_init(struct crypt_device *ctx)
|
||||
{
|
||||
struct utsname uts;
|
||||
|
||||
struct sockaddr_alg sa = {
|
||||
.salg_family = AF_ALG,
|
||||
.salg_type = "hash",
|
||||
@@ -104,11 +104,8 @@ int crypt_backend_init(struct crypt_device *ctx)
|
||||
if (crypto_backend_initialised)
|
||||
return 0;
|
||||
|
||||
log_dbg("Initialising kernel crypto API backend.");
|
||||
|
||||
if (uname(&uts) == -1 || strcmp(uts.sysname, "Linux"))
|
||||
return -EINVAL;
|
||||
log_dbg("Kernel version %s %s.", uts.sysname, uts.release);
|
||||
|
||||
if (_socket_init(&sa, &tfmfd, &opfd) < 0)
|
||||
return -EINVAL;
|
||||
@@ -116,6 +113,9 @@ int crypt_backend_init(struct crypt_device *ctx)
|
||||
close(tfmfd);
|
||||
close(opfd);
|
||||
|
||||
snprintf(version, sizeof(version), "%s %s kernel cryptoAPI",
|
||||
uts.sysname, uts.release);
|
||||
|
||||
crypto_backend_initialised = 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -125,6 +125,11 @@ 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;
|
||||
@@ -176,11 +181,6 @@ int crypt_hash_init(struct crypt_hash **ctx, const char *name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crypt_hash_restart(struct crypt_hash *ctx)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crypt_hash_write(struct crypt_hash *ctx, const char *buffer, size_t length)
|
||||
{
|
||||
ssize_t r;
|
||||
@@ -261,11 +261,6 @@ int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crypt_hmac_restart(struct crypt_hmac *ctx)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crypt_hmac_write(struct crypt_hmac *ctx, const char *buffer, size_t length)
|
||||
{
|
||||
ssize_t r;
|
||||
@@ -301,3 +296,9 @@ int crypt_hmac_destroy(struct crypt_hmac *ctx)
|
||||
free(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* RNG - N/A */
|
||||
int crypt_backend_rng(char *buffer, size_t length, int quality, int fips)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Nettle crypto backend implementation
|
||||
*
|
||||
* Copyright (C) 2011 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2011-2012 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
@@ -24,6 +24,8 @@
|
||||
#include <nettle/hmac.h>
|
||||
#include "crypto_backend.h"
|
||||
|
||||
static char *version = "Nettle";
|
||||
|
||||
typedef void (*init_func) (void *);
|
||||
typedef void (*update_func) (void *, unsigned, const uint8_t *);
|
||||
typedef void (*digest_func) (void *, unsigned, uint8_t *);
|
||||
@@ -81,6 +83,14 @@ static struct hash_alg hash_algs[] = {
|
||||
(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,
|
||||
},
|
||||
{ NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, }
|
||||
};
|
||||
|
||||
@@ -127,10 +137,14 @@ static struct hash_alg *_get_alg(const char *name)
|
||||
|
||||
int crypt_backend_init(struct crypt_device *ctx)
|
||||
{
|
||||
log_dbg("Initialising Nettle crypto backend.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *crypt_backend_version(void)
|
||||
{
|
||||
return version;
|
||||
}
|
||||
|
||||
/* HASH */
|
||||
int crypt_hash_size(const char *name)
|
||||
{
|
||||
@@ -159,10 +173,9 @@ int crypt_hash_init(struct crypt_hash **ctx, const char *name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crypt_hash_restart(struct crypt_hash *ctx)
|
||||
static void crypt_hash_restart(struct crypt_hash *ctx)
|
||||
{
|
||||
ctx->hash->init(&ctx->nettle_ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crypt_hash_write(struct crypt_hash *ctx, const char *buffer, size_t length)
|
||||
@@ -177,6 +190,7 @@ int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length)
|
||||
return -EINVAL;
|
||||
|
||||
ctx->hash->digest(&ctx->nettle_ctx, length, (uint8_t *)buffer);
|
||||
crypt_hash_restart(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -225,10 +239,9 @@ bad:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int crypt_hmac_restart(struct crypt_hmac *ctx)
|
||||
static void crypt_hmac_restart(struct crypt_hmac *ctx)
|
||||
{
|
||||
ctx->hash->hmac_set_key(&ctx->nettle_ctx, ctx->key_length, ctx->key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crypt_hmac_write(struct crypt_hmac *ctx, const char *buffer, size_t length)
|
||||
@@ -243,6 +256,7 @@ int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length)
|
||||
return -EINVAL;
|
||||
|
||||
ctx->hash->hmac_digest(&ctx->nettle_ctx, length, (uint8_t *)buffer);
|
||||
crypt_hmac_restart(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -254,3 +268,9 @@ int crypt_hmac_destroy(struct crypt_hmac *ctx)
|
||||
free(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* RNG - N/A */
|
||||
int crypt_backend_rng(char *buffer, size_t length, int quality, int fips)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* NSS crypto backend implementation
|
||||
*
|
||||
* Copyright (C) 2010-2011, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2010-2012, Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
@@ -23,7 +23,10 @@
|
||||
#include <pk11pub.h>
|
||||
#include "crypto_backend.h"
|
||||
|
||||
#define CONST_CAST(x) (x)(uintptr_t)
|
||||
|
||||
static int crypto_backend_initialised = 0;
|
||||
static char version[64];
|
||||
|
||||
struct hash_alg {
|
||||
const char *name;
|
||||
@@ -70,10 +73,14 @@ int crypt_backend_init(struct crypt_device *ctx)
|
||||
if (crypto_backend_initialised)
|
||||
return 0;
|
||||
|
||||
log_dbg("Initialising NSS crypto backend.");
|
||||
if (NSS_NoDB_Init(".") != SECSuccess)
|
||||
return -EINVAL;
|
||||
|
||||
#if HAVE_DECL_NSS_GETVERSION
|
||||
snprintf(version, 64, "NSS %s", NSS_GetVersion());
|
||||
#else
|
||||
snprintf(version, 64, "NSS");
|
||||
#endif
|
||||
crypto_backend_initialised = 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -83,6 +90,11 @@ uint32_t crypt_backend_flags(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *crypt_backend_version(void)
|
||||
{
|
||||
return crypto_backend_initialised ? version : "";
|
||||
}
|
||||
|
||||
/* HASH */
|
||||
int crypt_hash_size(const char *name)
|
||||
{
|
||||
@@ -121,7 +133,7 @@ int crypt_hash_init(struct crypt_hash **ctx, const char *name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crypt_hash_restart(struct crypt_hash *ctx)
|
||||
static int crypt_hash_restart(struct crypt_hash *ctx)
|
||||
{
|
||||
if (PK11_DigestBegin(ctx->md) != SECSuccess)
|
||||
return -EINVAL;
|
||||
@@ -131,7 +143,7 @@ int crypt_hash_restart(struct crypt_hash *ctx)
|
||||
|
||||
int crypt_hash_write(struct crypt_hash *ctx, const char *buffer, size_t length)
|
||||
{
|
||||
if (PK11_DigestOp(ctx->md, (unsigned char *)buffer, length) != SECSuccess)
|
||||
if (PK11_DigestOp(ctx->md, CONST_CAST(unsigned char *)buffer, length) != SECSuccess)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
@@ -154,6 +166,9 @@ int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length)
|
||||
if (tmp_len < length)
|
||||
return -EINVAL;
|
||||
|
||||
if (crypt_hash_restart(ctx))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -179,7 +194,7 @@ int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
|
||||
SECItem noParams;
|
||||
|
||||
keyItem.type = siBuffer;
|
||||
keyItem.data = (unsigned char *)buffer;
|
||||
keyItem.data = CONST_CAST(unsigned char *)buffer;
|
||||
keyItem.len = (int)length;
|
||||
|
||||
noParams.type = siBuffer;
|
||||
@@ -220,7 +235,7 @@ bad:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int crypt_hmac_restart(struct crypt_hmac *ctx)
|
||||
static int crypt_hmac_restart(struct crypt_hmac *ctx)
|
||||
{
|
||||
if (PK11_DigestBegin(ctx->md) != SECSuccess)
|
||||
return -EINVAL;
|
||||
@@ -230,7 +245,7 @@ int crypt_hmac_restart(struct crypt_hmac *ctx)
|
||||
|
||||
int crypt_hmac_write(struct crypt_hmac *ctx, const char *buffer, size_t length)
|
||||
{
|
||||
if (PK11_DigestOp(ctx->md, (unsigned char *)buffer, length) != SECSuccess)
|
||||
if (PK11_DigestOp(ctx->md, CONST_CAST(unsigned char *)buffer, length) != SECSuccess)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
@@ -253,6 +268,9 @@ int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length)
|
||||
if (tmp_len < length)
|
||||
return -EINVAL;
|
||||
|
||||
if (crypt_hmac_restart(ctx))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -268,3 +286,15 @@ int crypt_hmac_destroy(struct crypt_hmac *ctx)
|
||||
free(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* RNG */
|
||||
int crypt_backend_rng(char *buffer, size_t length, int quality, int fips)
|
||||
{
|
||||
if (fips)
|
||||
return -EINVAL;
|
||||
|
||||
if (PK11_GenerateRandom((unsigned char *)buffer, length) != SECSuccess)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* OPENSSL crypto backend implementation
|
||||
*
|
||||
* Copyright (C) 2010-2011, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2010-2012, Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link the code of portions of this program with the
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <errno.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/rand.h>
|
||||
#include "crypto_backend.h"
|
||||
|
||||
static int crypto_backend_initialised = 0;
|
||||
@@ -52,7 +53,6 @@ int crypt_backend_init(struct crypt_device *ctx)
|
||||
return 0;
|
||||
|
||||
OpenSSL_add_all_digests();
|
||||
log_dbg("OpenSSL crypto backend initialized.");
|
||||
|
||||
crypto_backend_initialised = 1;
|
||||
return 0;
|
||||
@@ -63,6 +63,11 @@ uint32_t crypt_backend_flags(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *crypt_backend_version(void)
|
||||
{
|
||||
return SSLeay_version(SSLEAY_VERSION);
|
||||
}
|
||||
|
||||
/* HASH */
|
||||
int crypt_hash_size(const char *name)
|
||||
{
|
||||
@@ -98,7 +103,7 @@ int crypt_hash_init(struct crypt_hash **ctx, const char *name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crypt_hash_restart(struct crypt_hash *ctx)
|
||||
static int crypt_hash_restart(struct crypt_hash *ctx)
|
||||
{
|
||||
if (EVP_DigestInit(&ctx->md, ctx->hash_id) != 1)
|
||||
return -EINVAL;
|
||||
@@ -131,6 +136,9 @@ int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length)
|
||||
if (tmp_len < length)
|
||||
return -EINVAL;
|
||||
|
||||
if (crypt_hash_restart(ctx))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -171,10 +179,9 @@ int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crypt_hmac_restart(struct crypt_hmac *ctx)
|
||||
static void crypt_hmac_restart(struct crypt_hmac *ctx)
|
||||
{
|
||||
HMAC_Init_ex(&ctx->md, NULL, 0, ctx->hash_id, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crypt_hmac_write(struct crypt_hmac *ctx, const char *buffer, size_t length)
|
||||
@@ -199,6 +206,8 @@ int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length)
|
||||
if (tmp_len < length)
|
||||
return -EINVAL;
|
||||
|
||||
crypt_hmac_restart(ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -209,3 +218,15 @@ int crypt_hmac_destroy(struct crypt_hmac *ctx)
|
||||
free(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* RNG */
|
||||
int crypt_backend_rng(char *buffer, size_t length, int quality, int fips)
|
||||
{
|
||||
if (fips)
|
||||
return -EINVAL;
|
||||
|
||||
if (RAND_bytes((unsigned char *)buffer, length) != 1)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,24 @@
|
||||
/*
|
||||
* libcryptsetup - cryptsetup library internal
|
||||
*
|
||||
* Copyright (C) 2004, Christophe Saout <christophe@saout.de>
|
||||
* Copyright (C) 2004-2007, Clemens Fruhwirth <clemens@endorphin.org>
|
||||
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef INTERNAL_H
|
||||
#define INTERNAL_H
|
||||
|
||||
@@ -11,21 +32,23 @@
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "nls.h"
|
||||
#include "bitops.h"
|
||||
#include "utils_crypt.h"
|
||||
#include "utils_loop.h"
|
||||
#include "utils_dm.h"
|
||||
#include "utils_fips.h"
|
||||
#include "crypto_backend.h"
|
||||
|
||||
#include "libcryptsetup.h"
|
||||
|
||||
/* to silent gcc -Wcast-qual for const cast */
|
||||
#define CONST_CAST(x) (x)(uintptr_t)
|
||||
|
||||
#define SECTOR_SHIFT 9
|
||||
#define SECTOR_SIZE (1 << SECTOR_SHIFT)
|
||||
#define DEFAULT_DISK_ALIGNMENT 1048576 /* 1MiB */
|
||||
#define DEFAULT_MEM_ALIGNMENT 4096
|
||||
|
||||
/* private struct crypt_options flags */
|
||||
|
||||
#define CRYPT_FLAG_FREE_DEVICE (1 << 24)
|
||||
#define CRYPT_FLAG_FREE_CIPHER (1 << 25)
|
||||
|
||||
#define CRYPT_FLAG_PRIVATE_MASK ((unsigned int)-1 << 24)
|
||||
#define MAX_ERROR_LENGTH 512
|
||||
|
||||
#define at_least(a, b) ({ __typeof__(a) __at_least = (a); (__at_least >= (b))?__at_least:(b); })
|
||||
|
||||
@@ -42,11 +65,9 @@ void crypt_free_volume_key(struct volume_key *vk);
|
||||
|
||||
int crypt_confirm(struct crypt_device *cd, const char *msg);
|
||||
|
||||
void set_error_va(const char *fmt, va_list va);
|
||||
void set_error(const char *fmt, ...);
|
||||
const char *get_error(void);
|
||||
|
||||
char *crypt_lookup_dev(const char *dev_id);
|
||||
int crypt_sysfs_check_crypt_segment(const char *device, uint64_t offset, uint64_t size);
|
||||
int crypt_sysfs_get_rotational(int major, int minor, int *rotational);
|
||||
|
||||
int sector_size_for_device(const char *device);
|
||||
int device_read_ahead(const char *dev, uint32_t *read_ahead);
|
||||
@@ -54,28 +75,25 @@ ssize_t write_blockwise(int fd, void *buf, size_t count);
|
||||
ssize_t read_blockwise(int fd, void *_buf, size_t count);
|
||||
ssize_t write_lseek_blockwise(int fd, char *buf, size_t count, off_t offset);
|
||||
int device_ready(struct crypt_device *cd, const char *device, int mode);
|
||||
int get_device_infos(const char *device,
|
||||
int open_exclusive,
|
||||
int *readonly,
|
||||
uint64_t *size);
|
||||
int device_size(const char *device, uint64_t *size);
|
||||
|
||||
unsigned crypt_getpagesize(void);
|
||||
|
||||
enum devcheck { DEV_OK = 0, DEV_EXCL = 1, DEV_SHARED = 2 };
|
||||
int device_check_and_adjust(struct crypt_device *cd,
|
||||
const char *device,
|
||||
int open_exclusive,
|
||||
enum devcheck device_check,
|
||||
uint64_t *size,
|
||||
uint64_t *offset,
|
||||
int *read_only);
|
||||
int wipe_device_header(const char *device, int sectors);
|
||||
uint32_t *flags);
|
||||
|
||||
void logger(struct crypt_device *cd, int class, const char *file, int line, const char *format, ...);
|
||||
#define log_dbg(x...) logger(NULL, CRYPT_LOG_DEBUG, __FILE__, __LINE__, x)
|
||||
#define log_std(c, x...) logger(c, CRYPT_LOG_NORMAL, __FILE__, __LINE__, x)
|
||||
#define log_verbose(c, x...) logger(c, CRYPT_LOG_VERBOSE, __FILE__, __LINE__, x)
|
||||
#define log_err(c, x...) do { \
|
||||
logger(c, CRYPT_LOG_ERROR, __FILE__, __LINE__, x); \
|
||||
set_error(x); } while(0)
|
||||
#define log_err(c, x...) logger(c, CRYPT_LOG_ERROR, __FILE__, __LINE__, x)
|
||||
|
||||
int crypt_get_debug_level(void);
|
||||
void debug_processes_using_device(const char *name);
|
||||
|
||||
int crypt_memlock_inc(struct crypt_device *ctx);
|
||||
int crypt_memlock_dec(struct crypt_device *ctx);
|
||||
@@ -85,7 +103,6 @@ void get_topology_alignment(const char *device,
|
||||
unsigned long *alignment_offset, /* bytes */
|
||||
unsigned long default_alignment);
|
||||
|
||||
enum { CRYPT_RND_NORMAL = 0, CRYPT_RND_KEY = 1 };
|
||||
int crypt_random_init(struct crypt_device *ctx);
|
||||
int crypt_random_get(struct crypt_device *ctx, char *buf, size_t len, int quality);
|
||||
void crypt_random_exit(void);
|
||||
@@ -95,5 +112,29 @@ int crypt_plain_hash(struct crypt_device *ctx,
|
||||
const char *hash_name,
|
||||
char *key, size_t key_size,
|
||||
const char *passphrase, size_t passphrase_size);
|
||||
int PLAIN_activate(struct crypt_device *cd,
|
||||
const char *name,
|
||||
struct volume_key *vk,
|
||||
uint64_t size,
|
||||
uint32_t flags);
|
||||
|
||||
/**
|
||||
* Different methods used to erase sensitive data concerning
|
||||
* either encrypted payload area or master key inside keyslot
|
||||
* area
|
||||
*/
|
||||
typedef enum {
|
||||
CRYPT_WIPE_ZERO, /**< overwrite area using zero blocks */
|
||||
CRYPT_WIPE_DISK, /**< erase disk (using Gutmann method if it is rotational disk)*/
|
||||
CRYPT_WIPE_SSD, /**< erase solid state disk (random write) */
|
||||
CRYPT_WIPE_RANDOM /**< overwrite area using some up to now unspecified
|
||||
* random algorithm */
|
||||
} crypt_wipe_type;
|
||||
|
||||
int crypt_wipe(const char *device,
|
||||
uint64_t offset,
|
||||
uint64_t sectors,
|
||||
crypt_wipe_type type,
|
||||
int flags);
|
||||
|
||||
#endif /* INTERNAL_H */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,30 +2,37 @@ CRYPTSETUP_1.0 {
|
||||
global:
|
||||
crypt_init;
|
||||
crypt_init_by_name;
|
||||
crypt_init_by_name_and_header;
|
||||
crypt_set_log_callback;
|
||||
crypt_set_confirm_callback;
|
||||
crypt_set_password_callback;
|
||||
crypt_set_timeout;
|
||||
crypt_set_password_retry;
|
||||
crypt_set_iterarion_time;
|
||||
crypt_set_iteration_time;
|
||||
crypt_set_password_verify;
|
||||
crypt_set_uuid;
|
||||
crypt_set_data_device;
|
||||
|
||||
crypt_memory_lock;
|
||||
crypt_format;
|
||||
crypt_load;
|
||||
crypt_repair;
|
||||
crypt_resize;
|
||||
crypt_suspend;
|
||||
crypt_resume_by_passphrase;
|
||||
crypt_resume_by_keyfile;
|
||||
crypt_resume_by_keyfile_offset;
|
||||
crypt_free;
|
||||
|
||||
crypt_keyslot_add_by_passphrase;
|
||||
crypt_keyslot_add_by_keyfile;
|
||||
crypt_keyslot_add_by_keyfile_offset;
|
||||
crypt_keyslot_add_by_volume_key;
|
||||
crypt_keyslot_destroy;
|
||||
crypt_activate_by_passphrase;
|
||||
crypt_activate_by_keyfile;
|
||||
crypt_activate_by_keyfile_offset;
|
||||
crypt_activate_by_volume_key;
|
||||
crypt_deactivate;
|
||||
crypt_volume_key_get;
|
||||
@@ -36,8 +43,10 @@ CRYPTSETUP_1.0 {
|
||||
crypt_get_cipher_mode;
|
||||
crypt_get_uuid;
|
||||
crypt_get_data_offset;
|
||||
crypt_get_iv_offset;
|
||||
crypt_get_volume_key_size;
|
||||
crypt_get_device_name;
|
||||
crypt_get_verity_info;
|
||||
|
||||
crypt_get_type;
|
||||
crypt_get_active_device;
|
||||
@@ -47,6 +56,7 @@ CRYPTSETUP_1.0 {
|
||||
|
||||
crypt_keyslot_max;
|
||||
crypt_keyslot_status;
|
||||
crypt_last_error;
|
||||
crypt_get_error;
|
||||
crypt_get_dir;
|
||||
crypt_set_debug_level;
|
||||
@@ -54,22 +64,6 @@ CRYPTSETUP_1.0 {
|
||||
|
||||
crypt_header_backup;
|
||||
crypt_header_restore;
|
||||
|
||||
crypt_create_device;
|
||||
crypt_update_device;
|
||||
crypt_resize_device;
|
||||
crypt_query_device;
|
||||
crypt_remove_device;
|
||||
crypt_luksFormat;
|
||||
crypt_luksOpen;
|
||||
crypt_luksKillSlot;
|
||||
crypt_luksRemoveKey;
|
||||
crypt_luksAddKey;
|
||||
crypt_luksUUID;
|
||||
crypt_isLuks;
|
||||
crypt_luksDump;
|
||||
|
||||
crypt_put_options;
|
||||
local:
|
||||
*;
|
||||
};
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 2004, Christophe Saout <christophe@saout.de>
|
||||
* Copyright (C) 2004-2007, Clemens Fruhwirth <clemens@endorphin.org>
|
||||
* Copyright (C) 2009-2011, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -16,7 +16,7 @@
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -28,12 +28,12 @@
|
||||
#include <uuid/uuid.h>
|
||||
|
||||
#include "internal.h"
|
||||
#include "luks.h"
|
||||
|
||||
#define DM_UUID_LEN 129
|
||||
#define DM_UUID_PREFIX "CRYPT-"
|
||||
#define DM_UUID_PREFIX_LEN 6
|
||||
#define DM_CRYPT_TARGET "crypt"
|
||||
#define DM_VERITY_TARGET "verity"
|
||||
#define RETRY_COUNT 5
|
||||
|
||||
/* Set if dm-crypt version was probed */
|
||||
@@ -119,11 +119,24 @@ static void _dm_set_crypt_compat(const char *dm_version, unsigned crypt_maj,
|
||||
if (crypt_maj >= 1 && crypt_min >= 8)
|
||||
_dm_crypt_flags |= DM_PLAIN64_SUPPORTED;
|
||||
|
||||
if (crypt_maj >= 1 && crypt_min >= 11)
|
||||
_dm_crypt_flags |= DM_DISCARDS_SUPPORTED;
|
||||
|
||||
/* Repeat test if dm-crypt is not present */
|
||||
if (crypt_maj > 0)
|
||||
_dm_crypt_checked = 1;
|
||||
}
|
||||
|
||||
static void _dm_set_verity_compat(const char *dm_version, unsigned verity_maj,
|
||||
unsigned verity_min, unsigned verity_patch)
|
||||
{
|
||||
if (verity_maj > 0)
|
||||
_dm_crypt_flags |= DM_VERITY_SUPPORTED;
|
||||
|
||||
log_dbg("Detected dm-verity version %i.%i.%i.",
|
||||
verity_maj, verity_min, verity_patch);
|
||||
}
|
||||
|
||||
static int _dm_check_versions(void)
|
||||
{
|
||||
struct dm_task *dmt;
|
||||
@@ -155,6 +168,11 @@ static int _dm_check_versions(void)
|
||||
(unsigned)target->version[0],
|
||||
(unsigned)target->version[1],
|
||||
(unsigned)target->version[2]);
|
||||
} else if (!strcmp(DM_VERITY_TARGET, target->name)) {
|
||||
_dm_set_verity_compat(dm_version,
|
||||
(unsigned)target->version[0],
|
||||
(unsigned)target->version[1],
|
||||
(unsigned)target->version[2]);
|
||||
}
|
||||
target = (struct dm_versions *)((char *) target + target->next);
|
||||
} while (last_target != target);
|
||||
@@ -206,7 +224,7 @@ void dm_exit(void)
|
||||
}
|
||||
|
||||
/* Return path to DM device */
|
||||
char *dm_device_path(int major, int minor)
|
||||
char *dm_device_path(const char *prefix, int major, int minor)
|
||||
{
|
||||
struct dm_task *dmt;
|
||||
const char *name;
|
||||
@@ -222,7 +240,7 @@ char *dm_device_path(int major, int minor)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (snprintf(path, sizeof(path), "/dev/mapper/%s", name) < 0)
|
||||
if (snprintf(path, sizeof(path), "%s%s", prefix ?: "", name) < 0)
|
||||
path[0] = '\0';
|
||||
|
||||
dm_task_destroy(dmt);
|
||||
@@ -238,30 +256,104 @@ static void hex_key(char *hexkey, size_t key_size, const char *key)
|
||||
sprintf(&hexkey[i * 2], "%02x", (unsigned char)key[i]);
|
||||
}
|
||||
|
||||
static char *get_params(const char *device, uint64_t skip, uint64_t offset,
|
||||
const char *cipher, size_t key_size, const char *key)
|
||||
/* http://code.google.com/p/cryptsetup/wiki/DMCrypt */
|
||||
static char *get_dm_crypt_params(struct crypt_dm_active_device *dmd)
|
||||
{
|
||||
char *params;
|
||||
char *hexkey;
|
||||
int r, max_size, null_cipher = 0;
|
||||
char *params, *hexkey;
|
||||
const char *features = "";
|
||||
|
||||
hexkey = crypt_safe_alloc(key_size * 2 + 1);
|
||||
if (!dmd)
|
||||
return NULL;
|
||||
|
||||
if (dmd->flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) {
|
||||
if (dm_flags() & DM_DISCARDS_SUPPORTED) {
|
||||
features = " 1 allow_discards";
|
||||
log_dbg("Discard/TRIM is allowed.");
|
||||
} else
|
||||
log_dbg("Discard/TRIM is not supported by the kernel.");
|
||||
}
|
||||
|
||||
if (!strncmp(dmd->u.crypt.cipher, "cipher_null-", 12))
|
||||
null_cipher = 1;
|
||||
|
||||
hexkey = crypt_safe_alloc(null_cipher ? 2 : (dmd->u.crypt.vk->keylength * 2 + 1));
|
||||
if (!hexkey)
|
||||
return NULL;
|
||||
|
||||
hex_key(hexkey, key_size, key);
|
||||
if (null_cipher)
|
||||
strncpy(hexkey, "-", 2);
|
||||
else
|
||||
hex_key(hexkey, dmd->u.crypt.vk->keylength, dmd->u.crypt.vk->key);
|
||||
|
||||
params = crypt_safe_alloc(strlen(hexkey) + strlen(cipher) + strlen(device) + 64);
|
||||
max_size = strlen(hexkey) + strlen(dmd->u.crypt.cipher) +
|
||||
strlen(dmd->data_device) + strlen(features) + 64;
|
||||
params = crypt_safe_alloc(max_size);
|
||||
if (!params)
|
||||
goto out;
|
||||
|
||||
sprintf(params, "%s %s %" PRIu64 " %s %" PRIu64,
|
||||
cipher, hexkey, skip, device, offset);
|
||||
|
||||
r = snprintf(params, max_size, "%s %s %" PRIu64 " %s %" PRIu64 "%s",
|
||||
dmd->u.crypt.cipher, hexkey, dmd->u.crypt.iv_offset,
|
||||
dmd->data_device, dmd->u.crypt.offset, features);
|
||||
if (r < 0 || r >= max_size) {
|
||||
crypt_safe_free(params);
|
||||
params = NULL;
|
||||
}
|
||||
out:
|
||||
crypt_safe_free(hexkey);
|
||||
return params;
|
||||
}
|
||||
|
||||
/* http://code.google.com/p/cryptsetup/wiki/DMVerity */
|
||||
static char *get_dm_verity_params(struct crypt_params_verity *vp,
|
||||
struct crypt_dm_active_device *dmd)
|
||||
{
|
||||
int max_size, r;
|
||||
char *params = NULL, *hexroot = NULL, *hexsalt = NULL;
|
||||
|
||||
if (!vp || !dmd)
|
||||
return NULL;
|
||||
|
||||
hexroot = crypt_safe_alloc(dmd->u.verity.root_hash_size * 2 + 1);
|
||||
if (!hexroot)
|
||||
goto out;
|
||||
hex_key(hexroot, dmd->u.verity.root_hash_size, dmd->u.verity.root_hash);
|
||||
|
||||
hexsalt = crypt_safe_alloc(vp->salt_size ? vp->salt_size * 2 + 1 : 2);
|
||||
if (!hexsalt)
|
||||
goto out;
|
||||
if (vp->salt_size)
|
||||
hex_key(hexsalt, vp->salt_size, vp->salt);
|
||||
else
|
||||
strncpy(hexsalt, "-", 2);
|
||||
|
||||
max_size = strlen(hexroot) + strlen(hexsalt) +
|
||||
strlen(dmd->data_device) +
|
||||
strlen(dmd->u.verity.hash_device) +
|
||||
strlen(vp->hash_name) + 128;
|
||||
|
||||
params = crypt_safe_alloc(max_size);
|
||||
if (!params)
|
||||
goto out;
|
||||
|
||||
r = snprintf(params, max_size,
|
||||
"%u %s %s %u %u %" PRIu64 " %" PRIu64 " %s %s %s",
|
||||
vp->hash_type, dmd->data_device,
|
||||
dmd->u.verity.hash_device,
|
||||
vp->data_block_size, vp->hash_block_size,
|
||||
vp->data_size, dmd->u.verity.hash_offset,
|
||||
vp->hash_name, hexroot, hexsalt);
|
||||
if (r < 0 || r >= max_size) {
|
||||
crypt_safe_free(params);
|
||||
params = NULL;
|
||||
}
|
||||
out:
|
||||
crypt_safe_free(hexroot);
|
||||
crypt_safe_free(hexsalt);
|
||||
return params;
|
||||
|
||||
}
|
||||
|
||||
/* DM helpers */
|
||||
static int _dm_simple(int task, const char *name, int udev_wait)
|
||||
{
|
||||
@@ -278,6 +370,11 @@ static int _dm_simple(int task, const char *name, int udev_wait)
|
||||
if (name && !dm_task_set_name(dmt, name))
|
||||
goto out;
|
||||
|
||||
#if HAVE_DECL_DM_TASK_RETRY_REMOVE
|
||||
/* Used only in DM_DEVICE_REMOVE */
|
||||
if (name && !dm_task_retry_remove(dmt))
|
||||
goto out;
|
||||
#endif
|
||||
if (udev_wait && !_dm_task_set_cookie(dmt, &cookie, 0))
|
||||
goto out;
|
||||
|
||||
@@ -340,8 +437,6 @@ int dm_remove_device(const char *name, int force, uint64_t size)
|
||||
if (--retries && r) {
|
||||
log_dbg("WARNING: other process locked internal device %s, %s.",
|
||||
name, retries ? "retrying remove" : "giving up");
|
||||
if (force && (crypt_get_debug_level() == CRYPT_LOG_DEBUG))
|
||||
debug_processes_using_device(name);
|
||||
sleep(1);
|
||||
if (force && !error_target) {
|
||||
/* If force flag is set, replace device with error, read-only target.
|
||||
@@ -395,34 +490,20 @@ static void dm_prepare_uuid(const char *name, const char *type, const char *uuid
|
||||
log_err(NULL, _("DM-UUID for device %s was truncated.\n"), name);
|
||||
}
|
||||
|
||||
int dm_create_device(const char *name,
|
||||
const char *device,
|
||||
const char *cipher,
|
||||
const char *type,
|
||||
const char *uuid,
|
||||
uint64_t size,
|
||||
uint64_t skip,
|
||||
uint64_t offset,
|
||||
size_t key_size,
|
||||
const char *key,
|
||||
int read_only,
|
||||
int reload)
|
||||
static int _dm_create_device(const char *name, const char *type,
|
||||
const char *device, uint32_t flags,
|
||||
const char *uuid, uint64_t size,
|
||||
char *params, int reload)
|
||||
{
|
||||
struct dm_task *dmt = NULL;
|
||||
struct dm_info dmi;
|
||||
char *params = NULL;
|
||||
char *error = NULL;
|
||||
char dev_uuid[DM_UUID_LEN] = {0};
|
||||
int r = -EINVAL;
|
||||
uint32_t read_ahead = 0;
|
||||
uint32_t cookie = 0;
|
||||
uint16_t udev_flags = 0;
|
||||
|
||||
params = get_params(device, skip, offset, cipher, key_size, key);
|
||||
if (!params)
|
||||
goto out_no_removal;
|
||||
|
||||
if (type && !strncmp(type, "TEMP", 4))
|
||||
if (flags & CRYPT_ACTIVATE_PRIVATE)
|
||||
udev_flags = CRYPT_TEMP_UDEV_FLAGS;
|
||||
|
||||
/* All devices must have DM_UUID, only resize on old device is exception */
|
||||
@@ -450,9 +531,11 @@ int dm_create_device(const char *name,
|
||||
|
||||
if ((dm_flags() & DM_SECURE_SUPPORTED) && !dm_task_secure_data(dmt))
|
||||
goto out_no_removal;
|
||||
if (read_only && !dm_task_set_ro(dmt))
|
||||
if ((flags & CRYPT_ACTIVATE_READONLY) && !dm_task_set_ro(dmt))
|
||||
goto out_no_removal;
|
||||
if (!dm_task_add_target(dmt, 0, size, DM_CRYPT_TARGET, params))
|
||||
|
||||
if (!dm_task_add_target(dmt, 0, size,
|
||||
!strcmp("VERITY", type) ? DM_VERITY_TARGET : DM_CRYPT_TARGET, params))
|
||||
goto out_no_removal;
|
||||
|
||||
#ifdef DM_READ_AHEAD_MINIMUM_FLAG
|
||||
@@ -488,18 +571,9 @@ out:
|
||||
cookie = 0;
|
||||
}
|
||||
|
||||
if (r < 0 && !reload) {
|
||||
if (get_error())
|
||||
error = strdup(get_error());
|
||||
|
||||
if (r < 0 && !reload)
|
||||
dm_remove_device(name, 0, 0);
|
||||
|
||||
if (error) {
|
||||
set_error(error);
|
||||
free(error);
|
||||
}
|
||||
}
|
||||
|
||||
out_no_removal:
|
||||
if (cookie && _dm_use_udev())
|
||||
(void)_dm_udev_wait(cookie);
|
||||
@@ -513,12 +587,31 @@ out_no_removal:
|
||||
return r;
|
||||
}
|
||||
|
||||
int dm_status_device(const char *name)
|
||||
int dm_create_device(const char *name,
|
||||
const char *type,
|
||||
struct crypt_dm_active_device *dmd,
|
||||
int reload)
|
||||
{
|
||||
char *table_params = NULL;
|
||||
|
||||
if (dmd->target == DM_CRYPT)
|
||||
table_params = get_dm_crypt_params(dmd);
|
||||
else if (dmd->target == DM_VERITY)
|
||||
table_params = get_dm_verity_params(dmd->u.verity.vp, dmd);
|
||||
|
||||
if (!table_params || !type)
|
||||
return -EINVAL;
|
||||
|
||||
return _dm_create_device(name, type, dmd->data_device, dmd->flags,
|
||||
dmd->uuid, dmd->size, table_params, reload);
|
||||
}
|
||||
|
||||
static int dm_status_dmi(const char *name, struct dm_info *dmi,
|
||||
const char *target, char **status_line)
|
||||
{
|
||||
struct dm_task *dmt;
|
||||
struct dm_info dmi;
|
||||
uint64_t start, length;
|
||||
char *target_type, *params;
|
||||
char *target_type, *params = NULL;
|
||||
void *next = NULL;
|
||||
int r = -EINVAL;
|
||||
|
||||
@@ -531,47 +624,299 @@ int dm_status_device(const char *name)
|
||||
if (!dm_task_run(dmt))
|
||||
goto out;
|
||||
|
||||
if (!dm_task_get_info(dmt, &dmi))
|
||||
if (!dm_task_get_info(dmt, dmi))
|
||||
goto out;
|
||||
|
||||
if (!dmi.exists) {
|
||||
if (!dmi->exists) {
|
||||
r = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
next = dm_get_next_target(dmt, next, &start, &length,
|
||||
&target_type, ¶ms);
|
||||
if (!target_type || strcmp(target_type, DM_CRYPT_TARGET) != 0 ||
|
||||
start != 0 || next)
|
||||
r = -EINVAL;
|
||||
else
|
||||
r = (dmi.open_count > 0);
|
||||
|
||||
if (!target_type || start != 0 || next)
|
||||
goto out;
|
||||
|
||||
if (target && strcmp(target_type, target))
|
||||
goto out;
|
||||
|
||||
/* for target == NULL check all supported */
|
||||
if (!target && (strcmp(target_type, DM_CRYPT_TARGET) &&
|
||||
strcmp(target_type, DM_VERITY_TARGET)))
|
||||
goto out;
|
||||
r = 0;
|
||||
out:
|
||||
if (!r && status_line && !(*status_line = strdup(params)))
|
||||
r = -ENOMEM;
|
||||
|
||||
if (dmt)
|
||||
dm_task_destroy(dmt);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int dm_query_device(const char *name,
|
||||
char **device,
|
||||
uint64_t *size,
|
||||
uint64_t *skip,
|
||||
uint64_t *offset,
|
||||
char **cipher,
|
||||
int *key_size,
|
||||
char **key,
|
||||
int *read_only,
|
||||
int *suspended,
|
||||
char **uuid)
|
||||
int dm_status_device(const char *name)
|
||||
{
|
||||
int r;
|
||||
struct dm_info dmi;
|
||||
|
||||
r = dm_status_dmi(name, &dmi, NULL, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return (dmi.open_count > 0);
|
||||
}
|
||||
|
||||
int dm_status_suspended(const char *name)
|
||||
{
|
||||
int r;
|
||||
struct dm_info dmi;
|
||||
|
||||
r = dm_status_dmi(name, &dmi, DM_CRYPT_TARGET, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return dmi.suspended ? 1 : 0;
|
||||
}
|
||||
|
||||
int dm_status_verity_ok(const char *name)
|
||||
{
|
||||
int r;
|
||||
struct dm_info dmi;
|
||||
char *status_line = NULL;
|
||||
|
||||
r = dm_status_dmi(name, &dmi, DM_VERITY_TARGET, &status_line);
|
||||
if (r < 0 || !status_line) {
|
||||
free(status_line);
|
||||
return r;
|
||||
}
|
||||
|
||||
log_dbg("Verity volume %s status is %s.", name, status_line ?: "");
|
||||
r = status_line[0] == 'V' ? 1 : 0;
|
||||
free(status_line);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* FIXME use hex wrapper, user val wrappers for line parsing */
|
||||
static int _dm_query_crypt(uint32_t get_flags,
|
||||
struct dm_info *dmi,
|
||||
char *params,
|
||||
struct crypt_dm_active_device *dmd)
|
||||
{
|
||||
uint64_t val64;
|
||||
char *rcipher, *key_, *rdevice, *endp, buffer[3], *arg;
|
||||
unsigned int i;
|
||||
|
||||
memset(dmd, 0, sizeof(*dmd));
|
||||
dmd->target = DM_CRYPT;
|
||||
|
||||
rcipher = strsep(¶ms, " ");
|
||||
/* cipher */
|
||||
if (get_flags & DM_ACTIVE_CRYPT_CIPHER)
|
||||
dmd->u.crypt.cipher = strdup(rcipher);
|
||||
|
||||
/* skip */
|
||||
key_ = strsep(¶ms, " ");
|
||||
if (!params)
|
||||
return -EINVAL;
|
||||
val64 = strtoull(params, ¶ms, 10);
|
||||
if (*params != ' ')
|
||||
return -EINVAL;
|
||||
params++;
|
||||
|
||||
dmd->u.crypt.iv_offset = val64;
|
||||
|
||||
/* device */
|
||||
rdevice = strsep(¶ms, " ");
|
||||
if (get_flags & DM_ACTIVE_DEVICE)
|
||||
dmd->data_device = crypt_lookup_dev(rdevice);
|
||||
|
||||
/*offset */
|
||||
if (!params)
|
||||
return -EINVAL;
|
||||
val64 = strtoull(params, ¶ms, 10);
|
||||
dmd->u.crypt.offset = val64;
|
||||
|
||||
/* Features section, available since crypt target version 1.11 */
|
||||
if (*params) {
|
||||
if (*params != ' ')
|
||||
return -EINVAL;
|
||||
params++;
|
||||
|
||||
/* Number of arguments */
|
||||
val64 = strtoull(params, ¶ms, 10);
|
||||
if (*params != ' ')
|
||||
return -EINVAL;
|
||||
params++;
|
||||
|
||||
for (i = 0; i < val64; i++) {
|
||||
if (!params)
|
||||
return -EINVAL;
|
||||
arg = strsep(¶ms, " ");
|
||||
if (!strcasecmp(arg, "allow_discards"))
|
||||
dmd->flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS;
|
||||
else /* unknown option */
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* All parameters shold be processed */
|
||||
if (params)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Never allow to return empty key */
|
||||
if ((get_flags & DM_ACTIVE_CRYPT_KEY) && dmi->suspended) {
|
||||
log_dbg("Cannot read volume key while suspended.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (get_flags & DM_ACTIVE_CRYPT_KEYSIZE) {
|
||||
dmd->u.crypt.vk = crypt_alloc_volume_key(strlen(key_) / 2, NULL);
|
||||
if (!dmd->u.crypt.vk)
|
||||
return -ENOMEM;
|
||||
|
||||
if (get_flags & DM_ACTIVE_CRYPT_KEY) {
|
||||
buffer[2] = '\0';
|
||||
for(i = 0; i < dmd->u.crypt.vk->keylength; i++) {
|
||||
memcpy(buffer, &key_[i * 2], 2);
|
||||
dmd->u.crypt.vk->key[i] = strtoul(buffer, &endp, 16);
|
||||
if (endp != &buffer[2]) {
|
||||
crypt_free_volume_key(dmd->u.crypt.vk);
|
||||
dmd->u.crypt.vk = NULL;
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
memset(key_, 0, strlen(key_));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _dm_query_verity(uint32_t get_flags,
|
||||
struct dm_info *dmi,
|
||||
char *params,
|
||||
struct crypt_dm_active_device *dmd)
|
||||
{
|
||||
struct crypt_params_verity *vp = NULL;
|
||||
uint32_t val32;
|
||||
uint64_t val64;
|
||||
ssize_t len;
|
||||
char *str, *str2;
|
||||
|
||||
if (get_flags & DM_ACTIVE_VERITY_PARAMS)
|
||||
vp = dmd->u.verity.vp;
|
||||
|
||||
memset(dmd, 0, sizeof(*dmd));
|
||||
|
||||
dmd->target = DM_VERITY;
|
||||
dmd->u.verity.vp = vp;
|
||||
|
||||
/* version */
|
||||
val32 = strtoul(params, ¶ms, 10);
|
||||
if (*params != ' ')
|
||||
return -EINVAL;
|
||||
if (vp)
|
||||
vp->hash_type = val32;
|
||||
params++;
|
||||
|
||||
/* data device */
|
||||
str = strsep(¶ms, " ");
|
||||
if (!params)
|
||||
return -EINVAL;
|
||||
if (get_flags & DM_ACTIVE_DEVICE)
|
||||
dmd->data_device = crypt_lookup_dev(str);
|
||||
|
||||
/* hash device */
|
||||
str = strsep(¶ms, " ");
|
||||
if (!params)
|
||||
return -EINVAL;
|
||||
if (get_flags & DM_ACTIVE_VERITY_HASH_DEVICE)
|
||||
dmd->u.verity.hash_device = crypt_lookup_dev(str);
|
||||
|
||||
/* data block size*/
|
||||
val32 = strtoul(params, ¶ms, 10);
|
||||
if (*params != ' ')
|
||||
return -EINVAL;
|
||||
if (vp)
|
||||
vp->data_block_size = val32;
|
||||
params++;
|
||||
|
||||
/* hash block size */
|
||||
val32 = strtoul(params, ¶ms, 10);
|
||||
if (*params != ' ')
|
||||
return -EINVAL;
|
||||
if (vp)
|
||||
vp->hash_block_size = val32;
|
||||
params++;
|
||||
|
||||
/* data blocks */
|
||||
val64 = strtoull(params, ¶ms, 10);
|
||||
if (*params != ' ')
|
||||
return -EINVAL;
|
||||
if (vp)
|
||||
vp->data_size = val64;
|
||||
params++;
|
||||
|
||||
/* hash start */
|
||||
val64 = strtoull(params, ¶ms, 10);
|
||||
if (*params != ' ')
|
||||
return -EINVAL;
|
||||
dmd->u.verity.hash_offset = val64;
|
||||
params++;
|
||||
|
||||
/* hash algorithm */
|
||||
str = strsep(¶ms, " ");
|
||||
if (!params)
|
||||
return -EINVAL;
|
||||
if (vp)
|
||||
vp->hash_name = strdup(str);
|
||||
|
||||
/* root digest */
|
||||
str = strsep(¶ms, " ");
|
||||
if (!params)
|
||||
return -EINVAL;
|
||||
len = crypt_hex_to_bytes(str, &str2, 0);
|
||||
if (len < 0)
|
||||
return len;
|
||||
dmd->u.verity.root_hash_size = len;
|
||||
if (get_flags & DM_ACTIVE_VERITY_ROOT_HASH)
|
||||
dmd->u.verity.root_hash = str2;
|
||||
else
|
||||
free(str2);
|
||||
|
||||
/* salt */
|
||||
str = strsep(¶ms, " ");
|
||||
if (params)
|
||||
return -EINVAL;
|
||||
if (vp) {
|
||||
if (!strcmp(str, "-")) {
|
||||
vp->salt_size = 0;
|
||||
vp->salt = NULL;
|
||||
} else {
|
||||
len = crypt_hex_to_bytes(str, &str2, 0);
|
||||
if (len < 0)
|
||||
return len;
|
||||
vp->salt_size = len;
|
||||
vp->salt = str2;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dm_query_device(const char *name, uint32_t get_flags,
|
||||
struct crypt_dm_active_device *dmd)
|
||||
{
|
||||
struct dm_task *dmt;
|
||||
struct dm_info dmi;
|
||||
uint64_t start, length, val64;
|
||||
char *target_type, *params, *rcipher, *key_, *rdevice, *endp, buffer[3];
|
||||
uint64_t start, length;
|
||||
char *target_type, *params;
|
||||
const char *tmp_uuid;
|
||||
void *next = NULL;
|
||||
int i, r = -EINVAL;
|
||||
int r = -EINVAL;
|
||||
|
||||
if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
|
||||
goto out;
|
||||
@@ -594,77 +939,40 @@ int dm_query_device(const char *name,
|
||||
|
||||
next = dm_get_next_target(dmt, next, &start, &length,
|
||||
&target_type, ¶ms);
|
||||
if (!target_type || strcmp(target_type, DM_CRYPT_TARGET) != 0 ||
|
||||
start != 0 || next)
|
||||
|
||||
if (!target_type || start != 0 || next)
|
||||
goto out;
|
||||
|
||||
if (size)
|
||||
*size = length;
|
||||
|
||||
rcipher = strsep(¶ms, " ");
|
||||
/* cipher */
|
||||
if (cipher)
|
||||
*cipher = strdup(rcipher);
|
||||
|
||||
/* skip */
|
||||
key_ = strsep(¶ms, " ");
|
||||
if (!params)
|
||||
goto out;
|
||||
val64 = strtoull(params, ¶ms, 10);
|
||||
if (*params != ' ')
|
||||
goto out;
|
||||
params++;
|
||||
if (skip)
|
||||
*skip = val64;
|
||||
|
||||
/* device */
|
||||
rdevice = strsep(¶ms, " ");
|
||||
if (device)
|
||||
*device = crypt_lookup_dev(rdevice);
|
||||
|
||||
/*offset */
|
||||
if (!params)
|
||||
goto out;
|
||||
val64 = strtoull(params, ¶ms, 10);
|
||||
if (*params)
|
||||
goto out;
|
||||
if (offset)
|
||||
*offset = val64;
|
||||
|
||||
/* key_size */
|
||||
if (key_size)
|
||||
*key_size = strlen(key_) / 2;
|
||||
|
||||
/* key */
|
||||
if (key_size && key) {
|
||||
*key = crypt_safe_alloc(*key_size);
|
||||
if (!*key) {
|
||||
r = -ENOMEM;
|
||||
if (!strcmp(target_type, DM_CRYPT_TARGET)) {
|
||||
r = _dm_query_crypt(get_flags, &dmi, params, dmd);
|
||||
} else if (!strcmp(target_type, DM_VERITY_TARGET)) {
|
||||
r = _dm_query_verity(get_flags, &dmi, params, dmd);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
}
|
||||
r = dm_status_verity_ok(name);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
if (r == 0)
|
||||
dmd->flags |= CRYPT_ACTIVATE_CORRUPTED;
|
||||
r = 0;
|
||||
} else
|
||||
r = -EINVAL;
|
||||
|
||||
buffer[2] = '\0';
|
||||
for(i = 0; i < *key_size; i++) {
|
||||
memcpy(buffer, &key_[i * 2], 2);
|
||||
(*key)[i] = strtoul(buffer, &endp, 16);
|
||||
if (endp != &buffer[2]) {
|
||||
crypt_safe_free(key);
|
||||
*key = NULL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
dmd->size = length;
|
||||
|
||||
if (dmi.read_only)
|
||||
dmd->flags |= CRYPT_ACTIVATE_READONLY;
|
||||
|
||||
tmp_uuid = dm_task_get_uuid(dmt);
|
||||
if (!tmp_uuid)
|
||||
dmd->flags |= CRYPT_ACTIVATE_NO_UUID;
|
||||
else if (get_flags & DM_ACTIVE_UUID) {
|
||||
if (!strncmp(tmp_uuid, DM_UUID_PREFIX, DM_UUID_PREFIX_LEN))
|
||||
dmd->uuid = strdup(tmp_uuid + DM_UUID_PREFIX_LEN);
|
||||
}
|
||||
memset(key_, 0, strlen(key_));
|
||||
|
||||
if (read_only)
|
||||
*read_only = dmi.read_only;
|
||||
|
||||
if (suspended)
|
||||
*suspended = dmi.suspended;
|
||||
|
||||
if (uuid && (tmp_uuid = dm_task_get_uuid(dmt)) &&
|
||||
!strncmp(tmp_uuid, DM_UUID_PREFIX, DM_UUID_PREFIX_LEN))
|
||||
*uuid = strdup(tmp_uuid + DM_UUID_PREFIX_LEN);
|
||||
|
||||
r = (dmi.open_count > 0);
|
||||
out:
|
||||
@@ -764,3 +1072,27 @@ int dm_is_dm_kernel_name(const char *name)
|
||||
{
|
||||
return strncmp(name, "dm-", 3) ? 0 : 1;
|
||||
}
|
||||
|
||||
int dm_check_segment(const char *name, uint64_t offset, uint64_t size)
|
||||
{
|
||||
struct crypt_dm_active_device dmd;
|
||||
int r;
|
||||
|
||||
log_dbg("Checking segments for device %s.", name);
|
||||
|
||||
r = dm_query_device(name, 0, &dmd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (offset >= (dmd.u.crypt.offset + dmd.size) ||
|
||||
(offset + size) <= dmd.u.crypt.offset)
|
||||
r = 0;
|
||||
else
|
||||
r = -EBUSY;
|
||||
|
||||
log_dbg("seg: %" PRIu64 " - %" PRIu64 ", new %" PRIu64 " - %" PRIu64 "%s",
|
||||
dmd.u.crypt.offset, dmd.u.crypt.offset + dmd.size, offset, offset + size,
|
||||
r ? " (overlapping)" : " (ok)");
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* loop-AES compatible volume handling
|
||||
*
|
||||
* Copyright (C) 2011, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2011-2012, Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
@@ -22,8 +22,9 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "crypto_backend.h"
|
||||
#include "libcryptsetup.h"
|
||||
#include "loopaes.h"
|
||||
#include "internal.h"
|
||||
|
||||
static const char *get_hash(unsigned int key_size)
|
||||
{
|
||||
@@ -185,22 +186,28 @@ int LOOPAES_activate(struct crypt_device *cd,
|
||||
const char *base_cipher,
|
||||
unsigned int keys_count,
|
||||
struct volume_key *vk,
|
||||
uint64_t offset,
|
||||
uint64_t skip,
|
||||
uint32_t flags)
|
||||
{
|
||||
uint64_t size;
|
||||
char *cipher = NULL;
|
||||
uint32_t req_flags;
|
||||
char *cipher;
|
||||
const char *device;
|
||||
int read_only, r;
|
||||
int r;
|
||||
struct crypt_dm_active_device dmd = {
|
||||
.target = DM_CRYPT,
|
||||
.uuid = crypt_get_uuid(cd),
|
||||
.size = 0,
|
||||
.flags = flags,
|
||||
.data_device = crypt_get_device_name(cd),
|
||||
.u.crypt = {
|
||||
.cipher = NULL,
|
||||
.vk = vk,
|
||||
.offset = crypt_get_data_offset(cd),
|
||||
.iv_offset = crypt_get_iv_offset(cd),
|
||||
}
|
||||
};
|
||||
|
||||
size = 0;
|
||||
/* Initial IV (skip) is always the same as offset */
|
||||
device = crypt_get_device_name(cd);
|
||||
read_only = flags & CRYPT_ACTIVATE_READONLY;
|
||||
|
||||
r = device_check_and_adjust(cd, device, 1, &size, &offset, &read_only);
|
||||
r = device_check_and_adjust(cd, dmd.data_device, DEV_EXCL,
|
||||
&dmd.size, &dmd.u.crypt.offset, &flags);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
@@ -214,12 +221,11 @@ int LOOPAES_activate(struct crypt_device *cd,
|
||||
if (r < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
log_dbg("Trying to activate loop-AES device %s using cipher %s.", name, cipher);
|
||||
r = dm_create_device(name, device,
|
||||
cipher, CRYPT_LOOPAES,
|
||||
crypt_get_uuid(cd),
|
||||
size, skip, offset, vk->keylength, vk->key,
|
||||
read_only, 0);
|
||||
dmd.u.crypt.cipher = cipher;
|
||||
log_dbg("Trying to activate loop-AES device %s using cipher %s.",
|
||||
name, dmd.u.crypt.cipher);
|
||||
|
||||
r = dm_create_device(name, CRYPT_LOOPAES, &dmd, 0);
|
||||
|
||||
if (!r && !(dm_flags() & req_flags)) {
|
||||
log_err(cd, _("Kernel doesn't support loop-AES compatible mapping.\n"));
|
||||
|
||||
@@ -1,9 +1,31 @@
|
||||
/*
|
||||
* loop-AES compatible volume handling
|
||||
*
|
||||
* Copyright (C) 2011-2012, Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef _LOOPAES_H
|
||||
#define _LOOPAES_H
|
||||
|
||||
#include <unistd.h>
|
||||
#include "config.h"
|
||||
|
||||
struct crypt_device;
|
||||
struct volume_key;
|
||||
|
||||
#define LOOPAES_KEYS_MAX 65
|
||||
|
||||
int LOOPAES_parse_keyfile(struct crypt_device *cd,
|
||||
@@ -18,7 +40,5 @@ int LOOPAES_activate(struct crypt_device *cd,
|
||||
const char *base_cipher,
|
||||
unsigned int keys_count,
|
||||
struct volume_key *vk,
|
||||
uint64_t offset,
|
||||
uint64_t skip,
|
||||
uint32_t flags);
|
||||
#endif
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* AFsplitter - Anti forensic information splitter
|
||||
*
|
||||
* Copyright (C) 2004, Clemens Fruhwirth <clemens@endorphin.org>
|
||||
* Copyright (C) 2009-2011, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* AFsplitter diffuses information over a large stripe of data,
|
||||
* therefor supporting secure data destruction.
|
||||
@@ -18,7 +18,7 @@
|
||||
*
|
||||
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
@@ -26,7 +26,6 @@
|
||||
#include <string.h>
|
||||
#include <netinet/in.h>
|
||||
#include <errno.h>
|
||||
#include "crypto_backend.h"
|
||||
#include "internal.h"
|
||||
#include "af.h"
|
||||
|
||||
|
||||
@@ -1,10 +1,27 @@
|
||||
#ifndef INCLUDED_CRYPTSETUP_LUKS_AF_H
|
||||
#define INCLUDED_CRYPTSETUP_LUKS_AF_H
|
||||
|
||||
/*
|
||||
* AFsplitter - Anti forensic information splitter
|
||||
* Copyright 2004, Clemens Fruhwirth <clemens@endorphin.org>
|
||||
*
|
||||
* Copyright (C) 2004, Clemens Fruhwirth <clemens@endorphin.org>
|
||||
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* AFsplitter diffuses information over a large stripe of data,
|
||||
* therefor supporting secure data destruction.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* 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 Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
#ifndef INCLUDED_CRYPTSETUP_LUKS_AF_H
|
||||
#define INCLUDED_CRYPTSETUP_LUKS_AF_H
|
||||
|
||||
/*
|
||||
* AF_split operates on src and produces information split data in
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* LUKS - Linux Unified Key Setup
|
||||
*
|
||||
* Copyright (C) 2004-2006, Clemens Fruhwirth <clemens@endorphin.org>
|
||||
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -14,7 +15,7 @@
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
@@ -51,13 +52,28 @@ static int devfd=-1;
|
||||
|
||||
static int setup_mapping(const char *cipher, const char *name,
|
||||
const char *device,
|
||||
const char *key, size_t keyLength,
|
||||
struct volume_key *vk,
|
||||
unsigned int sector, size_t srcLength,
|
||||
int mode, struct crypt_device *ctx)
|
||||
{
|
||||
int device_sector_size = sector_size_for_device(device);
|
||||
uint64_t size;
|
||||
struct crypt_dm_active_device dmd = {
|
||||
.target = DM_CRYPT,
|
||||
.uuid = NULL,
|
||||
.size = 0,
|
||||
.flags = 0,
|
||||
.data_device = device,
|
||||
.u.crypt = {
|
||||
.cipher = cipher,
|
||||
.vk = vk,
|
||||
.offset = sector,
|
||||
.iv_offset = 0,
|
||||
}
|
||||
};
|
||||
|
||||
dmd.flags = CRYPT_ACTIVATE_PRIVATE;
|
||||
if (mode == O_RDONLY)
|
||||
dmd.flags |= CRYPT_ACTIVATE_READONLY;
|
||||
/*
|
||||
* we need to round this to nearest multiple of the underlying
|
||||
* device's sector size, otherwise the mapping will be refused.
|
||||
@@ -66,11 +82,11 @@ static int setup_mapping(const char *cipher, const char *name,
|
||||
log_err(ctx, _("Unable to obtain sector size for %s"), device);
|
||||
return -EINVAL;
|
||||
}
|
||||
size = round_up_modulo(srcLength,device_sector_size)/SECTOR_SIZE;
|
||||
cleaner_size = size;
|
||||
|
||||
return dm_create_device(name, device, cipher, "TEMP", NULL, size, 0, sector,
|
||||
keyLength, key, (mode == O_RDONLY), 0);
|
||||
dmd.size = round_up_modulo(srcLength,device_sector_size)/SECTOR_SIZE;
|
||||
cleaner_size = dmd.size;
|
||||
|
||||
return dm_create_device(name, "TEMP", &dmd, 0);
|
||||
}
|
||||
|
||||
static void sigint_handler(int sig __attribute__((unused)))
|
||||
@@ -88,29 +104,10 @@ static void sigint_handler(int sig __attribute__((unused)))
|
||||
static const char *_error_hint(char *cipherMode, size_t keyLength)
|
||||
{
|
||||
const char *hint= "";
|
||||
#ifdef __linux__
|
||||
char c, tmp[4] = {0};
|
||||
struct utsname uts;
|
||||
int i = 0, kernel_minor;
|
||||
|
||||
/* Nothing to suggest here */
|
||||
if (uname(&uts) || strncmp(uts.release, "2.6.", 4))
|
||||
return hint;
|
||||
|
||||
/* Get kernel minor without suffixes */
|
||||
while (i < 3 && (c = uts.release[i + 4]))
|
||||
tmp[i++] = isdigit(c) ? c : '\0';
|
||||
kernel_minor = atoi(tmp);
|
||||
|
||||
if (!strncmp(cipherMode, "xts", 3) && (keyLength != 256 && keyLength != 512))
|
||||
hint = _("Key size in XTS mode must be 256 or 512 bits.\n");
|
||||
else if (!strncmp(cipherMode, "xts", 3) && kernel_minor < 24)
|
||||
hint = _("Block mode XTS is available since kernel 2.6.24.\n");
|
||||
if (!strncmp(cipherMode, "lrw", 3) && (keyLength != 256 && keyLength != 512))
|
||||
hint = _("Key size in LRW mode must be 256 or 512 bits.\n");
|
||||
else if (!strncmp(cipherMode, "lrw", 3) && kernel_minor < 20)
|
||||
hint = _("Block mode LRW is available since kernel 2.6.20.\n");
|
||||
#endif
|
||||
|
||||
return hint;
|
||||
}
|
||||
|
||||
@@ -118,7 +115,7 @@ static const char *_error_hint(char *cipherMode, size_t keyLength)
|
||||
handler and global vars for cleaning */
|
||||
static int LUKS_endec_template(char *src, size_t srcLength,
|
||||
struct luks_phdr *hdr,
|
||||
char *key, size_t keyLength,
|
||||
struct volume_key *vk,
|
||||
const char *device,
|
||||
unsigned int sector,
|
||||
ssize_t (*func)(int, void *, size_t),
|
||||
@@ -146,12 +143,12 @@ static int LUKS_endec_template(char *src, size_t srcLength,
|
||||
cleaner_name = name;
|
||||
|
||||
r = setup_mapping(dmCipherSpec, name, device,
|
||||
key, keyLength, sector, srcLength, mode, ctx);
|
||||
vk, sector, srcLength, mode, ctx);
|
||||
if(r < 0) {
|
||||
log_err(ctx, _("Failed to setup dm-crypt key mapping for device %s.\n"
|
||||
"Check that kernel supports %s cipher (check syslog for more info).\n%s"),
|
||||
device, dmCipherSpec,
|
||||
_error_hint(hdr->cipherMode, keyLength * 8));
|
||||
_error_hint(hdr->cipherMode, vk->keylength * 8));
|
||||
r = -EIO;
|
||||
goto out1;
|
||||
}
|
||||
@@ -188,22 +185,22 @@ static int LUKS_endec_template(char *src, size_t srcLength,
|
||||
|
||||
int LUKS_encrypt_to_storage(char *src, size_t srcLength,
|
||||
struct luks_phdr *hdr,
|
||||
char *key, size_t keyLength,
|
||||
struct volume_key *vk,
|
||||
const char *device,
|
||||
unsigned int sector,
|
||||
struct crypt_device *ctx)
|
||||
{
|
||||
return LUKS_endec_template(src,srcLength,hdr,key,keyLength, device,
|
||||
return LUKS_endec_template(src,srcLength,hdr,vk, device,
|
||||
sector, write_blockwise, O_RDWR, ctx);
|
||||
}
|
||||
|
||||
int LUKS_decrypt_from_storage(char *dst, size_t dstLength,
|
||||
struct luks_phdr *hdr,
|
||||
char *key, size_t keyLength,
|
||||
struct volume_key *vk,
|
||||
const char *device,
|
||||
unsigned int sector,
|
||||
struct crypt_device *ctx)
|
||||
{
|
||||
return LUKS_endec_template(dst,dstLength,hdr,key,keyLength, device,
|
||||
return LUKS_endec_template(dst,dstLength,hdr,vk, device,
|
||||
sector, read_blockwise, O_RDONLY, ctx);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* LUKS - Linux Unified Key Setup
|
||||
*
|
||||
* Copyright (C) 2004-2006, Clemens Fruhwirth <clemens@endorphin.org>
|
||||
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -14,13 +15,11 @@
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/fs.h>
|
||||
#include <netinet/in.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
@@ -29,6 +28,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <uuid/uuid.h>
|
||||
|
||||
#include "luks.h"
|
||||
@@ -46,6 +46,87 @@ static inline int round_up_modulo(int x, int m) {
|
||||
return div_round_up(x, m) * m;
|
||||
}
|
||||
|
||||
/* Get size of struct luks_phrd with all keyslots material space */
|
||||
static uint64_t LUKS_device_sectors(size_t keyLen)
|
||||
{
|
||||
uint64_t keyslot_sectors, sector;
|
||||
int i;
|
||||
|
||||
keyslot_sectors = div_round_up(keyLen * LUKS_STRIPES, SECTOR_SIZE);
|
||||
sector = round_up_modulo(LUKS_PHDR_SIZE, LUKS_ALIGN_KEYSLOTS / SECTOR_SIZE);
|
||||
|
||||
for (i = 0; i < LUKS_NUMKEYS; i++) {
|
||||
sector = round_up_modulo(sector, LUKS_ALIGN_KEYSLOTS / SECTOR_SIZE);
|
||||
sector += keyslot_sectors;
|
||||
}
|
||||
|
||||
return sector;
|
||||
}
|
||||
|
||||
static int LUKS_check_device_size(struct crypt_device *ctx, const char *device,
|
||||
size_t keyLength)
|
||||
{
|
||||
uint64_t dev_sectors, hdr_sectors;
|
||||
|
||||
if (!keyLength)
|
||||
return -EINVAL;
|
||||
|
||||
if(device_size(device, &dev_sectors)) {
|
||||
log_dbg("Cannot get device size for device %s.", device);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
dev_sectors >>= SECTOR_SHIFT;
|
||||
hdr_sectors = LUKS_device_sectors(keyLength);
|
||||
log_dbg("Key length %u, device size %" PRIu64 " sectors, header size %"
|
||||
PRIu64 " sectors.",keyLength, dev_sectors, hdr_sectors);
|
||||
|
||||
if (hdr_sectors > dev_sectors) {
|
||||
log_err(ctx, _("Device %s is too small.\n"), device);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check keyslot to prevent access outside of header and keyslot area */
|
||||
static int LUKS_check_keyslot_size(const struct luks_phdr *phdr, unsigned int keyIndex)
|
||||
{
|
||||
uint32_t secs_per_stripes;
|
||||
|
||||
/* First sectors is the header itself */
|
||||
if (phdr->keyblock[keyIndex].keyMaterialOffset * SECTOR_SIZE < sizeof(*phdr)) {
|
||||
log_dbg("Invalid offset %u in keyslot %u.",
|
||||
phdr->keyblock[keyIndex].keyMaterialOffset, keyIndex);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Ignore following check for detached header where offset can be zero. */
|
||||
if (phdr->payloadOffset == 0)
|
||||
return 0;
|
||||
|
||||
if (phdr->payloadOffset <= phdr->keyblock[keyIndex].keyMaterialOffset) {
|
||||
log_dbg("Invalid offset %u in keyslot %u (beyond data area offset %u).",
|
||||
phdr->keyblock[keyIndex].keyMaterialOffset, keyIndex,
|
||||
phdr->payloadOffset);
|
||||
return 1;
|
||||
}
|
||||
|
||||
secs_per_stripes = div_round_up(phdr->keyBytes * phdr->keyblock[keyIndex].stripes, SECTOR_SIZE);
|
||||
|
||||
if (phdr->payloadOffset < (phdr->keyblock[keyIndex].keyMaterialOffset + secs_per_stripes)) {
|
||||
log_dbg("Invalid keyslot size %u (offset %u, stripes %u) in "
|
||||
"keyslot %u (beyond data area offset %u).",
|
||||
secs_per_stripes,
|
||||
phdr->keyblock[keyIndex].keyMaterialOffset,
|
||||
phdr->keyblock[keyIndex].stripes,
|
||||
keyIndex, phdr->payloadOffset);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *dbg_slot_state(crypt_keyslot_info ki)
|
||||
{
|
||||
switch(ki) {
|
||||
@@ -77,11 +158,11 @@ int LUKS_hdr_backup(
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
r = LUKS_read_phdr(device, hdr, 1, ctx);
|
||||
r = LUKS_read_phdr(device, hdr, 1, 0, ctx);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
buffer_size = hdr->payloadOffset << SECTOR_SHIFT;
|
||||
buffer_size = LUKS_device_sectors(hdr->keyBytes) << SECTOR_SHIFT;
|
||||
buffer = crypt_safe_alloc(buffer_size);
|
||||
if (!buffer || buffer_size < LUKS_ALIGN_KEYSLOTS) {
|
||||
r = -ENOMEM;
|
||||
@@ -134,7 +215,7 @@ int LUKS_hdr_restore(
|
||||
struct crypt_device *ctx)
|
||||
{
|
||||
int r = 0, devfd = -1, diff_uuid = 0;
|
||||
ssize_t buffer_size;
|
||||
ssize_t buffer_size = 0;
|
||||
char *buffer = NULL, msg[200];
|
||||
struct stat st;
|
||||
struct luks_phdr hdr_file;
|
||||
@@ -145,10 +226,11 @@ int LUKS_hdr_restore(
|
||||
}
|
||||
|
||||
r = LUKS_read_phdr_backup(backup_file, device, &hdr_file, 0, ctx);
|
||||
buffer_size = hdr_file.payloadOffset << SECTOR_SHIFT;
|
||||
if (!r)
|
||||
buffer_size = LUKS_device_sectors(hdr_file.keyBytes) << SECTOR_SHIFT;
|
||||
|
||||
if (r || buffer_size < LUKS_ALIGN_KEYSLOTS) {
|
||||
log_err(ctx, _("Backup file do not contain valid LUKS header.\n"));
|
||||
log_err(ctx, _("Backup file doesn't contain valid LUKS header.\n"));
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
@@ -173,7 +255,7 @@ int LUKS_hdr_restore(
|
||||
}
|
||||
close(devfd);
|
||||
|
||||
r = LUKS_read_phdr(device, hdr, 0, ctx);
|
||||
r = LUKS_read_phdr(device, hdr, 0, 0, ctx);
|
||||
if (r == 0) {
|
||||
log_dbg("Device %s already contains LUKS header, checking UUID and offset.", device);
|
||||
if(hdr->payloadOffset != hdr_file.payloadOffset ||
|
||||
@@ -216,7 +298,7 @@ int LUKS_hdr_restore(
|
||||
close(devfd);
|
||||
|
||||
/* Be sure to reload new data */
|
||||
r = LUKS_read_phdr(device, hdr, 0, ctx);
|
||||
r = LUKS_read_phdr(device, hdr, 1, 0, ctx);
|
||||
out:
|
||||
if (devfd != -1)
|
||||
close(devfd);
|
||||
@@ -224,9 +306,96 @@ out:
|
||||
return r;
|
||||
}
|
||||
|
||||
/* This routine should do some just basic recovery for known problems. */
|
||||
static int _keyslot_repair(const char *device, struct luks_phdr *phdr, struct crypt_device *ctx)
|
||||
{
|
||||
struct luks_phdr temp_phdr;
|
||||
const unsigned char *sector = (const unsigned char*)phdr;
|
||||
struct volume_key *vk;
|
||||
uint64_t PBKDF2_per_sec = 1;
|
||||
int i, bad, r, need_write = 0;
|
||||
|
||||
if (phdr->keyBytes != 16 && phdr->keyBytes != 32) {
|
||||
log_err(ctx, _("Non standard key size, manual repair required.\n"));
|
||||
return -EINVAL;
|
||||
}
|
||||
/* cryptsetup 1.0 did not align to 4k, cannot repair this one */
|
||||
if (phdr->keyblock[0].keyMaterialOffset < (LUKS_ALIGN_KEYSLOTS / SECTOR_SIZE)) {
|
||||
log_err(ctx, _("Non standard keyslots alignment, manual repair required.\n"));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
vk = crypt_alloc_volume_key(phdr->keyBytes, NULL);
|
||||
|
||||
log_verbose(ctx, _("Repairing keyslots.\n"));
|
||||
|
||||
log_dbg("Generating second header with the same parameters for check.");
|
||||
/* cipherName, cipherMode, hashSpec, uuid are already null terminated */
|
||||
/* payloadOffset - cannot check */
|
||||
r = LUKS_generate_phdr(&temp_phdr, vk, phdr->cipherName, phdr->cipherMode,
|
||||
phdr->hashSpec,phdr->uuid, LUKS_STRIPES,
|
||||
phdr->payloadOffset, 0,
|
||||
1, &PBKDF2_per_sec,
|
||||
"/dev/null", ctx);
|
||||
if (r < 0) {
|
||||
log_err(ctx, _("Repair failed."));
|
||||
goto out;
|
||||
}
|
||||
|
||||
for(i = 0; i < LUKS_NUMKEYS; ++i) {
|
||||
if (phdr->keyblock[i].active == LUKS_KEY_ENABLED) {
|
||||
log_dbg("Skipping repair for active keyslot %i.", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
bad = 0;
|
||||
if (phdr->keyblock[i].keyMaterialOffset != temp_phdr.keyblock[i].keyMaterialOffset) {
|
||||
log_err(ctx, _("Keyslot %i: offset repaired (%u -> %u).\n"), i,
|
||||
(unsigned)phdr->keyblock[i].keyMaterialOffset,
|
||||
(unsigned)temp_phdr.keyblock[i].keyMaterialOffset);
|
||||
phdr->keyblock[i].keyMaterialOffset = temp_phdr.keyblock[i].keyMaterialOffset;
|
||||
bad = 1;
|
||||
}
|
||||
|
||||
if (phdr->keyblock[i].stripes != temp_phdr.keyblock[i].stripes) {
|
||||
log_err(ctx, _("Keyslot %i: stripes repaired (%u -> %u).\n"), i,
|
||||
(unsigned)phdr->keyblock[i].stripes,
|
||||
(unsigned)temp_phdr.keyblock[i].stripes);
|
||||
phdr->keyblock[i].stripes = temp_phdr.keyblock[i].stripes;
|
||||
bad = 1;
|
||||
}
|
||||
|
||||
/* Known case - MSDOS partition table signature */
|
||||
if (i == 6 && sector[0x1fe] == 0x55 && sector[0x1ff] == 0xaa) {
|
||||
log_err(ctx, _("Keyslot %i: bogus partition signature.\n"), i);
|
||||
bad = 1;
|
||||
}
|
||||
|
||||
if(bad) {
|
||||
log_err(ctx, _("Keyslot %i: salt wiped.\n"), i);
|
||||
phdr->keyblock[i].active = LUKS_KEY_DISABLED;
|
||||
memset(&phdr->keyblock[i].passwordSalt, 0x00, LUKS_SALTSIZE);
|
||||
phdr->keyblock[i].passwordIterations = 0;
|
||||
}
|
||||
|
||||
if (bad)
|
||||
need_write = 1;
|
||||
}
|
||||
|
||||
if (need_write) {
|
||||
log_verbose(ctx, _("Writing LUKS header to disk.\n"));
|
||||
r = LUKS_write_phdr(device, phdr, ctx);
|
||||
}
|
||||
out:
|
||||
crypt_free_volume_key(vk);
|
||||
memset(&temp_phdr, 0, sizeof(temp_phdr));
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _check_and_convert_hdr(const char *device,
|
||||
struct luks_phdr *hdr,
|
||||
int require_luks_device,
|
||||
int repair,
|
||||
struct crypt_device *ctx)
|
||||
{
|
||||
int r = 0;
|
||||
@@ -237,28 +406,46 @@ static int _check_and_convert_hdr(const char *device,
|
||||
log_dbg("LUKS header not detected.");
|
||||
if (require_luks_device)
|
||||
log_err(ctx, _("Device %s is not a valid LUKS device.\n"), device);
|
||||
else
|
||||
set_error(_("Device %s is not a valid LUKS device."), device);
|
||||
r = -EINVAL;
|
||||
return -EINVAL;
|
||||
} else if((hdr->version = ntohs(hdr->version)) != 1) { /* Convert every uint16/32_t item from network byte order */
|
||||
log_err(ctx, _("Unsupported LUKS version %d.\n"), hdr->version);
|
||||
r = -EINVAL;
|
||||
} else if (PBKDF2_HMAC_ready(hdr->hashSpec) < 0) {
|
||||
log_err(ctx, _("Requested LUKS hash %s is not supported.\n"), hdr->hashSpec);
|
||||
r = -EINVAL;
|
||||
} else {
|
||||
hdr->payloadOffset = ntohl(hdr->payloadOffset);
|
||||
hdr->keyBytes = ntohl(hdr->keyBytes);
|
||||
hdr->mkDigestIterations = ntohl(hdr->mkDigestIterations);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for(i = 0; i < LUKS_NUMKEYS; ++i) {
|
||||
hdr->keyblock[i].active = ntohl(hdr->keyblock[i].active);
|
||||
hdr->keyblock[i].passwordIterations = ntohl(hdr->keyblock[i].passwordIterations);
|
||||
hdr->keyblock[i].keyMaterialOffset = ntohl(hdr->keyblock[i].keyMaterialOffset);
|
||||
hdr->keyblock[i].stripes = ntohl(hdr->keyblock[i].stripes);
|
||||
hdr->hashSpec[LUKS_HASHSPEC_L - 1] = '\0';
|
||||
if (PBKDF2_HMAC_ready(hdr->hashSpec) < 0) {
|
||||
log_err(ctx, _("Requested LUKS hash %s is not supported.\n"), hdr->hashSpec);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Header detected */
|
||||
hdr->payloadOffset = ntohl(hdr->payloadOffset);
|
||||
hdr->keyBytes = ntohl(hdr->keyBytes);
|
||||
hdr->mkDigestIterations = ntohl(hdr->mkDigestIterations);
|
||||
|
||||
for(i = 0; i < LUKS_NUMKEYS; ++i) {
|
||||
hdr->keyblock[i].active = ntohl(hdr->keyblock[i].active);
|
||||
hdr->keyblock[i].passwordIterations = ntohl(hdr->keyblock[i].passwordIterations);
|
||||
hdr->keyblock[i].keyMaterialOffset = ntohl(hdr->keyblock[i].keyMaterialOffset);
|
||||
hdr->keyblock[i].stripes = ntohl(hdr->keyblock[i].stripes);
|
||||
if (LUKS_check_keyslot_size(hdr, i)) {
|
||||
log_err(ctx, _("LUKS keyslot %u is invalid.\n"), i);
|
||||
r = -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Avoid unterminated strings */
|
||||
hdr->cipherName[LUKS_CIPHERNAME_L - 1] = '\0';
|
||||
hdr->cipherMode[LUKS_CIPHERMODE_L - 1] = '\0';
|
||||
hdr->uuid[UUID_STRING_L - 1] = '\0';
|
||||
|
||||
if (repair) {
|
||||
if (r == -EINVAL)
|
||||
r = _keyslot_repair(device, hdr, ctx);
|
||||
else
|
||||
log_verbose(ctx, _("No known problems detected for LUKS header.\n"));
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -298,7 +485,8 @@ int LUKS_read_phdr_backup(const char *backup_file,
|
||||
r = -EIO;
|
||||
else {
|
||||
LUKS_fix_header_compatible(hdr);
|
||||
r = _check_and_convert_hdr(backup_file, hdr, require_luks_device, ctx);
|
||||
r = _check_and_convert_hdr(backup_file, hdr,
|
||||
require_luks_device, 0, ctx);
|
||||
}
|
||||
|
||||
close(devfd);
|
||||
@@ -308,11 +496,14 @@ int LUKS_read_phdr_backup(const char *backup_file,
|
||||
int LUKS_read_phdr(const char *device,
|
||||
struct luks_phdr *hdr,
|
||||
int require_luks_device,
|
||||
int repair,
|
||||
struct crypt_device *ctx)
|
||||
{
|
||||
ssize_t hdr_size = sizeof(struct luks_phdr);
|
||||
int devfd = 0, r = 0;
|
||||
uint64_t size;
|
||||
|
||||
if (repair && !require_luks_device)
|
||||
return -EINVAL;
|
||||
|
||||
log_dbg("Reading LUKS header of size %d from device %s",
|
||||
hdr_size, device);
|
||||
@@ -326,17 +517,13 @@ int LUKS_read_phdr(const char *device,
|
||||
if (read_blockwise(devfd, hdr, hdr_size) < hdr_size)
|
||||
r = -EIO;
|
||||
else
|
||||
r = _check_and_convert_hdr(device, hdr, require_luks_device, ctx);
|
||||
r = _check_and_convert_hdr(device, hdr, require_luks_device,
|
||||
repair, ctx);
|
||||
|
||||
if (!r)
|
||||
r = LUKS_check_device_size(ctx, device, hdr->keyBytes);
|
||||
|
||||
#ifdef BLKGETSIZE64
|
||||
if (r == 0 && (ioctl(devfd, BLKGETSIZE64, &size) < 0 ||
|
||||
size < (uint64_t)hdr->payloadOffset)) {
|
||||
log_err(ctx, _("LUKS header detected but device %s is too small.\n"), device);
|
||||
r = -EINVAL;
|
||||
}
|
||||
#endif
|
||||
close(devfd);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -353,6 +540,10 @@ int LUKS_write_phdr(const char *device,
|
||||
log_dbg("Updating LUKS header of size %d on device %s",
|
||||
sizeof(struct luks_phdr), device);
|
||||
|
||||
r = LUKS_check_device_size(ctx, device, hdr->keyBytes);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
devfd = open(device,O_RDWR | O_DIRECT | O_SYNC);
|
||||
if(-1 == devfd) {
|
||||
log_err(ctx, _("Cannot open device %s.\n"), device);
|
||||
@@ -381,7 +572,7 @@ int LUKS_write_phdr(const char *device,
|
||||
|
||||
/* Re-read header from disk to be sure that in-memory and on-disk data are the same. */
|
||||
if (!r) {
|
||||
r = LUKS_read_phdr(device, hdr, 1, ctx);
|
||||
r = LUKS_read_phdr(device, hdr, 1, 0, ctx);
|
||||
if (r)
|
||||
log_err(ctx, _("Error re-reading LUKS header after update on device %s.\n"), device);
|
||||
}
|
||||
@@ -412,6 +603,7 @@ int LUKS_generate_phdr(struct luks_phdr *header,
|
||||
unsigned int alignOffset,
|
||||
uint32_t iteration_time_ms,
|
||||
uint64_t *PBKDF2_per_sec,
|
||||
const char *metadata_device,
|
||||
struct crypt_device *ctx)
|
||||
{
|
||||
unsigned int i=0;
|
||||
@@ -421,7 +613,8 @@ int LUKS_generate_phdr(struct luks_phdr *header,
|
||||
int currentSector;
|
||||
char luksMagic[] = LUKS_MAGIC;
|
||||
|
||||
if (alignPayload == 0)
|
||||
/* For separate metadata device allow zero alignment */
|
||||
if (alignPayload == 0 && !metadata_device)
|
||||
alignPayload = DEFAULT_DISK_ALIGNMENT / SECTOR_SIZE;
|
||||
|
||||
if (PBKDF2_HMAC_ready(hashSpec) < 0) {
|
||||
@@ -453,7 +646,7 @@ int LUKS_generate_phdr(struct luks_phdr *header,
|
||||
header->version, header->hashSpec ,header->cipherName, header->cipherMode,
|
||||
header->keyBytes);
|
||||
|
||||
r = crypt_random_get(ctx, header->mkDigestSalt, LUKS_SALTSIZE, CRYPT_RND_NORMAL);
|
||||
r = crypt_random_get(ctx, header->mkDigestSalt, LUKS_SALTSIZE, CRYPT_RND_SALT);
|
||||
if(r < 0) {
|
||||
log_err(ctx, _("Cannot create LUKS header: reading random salt failed.\n"));
|
||||
return r;
|
||||
@@ -485,10 +678,15 @@ int LUKS_generate_phdr(struct luks_phdr *header,
|
||||
currentSector = round_up_modulo(currentSector + blocksPerStripeSet,
|
||||
LUKS_ALIGN_KEYSLOTS / SECTOR_SIZE);
|
||||
}
|
||||
currentSector = round_up_modulo(currentSector, alignPayload);
|
||||
|
||||
/* alignOffset - offset from natural device alignment provided by topology info */
|
||||
header->payloadOffset = currentSector + alignOffset;
|
||||
if (metadata_device) {
|
||||
/* for separate metadata device use alignPayload directly */
|
||||
header->payloadOffset = alignPayload;
|
||||
} else {
|
||||
/* alignOffset - offset from natural device alignment provided by topology info */
|
||||
currentSector = round_up_modulo(currentSector, alignPayload);
|
||||
header->payloadOffset = currentSector + alignOffset;
|
||||
}
|
||||
|
||||
uuid_unparse(partitionUuid, header->uuid);
|
||||
|
||||
@@ -525,7 +723,7 @@ int LUKS_set_key(const char *device, unsigned int keyIndex,
|
||||
uint64_t *PBKDF2_per_sec,
|
||||
struct crypt_device *ctx)
|
||||
{
|
||||
char derivedKey[hdr->keyBytes];
|
||||
struct volume_key *derived_key;
|
||||
char *AfKey = NULL;
|
||||
unsigned int AFEKSize;
|
||||
uint64_t PBKDF2_temp;
|
||||
@@ -560,23 +758,26 @@ int LUKS_set_key(const char *device, unsigned int keyIndex,
|
||||
|
||||
log_dbg("Key slot %d use %d password iterations.", keyIndex, hdr->keyblock[keyIndex].passwordIterations);
|
||||
|
||||
derived_key = crypt_alloc_volume_key(hdr->keyBytes, NULL);
|
||||
if (!derived_key)
|
||||
return -ENOMEM;
|
||||
|
||||
r = crypt_random_get(ctx, hdr->keyblock[keyIndex].passwordSalt,
|
||||
LUKS_SALTSIZE, CRYPT_RND_NORMAL);
|
||||
LUKS_SALTSIZE, CRYPT_RND_SALT);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
// assert((vk->keylength % TWOFISH_BLOCKSIZE) == 0); FIXME
|
||||
|
||||
r = PBKDF2_HMAC(hdr->hashSpec, password,passwordLen,
|
||||
hdr->keyblock[keyIndex].passwordSalt,LUKS_SALTSIZE,
|
||||
hdr->keyblock[keyIndex].passwordIterations,
|
||||
derivedKey, hdr->keyBytes);
|
||||
derived_key->key, hdr->keyBytes);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* AF splitting, the masterkey stored in vk->key is split to AfKey
|
||||
*/
|
||||
assert(vk->keylength == hdr->keyBytes);
|
||||
AFEKSize = hdr->keyblock[keyIndex].stripes*vk->keylength;
|
||||
AfKey = crypt_safe_alloc(AFEKSize);
|
||||
if (!AfKey) {
|
||||
@@ -596,14 +797,12 @@ int LUKS_set_key(const char *device, unsigned int keyIndex,
|
||||
r = LUKS_encrypt_to_storage(AfKey,
|
||||
AFEKSize,
|
||||
hdr,
|
||||
derivedKey,
|
||||
hdr->keyBytes,
|
||||
derived_key,
|
||||
device,
|
||||
hdr->keyblock[keyIndex].keyMaterialOffset,
|
||||
ctx);
|
||||
if (r < 0) {
|
||||
if(!get_error())
|
||||
log_err(ctx, _("Failed to write to key storage.\n"));
|
||||
log_err(ctx, _("Failed to write to key storage.\n"));
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -619,7 +818,7 @@ int LUKS_set_key(const char *device, unsigned int keyIndex,
|
||||
r = 0;
|
||||
out:
|
||||
crypt_safe_free(AfKey);
|
||||
memset(derivedKey, 0, sizeof(derivedKey));
|
||||
crypt_free_volume_key(derived_key);
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -651,7 +850,7 @@ static int LUKS_open_key(const char *device,
|
||||
struct crypt_device *ctx)
|
||||
{
|
||||
crypt_keyslot_info ki = LUKS_keyslot_info(hdr, keyIndex);
|
||||
char derivedKey[hdr->keyBytes];
|
||||
struct volume_key *derived_key;
|
||||
char *AfKey;
|
||||
size_t AFEKSize;
|
||||
int r;
|
||||
@@ -662,8 +861,11 @@ static int LUKS_open_key(const char *device,
|
||||
if (ki < CRYPT_SLOT_ACTIVE)
|
||||
return -ENOENT;
|
||||
|
||||
// assert((vk->keylength % TWOFISH_BLOCKSIZE) == 0); FIXME
|
||||
derived_key = crypt_alloc_volume_key(hdr->keyBytes, NULL);
|
||||
if (!derived_key)
|
||||
return -ENOMEM;
|
||||
|
||||
assert(vk->keylength == hdr->keyBytes);
|
||||
AFEKSize = hdr->keyblock[keyIndex].stripes*vk->keylength;
|
||||
AfKey = crypt_safe_alloc(AFEKSize);
|
||||
if (!AfKey)
|
||||
@@ -672,7 +874,7 @@ static int LUKS_open_key(const char *device,
|
||||
r = PBKDF2_HMAC(hdr->hashSpec, password,passwordLen,
|
||||
hdr->keyblock[keyIndex].passwordSalt,LUKS_SALTSIZE,
|
||||
hdr->keyblock[keyIndex].passwordIterations,
|
||||
derivedKey, hdr->keyBytes);
|
||||
derived_key->key, hdr->keyBytes);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
@@ -680,8 +882,7 @@ static int LUKS_open_key(const char *device,
|
||||
r = LUKS_decrypt_from_storage(AfKey,
|
||||
AFEKSize,
|
||||
hdr,
|
||||
derivedKey,
|
||||
hdr->keyBytes,
|
||||
derived_key,
|
||||
device,
|
||||
hdr->keyblock[keyIndex].keyMaterialOffset,
|
||||
ctx);
|
||||
@@ -699,7 +900,7 @@ static int LUKS_open_key(const char *device,
|
||||
log_verbose(ctx, _("Key slot %d unlocked.\n"), keyIndex);
|
||||
out:
|
||||
crypt_safe_free(AfKey);
|
||||
memset(derivedKey, 0, sizeof(derivedKey));
|
||||
crypt_free_volume_key(derived_key);
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -736,72 +937,6 @@ int LUKS_open_key_with_hdr(const char *device,
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wipe patterns according to Gutmann's Paper
|
||||
*/
|
||||
|
||||
static void wipeSpecial(char *buffer, size_t buffer_size, unsigned int turn)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
unsigned char write_modes[][3] = {
|
||||
{"\x55\x55\x55"}, {"\xaa\xaa\xaa"}, {"\x92\x49\x24"},
|
||||
{"\x49\x24\x92"}, {"\x24\x92\x49"}, {"\x00\x00\x00"},
|
||||
{"\x11\x11\x11"}, {"\x22\x22\x22"}, {"\x33\x33\x33"},
|
||||
{"\x44\x44\x44"}, {"\x55\x55\x55"}, {"\x66\x66\x66"},
|
||||
{"\x77\x77\x77"}, {"\x88\x88\x88"}, {"\x99\x99\x99"},
|
||||
{"\xaa\xaa\xaa"}, {"\xbb\xbb\xbb"}, {"\xcc\xcc\xcc"},
|
||||
{"\xdd\xdd\xdd"}, {"\xee\xee\xee"}, {"\xff\xff\xff"},
|
||||
{"\x92\x49\x24"}, {"\x49\x24\x92"}, {"\x24\x92\x49"},
|
||||
{"\x6d\xb6\xdb"}, {"\xb6\xdb\x6d"}, {"\xdb\x6d\xb6"}
|
||||
};
|
||||
|
||||
for(i = 0; i < buffer_size / 3; ++i) {
|
||||
memcpy(buffer, write_modes[turn], 3);
|
||||
buffer += 3;
|
||||
}
|
||||
}
|
||||
|
||||
static int wipe(const char *device, unsigned int from, unsigned int to)
|
||||
{
|
||||
int devfd, r = 0;
|
||||
char *buffer;
|
||||
unsigned int i, bufLen;
|
||||
ssize_t written;
|
||||
|
||||
devfd = open(device, O_RDWR | O_DIRECT | O_SYNC);
|
||||
if(devfd == -1)
|
||||
return -EINVAL;
|
||||
|
||||
bufLen = (to - from) * SECTOR_SIZE;
|
||||
buffer = malloc(bufLen);
|
||||
if(!buffer) {
|
||||
close(devfd);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
for(i = 0; i < 39; ++i) {
|
||||
if (i < 5) crypt_random_get(NULL, buffer, bufLen,
|
||||
CRYPT_RND_NORMAL);
|
||||
else if(i >= 5 && i < 32) wipeSpecial(buffer, bufLen, i - 5);
|
||||
else if(i >= 32 && i < 38) crypt_random_get(NULL, buffer, bufLen,
|
||||
CRYPT_RND_NORMAL);
|
||||
else if(i >= 38 && i < 39) memset(buffer, 0xFF, bufLen);
|
||||
|
||||
written = write_lseek_blockwise(devfd, buffer, bufLen,
|
||||
from * SECTOR_SIZE);
|
||||
if (written < 0 || written != bufLen) {
|
||||
r = -EIO;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
close(devfd);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int LUKS_del_key(const char *device,
|
||||
unsigned int keyIndex,
|
||||
struct luks_phdr *hdr,
|
||||
@@ -810,7 +945,7 @@ int LUKS_del_key(const char *device,
|
||||
unsigned int startOffset, endOffset, stripesLen;
|
||||
int r;
|
||||
|
||||
r = LUKS_read_phdr(device, hdr, 1, ctx);
|
||||
r = LUKS_read_phdr(device, hdr, 1, 0, ctx);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
@@ -826,7 +961,9 @@ int LUKS_del_key(const char *device,
|
||||
stripesLen = hdr->keyBytes * hdr->keyblock[keyIndex].stripes;
|
||||
endOffset = startOffset + div_round_up(stripesLen, SECTOR_SIZE);
|
||||
|
||||
r = wipe(device, startOffset, endOffset);
|
||||
r = crypt_wipe(device, startOffset * SECTOR_SIZE,
|
||||
(endOffset - startOffset) * SECTOR_SIZE,
|
||||
CRYPT_WIPE_DISK, 0);
|
||||
if (r) {
|
||||
log_err(ctx, _("Cannot wipe device %s.\n"), device);
|
||||
return r;
|
||||
@@ -897,3 +1034,47 @@ int LUKS_keyslot_set(struct luks_phdr *hdr, int keyslot, int enable)
|
||||
log_dbg("Key slot %d was %s in LUKS header.", keyslot, enable ? "enabled" : "disabled");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LUKS1_activate(struct crypt_device *cd,
|
||||
const char *name,
|
||||
struct volume_key *vk,
|
||||
uint32_t flags)
|
||||
{
|
||||
int r;
|
||||
char *dm_cipher = NULL;
|
||||
enum devcheck device_check;
|
||||
struct crypt_dm_active_device dmd = {
|
||||
.target = DM_CRYPT,
|
||||
.uuid = crypt_get_uuid(cd),
|
||||
.flags = flags,
|
||||
.size = 0,
|
||||
.data_device = crypt_get_device_name(cd),
|
||||
.u.crypt = {
|
||||
.cipher = NULL,
|
||||
.vk = vk,
|
||||
.offset = crypt_get_data_offset(cd),
|
||||
.iv_offset = 0,
|
||||
}
|
||||
};
|
||||
|
||||
if (dmd.flags & CRYPT_ACTIVATE_SHARED)
|
||||
device_check = DEV_SHARED;
|
||||
else
|
||||
device_check = DEV_EXCL;
|
||||
|
||||
r = device_check_and_adjust(cd, dmd.data_device, device_check,
|
||||
&dmd.size, &dmd.u.crypt.offset,
|
||||
&dmd.flags);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = asprintf(&dm_cipher, "%s-%s", crypt_get_cipher(cd), crypt_get_cipher_mode(cd));
|
||||
if (r < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
dmd.u.crypt.cipher = dm_cipher;
|
||||
r = dm_create_device(name, CRYPT_LUKS1, &dmd, 0);
|
||||
|
||||
free(dm_cipher);
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,23 @@
|
||||
/*
|
||||
* LUKS - Linux Unified Key Setup
|
||||
*
|
||||
* Copyright (C) 2004-2006, Clemens Fruhwirth <clemens@endorphin.org>
|
||||
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_CRYPTSETUP_LUKS_LUKS_H
|
||||
#define INCLUDED_CRYPTSETUP_LUKS_LUKS_H
|
||||
|
||||
@@ -88,12 +108,14 @@ int LUKS_generate_phdr(
|
||||
unsigned int alignOffset,
|
||||
uint32_t iteration_time_ms,
|
||||
uint64_t *PBKDF2_per_sec,
|
||||
const char *metadata_device,
|
||||
struct crypt_device *ctx);
|
||||
|
||||
int LUKS_read_phdr(
|
||||
const char *device,
|
||||
struct luks_phdr *hdr,
|
||||
int require_luks_device,
|
||||
int repair,
|
||||
struct crypt_device *ctx);
|
||||
|
||||
int LUKS_read_phdr_backup(
|
||||
@@ -160,7 +182,7 @@ int LUKS_keyslot_set(struct luks_phdr *hdr, int keyslot, int enable);
|
||||
int LUKS_encrypt_to_storage(
|
||||
char *src, size_t srcLength,
|
||||
struct luks_phdr *hdr,
|
||||
char *key, size_t keyLength,
|
||||
struct volume_key *vk,
|
||||
const char *device,
|
||||
unsigned int sector,
|
||||
struct crypt_device *ctx);
|
||||
@@ -168,9 +190,14 @@ int LUKS_encrypt_to_storage(
|
||||
int LUKS_decrypt_from_storage(
|
||||
char *dst, size_t dstLength,
|
||||
struct luks_phdr *hdr,
|
||||
char *key, size_t keyLength,
|
||||
struct volume_key *vk,
|
||||
const char *device,
|
||||
unsigned int sector,
|
||||
struct crypt_device *ctx);
|
||||
|
||||
int LUKS1_activate(struct crypt_device *cd,
|
||||
const char *name,
|
||||
struct volume_key *vk,
|
||||
uint32_t flags);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
/* Implementation of Password-Based Cryptography as per PKCS#5
|
||||
/*
|
||||
* Implementation of Password-Based Cryptography as per PKCS#5
|
||||
* Copyright (C) 2002,2003 Simon Josefsson
|
||||
* Copyright (C) 2004 Free Software Foundation
|
||||
*
|
||||
* LUKS code
|
||||
* Copyright (C) 2004, Clemens Fruhwirth <clemens@endorphin.org>
|
||||
* Copyright (C) 2009-2011, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -18,7 +19,7 @@
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -167,9 +168,6 @@ static int pkcs5_pbkdf2(const char *hash,
|
||||
memset(T, 0, hLen);
|
||||
|
||||
for (u = 1; u <= c ; u++) {
|
||||
if (crypt_hmac_restart(hmac))
|
||||
goto out;
|
||||
|
||||
if (u == 1) {
|
||||
memcpy(tmp, S, Slen);
|
||||
tmp[Slen + 0] = (i & 0xff000000) >> 24;
|
||||
|
||||
@@ -1,3 +1,28 @@
|
||||
/*
|
||||
* Implementation of Password-Based Cryptography as per PKCS#5
|
||||
* Copyright (C) 2002,2003 Simon Josefsson
|
||||
* Copyright (C) 2004 Free Software Foundation
|
||||
*
|
||||
* LUKS code
|
||||
* Copyright (C) 2004, Clemens Fruhwirth <clemens@endorphin.org>
|
||||
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this file; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_CRYPTSETUP_LUKS_PBKDF_H
|
||||
#define INCLUDED_CRYPTSETUP_LUKS_PBKDF_H
|
||||
|
||||
|
||||
@@ -31,4 +31,4 @@
|
||||
( (Count) == 1 ? (Singular) : (Plural) )
|
||||
#endif
|
||||
|
||||
#endif /* CRYPTSETUP_H */
|
||||
#endif /* CRYPTSETUP_NLS_H */
|
||||
|
||||
14
lib/random.c
14
lib/random.c
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* cryptsetup kernel RNG access functions
|
||||
*
|
||||
* Copyright (C) 2010-2011, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2010-2012, Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
@@ -176,7 +176,17 @@ int crypt_random_get(struct crypt_device *ctx, char *buf, size_t len, int qualit
|
||||
case CRYPT_RND_NORMAL:
|
||||
status = _get_urandom(ctx, buf, len);
|
||||
break;
|
||||
case CRYPT_RND_SALT:
|
||||
if (crypt_fips_mode())
|
||||
status = crypt_backend_rng(buf, len, quality, 1);
|
||||
else
|
||||
status = _get_urandom(ctx, buf, len);
|
||||
break;
|
||||
case CRYPT_RND_KEY:
|
||||
if (crypt_fips_mode()) {
|
||||
status = crypt_backend_rng(buf, len, quality, 1);
|
||||
break;
|
||||
}
|
||||
rng_type = ctx ? crypt_get_rng_type(ctx) :
|
||||
crypt_random_default_key_rng();
|
||||
switch (rng_type) {
|
||||
|
||||
1974
lib/setup.c
1974
lib/setup.c
File diff suppressed because it is too large
Load Diff
132
lib/utils.c
132
lib/utils.c
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 2004, Christophe Saout <christophe@saout.de>
|
||||
* Copyright (C) 2004-2007, Clemens Fruhwirth <clemens@endorphin.org>
|
||||
* Copyright (C) 2009-2011, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -16,7 +16,7 @@
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -38,44 +38,9 @@
|
||||
#include "libcryptsetup.h"
|
||||
#include "internal.h"
|
||||
|
||||
static char *error=NULL;
|
||||
|
||||
__attribute__((format(printf, 1, 0)))
|
||||
void set_error_va(const char *fmt, va_list va)
|
||||
unsigned crypt_getpagesize(void)
|
||||
{
|
||||
int r;
|
||||
|
||||
if(error) {
|
||||
free(error);
|
||||
error = NULL;
|
||||
}
|
||||
|
||||
if(!fmt) return;
|
||||
|
||||
r = vasprintf(&error, fmt, va);
|
||||
if (r < 0) {
|
||||
free(error);
|
||||
error = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (r && error[r - 1] == '\n')
|
||||
error[r - 1] = '\0';
|
||||
}
|
||||
|
||||
__attribute__((format(printf, 1, 2)))
|
||||
void set_error(const char *fmt, ...)
|
||||
{
|
||||
va_list va;
|
||||
|
||||
va_start(va, fmt);
|
||||
set_error_va(fmt, va);
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
const char *get_error(void)
|
||||
{
|
||||
return error;
|
||||
return (unsigned)sysconf(_SC_PAGESIZE);
|
||||
}
|
||||
|
||||
static int get_alignment(int fd)
|
||||
@@ -336,10 +301,23 @@ int device_ready(struct crypt_device *cd, const char *device, int mode)
|
||||
return r;
|
||||
}
|
||||
|
||||
int get_device_infos(const char *device,
|
||||
int open_exclusive,
|
||||
int *readonly,
|
||||
uint64_t *size)
|
||||
int device_size(const char *device, uint64_t *size)
|
||||
{
|
||||
int devfd, r = 0;
|
||||
|
||||
devfd = open(device, O_RDONLY);
|
||||
if(devfd == -1)
|
||||
return -EINVAL;
|
||||
|
||||
if (ioctl(devfd, BLKGETSIZE64, size) < 0)
|
||||
r = -EINVAL;
|
||||
|
||||
close(devfd);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int get_device_infos(const char *device, enum devcheck device_check,
|
||||
int *readonly, uint64_t *size)
|
||||
{
|
||||
struct stat st;
|
||||
unsigned long size_small;
|
||||
@@ -353,7 +331,7 @@ int get_device_infos(const char *device,
|
||||
return -EINVAL;
|
||||
|
||||
/* never wipe header on mounted device */
|
||||
if (open_exclusive && S_ISBLK(st.st_mode))
|
||||
if (device_check == DEV_EXCL && S_ISBLK(st.st_mode))
|
||||
flags |= O_EXCL;
|
||||
|
||||
/* Try to open read-write to check whether it is a read-only device */
|
||||
@@ -363,7 +341,7 @@ int get_device_infos(const char *device,
|
||||
fd = open(device, O_RDONLY | flags);
|
||||
}
|
||||
|
||||
if (fd == -1 && open_exclusive && errno == EBUSY)
|
||||
if (fd == -1 && device_check == DEV_EXCL && errno == EBUSY)
|
||||
return -EBUSY;
|
||||
|
||||
if (fd == -1)
|
||||
@@ -396,10 +374,10 @@ out:
|
||||
|
||||
int device_check_and_adjust(struct crypt_device *cd,
|
||||
const char *device,
|
||||
int open_exclusive,
|
||||
enum devcheck device_check,
|
||||
uint64_t *size,
|
||||
uint64_t *offset,
|
||||
int *read_only)
|
||||
uint32_t *flags)
|
||||
{
|
||||
int r, real_readonly;
|
||||
uint64_t real_size;
|
||||
@@ -407,7 +385,7 @@ int device_check_and_adjust(struct crypt_device *cd,
|
||||
if (!device)
|
||||
return -ENOTBLK;
|
||||
|
||||
r = get_device_infos(device, open_exclusive, &real_readonly, &real_size);
|
||||
r = get_device_infos(device, device_check, &real_readonly, &real_size);
|
||||
if (r < 0) {
|
||||
if (r == -EBUSY)
|
||||
log_err(cd, _("Cannot use device %s which is in use "
|
||||
@@ -419,62 +397,38 @@ int device_check_and_adjust(struct crypt_device *cd,
|
||||
return r;
|
||||
}
|
||||
|
||||
if (*offset >= real_size) {
|
||||
log_err(cd, _("Requested offset is beyond real size of device %s.\n"),
|
||||
device);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!*size) {
|
||||
*size = real_size;
|
||||
if (!*size) {
|
||||
log_err(cd, _("Device %s has zero size.\n"), device);
|
||||
return -ENOTBLK;
|
||||
}
|
||||
if (*size < *offset) {
|
||||
log_err(cd, _("Device %s is too small.\n"), device);
|
||||
return -EINVAL;
|
||||
}
|
||||
*size -= *offset;
|
||||
}
|
||||
|
||||
/* in case of size is set by parameter */
|
||||
if ((real_size - *offset) < *size) {
|
||||
log_dbg("Device %s: offset = %" PRIu64 " requested size = %" PRIu64
|
||||
", backing device size = %" PRIu64,
|
||||
device, *offset, *size, real_size);
|
||||
log_err(cd, _("Device %s is too small.\n"), device);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (real_readonly)
|
||||
*read_only = 1;
|
||||
*flags |= CRYPT_ACTIVATE_READONLY;
|
||||
|
||||
log_dbg("Calculated device size is %" PRIu64 " sectors (%s), offset %" PRIu64 ".",
|
||||
*size, *read_only ? "RO" : "RW", *offset);
|
||||
*size, real_readonly ? "RO" : "RW", *offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wipe_device_header(const char *device, int sectors)
|
||||
{
|
||||
struct stat st;
|
||||
char *buffer;
|
||||
int size = sectors * SECTOR_SIZE;
|
||||
int r = -1;
|
||||
int devfd;
|
||||
int flags = O_RDWR | O_DIRECT | O_SYNC;
|
||||
|
||||
if (stat(device, &st) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* never wipe header on mounted device */
|
||||
if (S_ISBLK(st.st_mode))
|
||||
flags |= O_EXCL;
|
||||
|
||||
devfd = open(device, flags);
|
||||
if(devfd == -1)
|
||||
return errno == EBUSY ? -EBUSY : -EINVAL;
|
||||
|
||||
buffer = malloc(size);
|
||||
if (!buffer) {
|
||||
close(devfd);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(buffer, 0, size);
|
||||
|
||||
r = write_blockwise(devfd, buffer, size) < size ? -EIO : 0;
|
||||
|
||||
free(buffer);
|
||||
close(devfd);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* MEMLOCK */
|
||||
#define DEFAULT_PROCESS_PRIORITY -18
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* util_crypt - cipher utilities for cryptsetup
|
||||
* utils_crypt - cipher utilities for cryptsetup
|
||||
*
|
||||
* Copyright (C) 2004-2007, Clemens Fruhwirth <clemens@endorphin.org>
|
||||
* Copyright (C) 2009-2011, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -15,7 +15,7 @@
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
@@ -23,6 +23,8 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
@@ -58,6 +60,15 @@ int crypt_parse_name_and_mode(const char *s, char *cipher, int *key_nums,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Short version for "empty" cipher */
|
||||
if (!strcmp(s, "null")) {
|
||||
strncpy(cipher, "cipher_null", MAX_CIPHER_LEN);
|
||||
strncpy(cipher_mode, "ecb", 9);
|
||||
if (key_nums)
|
||||
*key_nums = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sscanf(s, "%" MAX_CIPHER_LEN_STR "[^-]", cipher) == 1) {
|
||||
strncpy(cipher_mode, "cbc-plain", 10);
|
||||
if (key_nums)
|
||||
@@ -235,6 +246,7 @@ static int crypt_get_key_tty(const char *prompt,
|
||||
|
||||
if (strncmp(pass, pass_verify, key_size_max)) {
|
||||
log_err(cd, _("Passphrases do not match.\n"));
|
||||
r = -EPERM;
|
||||
goto out_err;
|
||||
}
|
||||
}
|
||||
@@ -256,14 +268,14 @@ out_err:
|
||||
*/
|
||||
int crypt_get_key(const char *prompt,
|
||||
char **key, size_t *key_size,
|
||||
size_t keyfile_size_max, const char *key_file,
|
||||
int timeout, int verify,
|
||||
size_t keyfile_offset, size_t keyfile_size_max,
|
||||
const char *key_file, int timeout, int verify,
|
||||
struct crypt_device *cd)
|
||||
{
|
||||
int fd, regular_file, read_stdin, char_read, unlimited_read = 0;
|
||||
int r = -EINVAL;
|
||||
char *pass = NULL;
|
||||
size_t buflen, i;
|
||||
char *pass = NULL, tmp;
|
||||
size_t buflen, i, file_read_size;
|
||||
struct stat st;
|
||||
|
||||
*key = NULL;
|
||||
@@ -272,8 +284,13 @@ int crypt_get_key(const char *prompt,
|
||||
/* Passphrase read from stdin? */
|
||||
read_stdin = (!key_file || !strcmp(key_file, "-")) ? 1 : 0;
|
||||
|
||||
if(read_stdin && isatty(STDIN_FILENO))
|
||||
if (read_stdin && isatty(STDIN_FILENO)) {
|
||||
if (keyfile_offset) {
|
||||
log_err(cd, _("Cannot use offset with terminal input.\n"));
|
||||
return -EINVAL;
|
||||
}
|
||||
return crypt_get_key_tty(prompt, key, key_size, timeout, verify, cd);
|
||||
}
|
||||
|
||||
if (read_stdin)
|
||||
log_dbg("STDIN descriptor passphrase entry requested.");
|
||||
@@ -302,11 +319,19 @@ int crypt_get_key(const char *prompt,
|
||||
}
|
||||
if(S_ISREG(st.st_mode)) {
|
||||
regular_file = 1;
|
||||
file_read_size = (size_t)st.st_size;
|
||||
|
||||
if (keyfile_offset > file_read_size) {
|
||||
log_err(cd, _("Cannot seek to requested keyfile offset.\n"));
|
||||
goto out_err;
|
||||
}
|
||||
file_read_size -= keyfile_offset;
|
||||
|
||||
/* known keyfile size, alloc it in one step */
|
||||
if ((size_t)st.st_size >= keyfile_size_max)
|
||||
if (file_read_size >= keyfile_size_max)
|
||||
buflen = keyfile_size_max;
|
||||
else
|
||||
buflen = st.st_size;
|
||||
else if (file_read_size)
|
||||
buflen = file_read_size;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -316,6 +341,13 @@ int crypt_get_key(const char *prompt,
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
/* Discard keyfile_offset bytes on input */
|
||||
for(i = 0; i < keyfile_offset; i++)
|
||||
if (read(fd, &tmp, 1) != 1) {
|
||||
log_err(cd, _("Cannot seek to requested keyfile offset.\n"));
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
for(i = 0; i < keyfile_size_max; i++) {
|
||||
if(i == buflen) {
|
||||
buflen += 4096;
|
||||
@@ -347,7 +379,7 @@ int crypt_get_key(const char *prompt,
|
||||
|
||||
/* Fail if we exceeded internal default (no specified size) */
|
||||
if (unlimited_read && i == keyfile_size_max) {
|
||||
log_err(cd, _("Maximum keyfile size exceeeded.\n"));
|
||||
log_err(cd, _("Maximum keyfile size exceeded.\n"));
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
@@ -356,12 +388,6 @@ int crypt_get_key(const char *prompt,
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
/* Well, for historical reasons reading empty keyfile is not fail. */
|
||||
if(!i) {
|
||||
crypt_safe_free(pass);
|
||||
pass = NULL;
|
||||
}
|
||||
|
||||
*key = pass;
|
||||
*key_size = i;
|
||||
r = 0;
|
||||
@@ -373,3 +399,91 @@ out_err:
|
||||
crypt_safe_free(pass);
|
||||
return r;
|
||||
}
|
||||
|
||||
ssize_t crypt_hex_to_bytes(const char *hex, char **result, int safe_alloc)
|
||||
{
|
||||
char buf[3] = "xx\0", *endp, *bytes;
|
||||
size_t i, len;
|
||||
|
||||
len = strlen(hex);
|
||||
if (len % 2)
|
||||
return -EINVAL;
|
||||
len /= 2;
|
||||
|
||||
bytes = safe_alloc ? crypt_safe_alloc(len) : malloc(len);
|
||||
if (!bytes)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
memcpy(buf, &hex[i * 2], 2);
|
||||
bytes[i] = strtoul(buf, &endp, 16);
|
||||
if (endp != &buf[2]) {
|
||||
safe_alloc ? crypt_safe_free(bytes) : free(bytes);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
*result = bytes;
|
||||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
* Device size string parsing, suffixes:
|
||||
* s|S - 512 bytes sectors
|
||||
* k |K |m |M |g |G |t |T - 1024 base
|
||||
* kiB|KiB|miB|MiB|giB|GiB|tiB|TiB - 1024 base
|
||||
* kb |KB |mM |MB |gB |GB |tB |TB - 1000 base
|
||||
*/
|
||||
int crypt_string_to_size(struct crypt_device *cd, const char *s, uint64_t *size)
|
||||
{
|
||||
char *endp = NULL;
|
||||
size_t len;
|
||||
uint64_t mult_base, mult, tmp;
|
||||
|
||||
*size = strtoull(s, &endp, 10);
|
||||
if (!isdigit(s[0]) ||
|
||||
(errno == ERANGE && *size == ULLONG_MAX) ||
|
||||
(errno != 0 && *size == 0))
|
||||
return -EINVAL;
|
||||
|
||||
if (!endp || !*endp)
|
||||
return 0;
|
||||
|
||||
len = strlen(endp);
|
||||
/* Allow "B" and "iB" suffixes */
|
||||
if (len > 3 ||
|
||||
(len == 3 && (endp[1] != 'i' || endp[2] != 'B')) ||
|
||||
(len == 2 && endp[1] != 'B'))
|
||||
return -EINVAL;
|
||||
|
||||
if (len == 1 || len == 3)
|
||||
mult_base = 1024;
|
||||
else
|
||||
mult_base = 1000;
|
||||
|
||||
mult = 1;
|
||||
switch (endp[0]) {
|
||||
case 's':
|
||||
case 'S': mult = 512;
|
||||
break;
|
||||
case 't':
|
||||
case 'T': mult *= mult_base;
|
||||
case 'g':
|
||||
case 'G': mult *= mult_base;
|
||||
case 'm':
|
||||
case 'M': mult *= mult_base;
|
||||
case 'k':
|
||||
case 'K': mult *= mult_base;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tmp = *size * mult;
|
||||
if ((tmp / *size) != mult) {
|
||||
log_dbg("Device size overflow.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*size = tmp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,23 @@
|
||||
/*
|
||||
* utils_crypt - cipher utilities for cryptsetup
|
||||
*
|
||||
* Copyright (C) 2004-2007, Clemens Fruhwirth <clemens@endorphin.org>
|
||||
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef _UTILS_CRYPT_H
|
||||
#define _UTILS_CRYPT_H
|
||||
|
||||
@@ -14,7 +34,7 @@ int crypt_parse_name_and_mode(const char *s, char *cipher,
|
||||
|
||||
int crypt_get_key(const char *prompt,
|
||||
char **key, size_t *key_size,
|
||||
size_t keyfile_size_max,
|
||||
size_t keyfile_offset, size_t keyfile_size_max,
|
||||
const char *key_file,
|
||||
int timeout, int verify,
|
||||
struct crypt_device *cd);
|
||||
@@ -23,4 +43,7 @@ void *crypt_safe_alloc(size_t size);
|
||||
void crypt_safe_free(void *data);
|
||||
void *crypt_safe_realloc(void *data, size_t size);
|
||||
|
||||
ssize_t crypt_hex_to_bytes(const char *hex, char **result, int safe_alloc);
|
||||
int crypt_string_to_size(struct crypt_device *cd, const char *s, uint64_t *size);
|
||||
|
||||
#endif /* _UTILS_CRYPT_H */
|
||||
|
||||
@@ -1,146 +0,0 @@
|
||||
/*
|
||||
* Temporary debug code to find processes locking internal cryptsetup devices.
|
||||
* This code is intended to run only in debug mode.
|
||||
*
|
||||
* inspired by psmisc/fuser proc scanning code
|
||||
*
|
||||
* Copyright (C) 2009-2011, Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include "libcryptsetup.h"
|
||||
#include "internal.h"
|
||||
|
||||
#define MAX_PATHNAME 1024
|
||||
#define MAX_SHORTNAME 64
|
||||
|
||||
static int numeric_name(const char *name)
|
||||
{
|
||||
return (name[0] < '0' || name[0] > '9') ? 0 : 1;
|
||||
}
|
||||
|
||||
static int check_pid(const pid_t pid, const char *dev_name, const char *short_dev_name)
|
||||
{
|
||||
char dirpath[MAX_SHORTNAME], fdpath[MAX_SHORTNAME], linkpath[MAX_PATHNAME];
|
||||
DIR *dirp;
|
||||
struct dirent *direntry;
|
||||
ssize_t len;
|
||||
int r = 0;
|
||||
|
||||
snprintf(dirpath, sizeof(dirpath), "/proc/%d/fd", pid);
|
||||
|
||||
if (!(dirp = opendir(dirpath)))
|
||||
return r;
|
||||
|
||||
while ((direntry = readdir(dirp))) {
|
||||
if (!numeric_name(direntry->d_name))
|
||||
continue;
|
||||
|
||||
snprintf(fdpath, sizeof(fdpath), "/proc/%d/fd/%s", pid, direntry->d_name);
|
||||
|
||||
if ((len = readlink(fdpath, linkpath, MAX_PATHNAME-1)) < 0)
|
||||
break;
|
||||
linkpath[len] = '\0';
|
||||
|
||||
if (!strcmp(dev_name, linkpath)) {
|
||||
r = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!strcmp(short_dev_name, linkpath)) {
|
||||
r = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
closedir(dirp);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int read_proc_info(const pid_t pid, pid_t *ppid, char *name, int max_size)
|
||||
{
|
||||
char path[MAX_SHORTNAME], info[max_size], c;
|
||||
int fd, xpid, r = 0;
|
||||
|
||||
snprintf(path, sizeof(path), "/proc/%u/stat", pid);
|
||||
if ((fd = open(path, O_RDONLY)) < 0)
|
||||
return 0;
|
||||
|
||||
if (read(fd, info, max_size) > 0 &&
|
||||
sscanf(info, "%d %s %c %d", &xpid, name, &c, ppid) == 4)
|
||||
r = 1;
|
||||
|
||||
if (!r) {
|
||||
*ppid = 0;
|
||||
name[0] = '\0';
|
||||
}
|
||||
close(fd);
|
||||
return r;
|
||||
}
|
||||
|
||||
static void report_proc(const pid_t pid, const char *dev_name)
|
||||
{
|
||||
char name[MAX_PATHNAME], name2[MAX_PATHNAME];
|
||||
pid_t ppid, ppid2;
|
||||
|
||||
if (read_proc_info(pid, &ppid, name, MAX_PATHNAME) &&
|
||||
read_proc_info(ppid, &ppid2, name2, MAX_PATHNAME))
|
||||
log_dbg("WARNING: Process PID %u %s [PPID %u %s] spying on internal device %s.",
|
||||
pid, name, ppid, name2, dev_name);
|
||||
}
|
||||
|
||||
void debug_processes_using_device(const char *dm_name)
|
||||
{
|
||||
char short_dev_name[MAX_SHORTNAME], dev_name[MAX_PATHNAME];
|
||||
DIR *proc_dir;
|
||||
struct dirent *proc_dentry;
|
||||
struct stat st;
|
||||
pid_t pid;
|
||||
|
||||
if (crypt_get_debug_level() != CRYPT_LOG_DEBUG)
|
||||
return;
|
||||
|
||||
snprintf(dev_name, sizeof(dev_name), "/dev/mapper/%s", dm_name);
|
||||
if (stat(dev_name, &st) || !S_ISBLK(st.st_mode))
|
||||
return;
|
||||
snprintf(short_dev_name, sizeof(short_dev_name), "/dev/dm-%u", minor(st.st_rdev));
|
||||
|
||||
if (!(proc_dir = opendir("/proc")))
|
||||
return;
|
||||
|
||||
while ((proc_dentry = readdir(proc_dir))) {
|
||||
if (!numeric_name(proc_dentry->d_name))
|
||||
continue;
|
||||
|
||||
pid = atoi(proc_dentry->d_name);
|
||||
switch(check_pid(pid, dev_name, short_dev_name)) {
|
||||
case 1: report_proc(pid, dev_name);
|
||||
break;
|
||||
case 2: report_proc(pid, short_dev_name);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
closedir(proc_dir);
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 2004, Christophe Saout <christophe@saout.de>
|
||||
* Copyright (C) 2004-2007, Clemens Fruhwirth <clemens@endorphin.org>
|
||||
* Copyright (C) 2009-2011, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -16,7 +16,7 @@
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
@@ -24,11 +24,15 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include "utils_dm.h"
|
||||
|
||||
char *crypt_lookup_dev(const char *dev_id);
|
||||
int crypt_sysfs_check_crypt_segment(const char *device, uint64_t offset, uint64_t size);
|
||||
int crypt_sysfs_get_rotational(int major, int minor, int *rotational);
|
||||
|
||||
static char *__lookup_dev(char *path, dev_t dev, int dir_level, const int max_level)
|
||||
{
|
||||
@@ -146,7 +150,7 @@ char *crypt_lookup_dev(const char *dev_id)
|
||||
devname++;
|
||||
|
||||
if (dm_is_dm_kernel_name(devname))
|
||||
devpath = dm_device_path(major, minor);
|
||||
devpath = dm_device_path("/dev/mapper/", major, minor);
|
||||
else if (snprintf(path, sizeof(path), "/dev/%s", devname) > 0)
|
||||
devpath = strdup(path);
|
||||
|
||||
@@ -163,3 +167,102 @@ char *crypt_lookup_dev(const char *dev_id)
|
||||
|
||||
return devpath;
|
||||
}
|
||||
|
||||
static int crypt_sysfs_get_major_minor(const char *kname, int *major, int *minor)
|
||||
{
|
||||
char path[PATH_MAX], tmp[64] = {0};
|
||||
int fd, r = 0;
|
||||
|
||||
if (snprintf(path, sizeof(path), "/sys/block/%s/dev", kname) < 0)
|
||||
return 0;
|
||||
|
||||
if ((fd = open(path, O_RDONLY)) < 0)
|
||||
return 0;
|
||||
r = read(fd, tmp, sizeof(tmp));
|
||||
close(fd);
|
||||
|
||||
if (r <= 0)
|
||||
return 0;
|
||||
|
||||
tmp[63] = '\0';
|
||||
if (sscanf(tmp, "%d:%d", major, minor) != 2)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int crypt_sysfs_get_holders_dir(const char *device, char *path, int size)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if (stat(device, &st) < 0 || !S_ISBLK(st.st_mode))
|
||||
return 0;
|
||||
|
||||
if (snprintf(path, size, "/sys/dev/block/%d:%d/holders",
|
||||
major(st.st_rdev), minor(st.st_rdev)) < 0)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int crypt_sysfs_check_crypt_segment(const char *device, uint64_t offset, uint64_t size)
|
||||
{
|
||||
DIR *dir;
|
||||
struct dirent *d;
|
||||
char path[PATH_MAX], *dmname;
|
||||
int major, minor, r = 0;
|
||||
|
||||
if (!crypt_sysfs_get_holders_dir(device, path, sizeof(path)))
|
||||
return -EINVAL;
|
||||
|
||||
if (!(dir = opendir(path)))
|
||||
return -EINVAL;
|
||||
|
||||
while (!r && (d = readdir(dir))) {
|
||||
if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
|
||||
continue;
|
||||
|
||||
if (!dm_is_dm_kernel_name(d->d_name)) {
|
||||
r = -EBUSY;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!crypt_sysfs_get_major_minor(d->d_name, &major, &minor)) {
|
||||
r = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(dmname = dm_device_path(NULL, major, minor))) {
|
||||
r = -EINVAL;
|
||||
break;
|
||||
}
|
||||
r = dm_check_segment(dmname, offset, size);
|
||||
free(dmname);
|
||||
}
|
||||
closedir(dir);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int crypt_sysfs_get_rotational(int major, int minor, int *rotational)
|
||||
{
|
||||
char path[PATH_MAX], tmp[64] = {0};
|
||||
int fd, r;
|
||||
|
||||
if (snprintf(path, sizeof(path), "/sys/dev/block/%d:%d/queue/rotational",
|
||||
major, minor) < 0)
|
||||
return 0;
|
||||
|
||||
if ((fd = open(path, O_RDONLY)) < 0)
|
||||
return 0;
|
||||
r = read(fd, tmp, sizeof(tmp));
|
||||
close(fd);
|
||||
|
||||
if (r <= 0)
|
||||
return 0;
|
||||
|
||||
if (sscanf(tmp, "%d", rotational) != 1)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,24 @@
|
||||
/*
|
||||
* libdevmapper - device-mapper backend for cryptsetup
|
||||
*
|
||||
* Copyright (C) 2004, Christophe Saout <christophe@saout.de>
|
||||
* Copyright (C) 2004-2007, Clemens Fruhwirth <clemens@endorphin.org>
|
||||
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef _UTILS_DM_H
|
||||
#define _UTILS_DM_H
|
||||
|
||||
@@ -5,41 +26,78 @@
|
||||
#include <inttypes.h>
|
||||
|
||||
struct crypt_device;
|
||||
struct volume_key;
|
||||
struct crypt_params_verity;
|
||||
|
||||
/* Device mapper backend - kernel support flags */
|
||||
#define DM_KEY_WIPE_SUPPORTED (1 << 0) /* key wipe message */
|
||||
#define DM_LMK_SUPPORTED (1 << 1) /* lmk mode */
|
||||
#define DM_SECURE_SUPPORTED (1 << 2) /* wipe (secure) buffer flag */
|
||||
#define DM_PLAIN64_SUPPORTED (1 << 3) /* plain64 IV */
|
||||
#define DM_DISCARDS_SUPPORTED (1 << 4) /* discards/TRIM option is supported */
|
||||
#define DM_VERITY_SUPPORTED (1 << 5) /* dm-verity target supported */
|
||||
uint32_t dm_flags(void);
|
||||
|
||||
#define DM_ACTIVE_DEVICE (1 << 0)
|
||||
#define DM_ACTIVE_UUID (1 << 1)
|
||||
|
||||
#define DM_ACTIVE_CRYPT_CIPHER (1 << 2)
|
||||
#define DM_ACTIVE_CRYPT_KEYSIZE (1 << 3)
|
||||
#define DM_ACTIVE_CRYPT_KEY (1 << 4)
|
||||
|
||||
#define DM_ACTIVE_VERITY_ROOT_HASH (1 << 5)
|
||||
#define DM_ACTIVE_VERITY_HASH_DEVICE (1 << 6)
|
||||
#define DM_ACTIVE_VERITY_PARAMS (1 << 7)
|
||||
|
||||
struct crypt_dm_active_device {
|
||||
enum { DM_CRYPT = 0, DM_VERITY } target;
|
||||
uint64_t size; /* active device size */
|
||||
uint32_t flags; /* activation flags */
|
||||
const char *uuid;
|
||||
const char *data_device;
|
||||
union {
|
||||
struct {
|
||||
const char *cipher;
|
||||
|
||||
/* Active key for device */
|
||||
struct volume_key *vk;
|
||||
|
||||
/* struct crypt_active_device */
|
||||
uint64_t offset; /* offset in sectors */
|
||||
uint64_t iv_offset; /* IV initilisation sector */
|
||||
} crypt;
|
||||
struct {
|
||||
const char *hash_device;
|
||||
|
||||
const char *root_hash;
|
||||
uint32_t root_hash_size;
|
||||
|
||||
uint64_t hash_offset; /* hash offset in blocks (not header) */
|
||||
struct crypt_params_verity *vp;
|
||||
} verity;
|
||||
} u;
|
||||
};
|
||||
|
||||
const char *dm_get_dir(void);
|
||||
int dm_init(struct crypt_device *context, int check_kernel);
|
||||
void dm_exit(void);
|
||||
int dm_remove_device(const char *name, int force, uint64_t size);
|
||||
int dm_status_device(const char *name);
|
||||
int dm_query_device(const char *name,
|
||||
char **device,
|
||||
uint64_t *size,
|
||||
uint64_t *skip,
|
||||
uint64_t *offset,
|
||||
char **cipher,
|
||||
int *key_size,
|
||||
char **key,
|
||||
int *read_only,
|
||||
int *suspended,
|
||||
char **uuid);
|
||||
int dm_create_device(const char *name, const char *device, const char *cipher,
|
||||
const char *type, const char *uuid,
|
||||
uint64_t size, uint64_t skip, uint64_t offset,
|
||||
size_t key_size, const char *key,
|
||||
int read_only, int reload);
|
||||
int dm_status_suspended(const char *name);
|
||||
int dm_status_verity_ok(const char *name);
|
||||
int dm_query_device(const char *name, uint32_t get_flags,
|
||||
struct crypt_dm_active_device *dmd);
|
||||
int dm_create_device(const char *name,
|
||||
const char *type,
|
||||
struct crypt_dm_active_device *dmd,
|
||||
int reload);
|
||||
int dm_suspend_and_wipe_key(const char *name);
|
||||
int dm_resume_and_reinstate_key(const char *name,
|
||||
size_t key_size,
|
||||
const char *key);
|
||||
char *dm_device_path(int major, int minor);
|
||||
char *dm_device_path(const char *prefix, int major, int minor);
|
||||
int dm_is_dm_device(int major, int minor);
|
||||
int dm_is_dm_kernel_name(const char *name);
|
||||
int dm_check_segment(const char *name, uint64_t offset, uint64_t size);
|
||||
|
||||
#endif /* _UTILS_DM_H */
|
||||
|
||||
62
lib/utils_fips.c
Normal file
62
lib/utils_fips.c
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* FIPS mode utilities
|
||||
*
|
||||
* Copyright (C) 2011-2012, Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* 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 <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include "libcryptsetup.h"
|
||||
#include "nls.h"
|
||||
#include "utils_fips.h"
|
||||
#include "config.h"
|
||||
|
||||
#if !ENABLE_FIPS
|
||||
int crypt_fips_mode(void) { return 0; }
|
||||
void crypt_fips_libcryptsetup_check(struct crypt_device *cd) {}
|
||||
void crypt_fips_self_check(struct crypt_device *cd) {}
|
||||
#else
|
||||
#include <fipscheck.h>
|
||||
|
||||
int crypt_fips_mode(void)
|
||||
{
|
||||
return FIPSCHECK_kernel_fips_mode();
|
||||
}
|
||||
|
||||
static void crypt_fips_verify(struct crypt_device *cd,
|
||||
const char *name, const char *function)
|
||||
{
|
||||
if (!crypt_fips_mode())
|
||||
return;
|
||||
|
||||
if (!FIPSCHECK_verify(name, function)) {
|
||||
crypt_log(cd, CRYPT_LOG_ERROR, _("FIPS checksum verification failed.\n"));
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
crypt_log(cd, CRYPT_LOG_VERBOSE, _("Running in FIPS mode.\n"));
|
||||
}
|
||||
|
||||
void crypt_fips_libcryptsetup_check(struct crypt_device *cd)
|
||||
{
|
||||
crypt_fips_verify(cd, LIBCRYPTSETUP_VERSION_FIPS, "crypt_init");
|
||||
}
|
||||
|
||||
void crypt_fips_self_check(struct crypt_device *cd)
|
||||
{
|
||||
crypt_fips_verify(cd, NULL, NULL);
|
||||
}
|
||||
#endif /* ENABLE_FIPS */
|
||||
29
lib/utils_fips.h
Normal file
29
lib/utils_fips.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* FIPS mode utilities
|
||||
*
|
||||
* Copyright (C) 2011-2012, Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef _UTILS_FIPS_H
|
||||
#define _UTILS_FIPS_H
|
||||
|
||||
struct crypt_device;
|
||||
|
||||
int crypt_fips_mode(void);
|
||||
void crypt_fips_libcryptsetup_check(struct crypt_device *cd);
|
||||
void crypt_fips_self_check(struct crypt_device *cd);
|
||||
|
||||
#endif /* _UTILS_FIPS_H */
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* loopback block device utilities
|
||||
*
|
||||
* Copyright (C) 2011, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2011-2012, Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
@@ -29,7 +29,17 @@
|
||||
|
||||
#include "utils_loop.h"
|
||||
|
||||
char *crypt_loop_get_device(void)
|
||||
#define LOOP_DEV_MAJOR 7
|
||||
|
||||
#ifndef LO_FLAGS_AUTOCLEAR
|
||||
#define LO_FLAGS_AUTOCLEAR 4
|
||||
#endif
|
||||
|
||||
#ifndef LOOP_CTL_GET_FREE
|
||||
#define LOOP_CTL_GET_FREE 0x4C82
|
||||
#endif
|
||||
|
||||
static char *crypt_loop_get_device_old(void)
|
||||
{
|
||||
char dev[20];
|
||||
int i, loop_fd;
|
||||
@@ -56,6 +66,32 @@ char *crypt_loop_get_device(void)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *crypt_loop_get_device(void)
|
||||
{
|
||||
char dev[64];
|
||||
int i, loop_fd;
|
||||
struct stat st;
|
||||
|
||||
loop_fd = open("/dev/loop-control", O_RDONLY);
|
||||
if (loop_fd < 0)
|
||||
return crypt_loop_get_device_old();
|
||||
|
||||
i = ioctl(loop_fd, LOOP_CTL_GET_FREE);
|
||||
if (i < 0) {
|
||||
close(loop_fd);
|
||||
return NULL;
|
||||
}
|
||||
close(loop_fd);
|
||||
|
||||
if (sprintf(dev, "/dev/loop%d", i) < 0)
|
||||
return NULL;
|
||||
|
||||
if (stat(dev, &st) || !S_ISBLK(st.st_mode))
|
||||
return NULL;
|
||||
|
||||
return strdup(dev);
|
||||
}
|
||||
|
||||
int crypt_loop_attach(const char *loop, const char *file, int offset,
|
||||
int autoclear, int *readonly)
|
||||
{
|
||||
@@ -63,7 +99,7 @@ int crypt_loop_attach(const char *loop, const char *file, int offset,
|
||||
int loop_fd = -1, file_fd = -1, r = 1;
|
||||
|
||||
file_fd = open(file, (*readonly ? O_RDONLY : O_RDWR) | O_EXCL);
|
||||
if (file_fd < 0 && errno == EROFS && !*readonly) {
|
||||
if (file_fd < 0 && (errno == EROFS || errno == EACCES) && !*readonly) {
|
||||
*readonly = 1;
|
||||
file_fd = open(file, O_RDONLY | O_EXCL);
|
||||
}
|
||||
|
||||
@@ -1,14 +1,27 @@
|
||||
/*
|
||||
* loopback block device utilities
|
||||
*
|
||||
* Copyright (C) 2011-2012, Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef _UTILS_LOOP_H
|
||||
#define _UTILS_LOOP_H
|
||||
|
||||
/* loopback device helpers */
|
||||
|
||||
#define LOOP_DEV_MAJOR 7
|
||||
|
||||
#ifndef LO_FLAGS_AUTOCLEAR
|
||||
#define LO_FLAGS_AUTOCLEAR 4
|
||||
#endif
|
||||
|
||||
char *crypt_loop_get_device(void);
|
||||
char *crypt_loop_backing_file(const char *loop);
|
||||
int crypt_loop_device(const char *loop);
|
||||
|
||||
187
lib/utils_wipe.c
Normal file
187
lib/utils_wipe.c
Normal file
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
* utils_wipe - wipe a device
|
||||
*
|
||||
* Copyright (C) 2004-2007, Clemens Fruhwirth <clemens@endorphin.org>
|
||||
* Copyright (C) 2011-2012, Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* 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 <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "libcryptsetup.h"
|
||||
#include "internal.h"
|
||||
|
||||
#define MAXIMUM_WIPE_BYTES 1024 * 1024 * 32 /* 32 MiB */
|
||||
|
||||
static ssize_t _crypt_wipe_zero(int fd, char *buffer, uint64_t offset, uint64_t size)
|
||||
{
|
||||
memset(buffer, 0, size);
|
||||
return write_lseek_blockwise(fd, buffer, size, offset);
|
||||
}
|
||||
|
||||
static ssize_t _crypt_wipe_random(int fd, char *buffer, uint64_t offset, uint64_t size)
|
||||
{
|
||||
if (crypt_random_get(NULL, buffer, size, CRYPT_RND_NORMAL) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
return write_lseek_blockwise(fd, buffer, size, offset);
|
||||
}
|
||||
|
||||
/*
|
||||
* Wipe using Peter Gutmann method described in
|
||||
* http://www.cs.auckland.ac.nz/~pgut001/pubs/secure_del.html
|
||||
*/
|
||||
static void wipeSpecial(char *buffer, size_t buffer_size, unsigned int turn)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
unsigned char write_modes[][3] = {
|
||||
{"\x55\x55\x55"}, {"\xaa\xaa\xaa"}, {"\x92\x49\x24"},
|
||||
{"\x49\x24\x92"}, {"\x24\x92\x49"}, {"\x00\x00\x00"},
|
||||
{"\x11\x11\x11"}, {"\x22\x22\x22"}, {"\x33\x33\x33"},
|
||||
{"\x44\x44\x44"}, {"\x55\x55\x55"}, {"\x66\x66\x66"},
|
||||
{"\x77\x77\x77"}, {"\x88\x88\x88"}, {"\x99\x99\x99"},
|
||||
{"\xaa\xaa\xaa"}, {"\xbb\xbb\xbb"}, {"\xcc\xcc\xcc"},
|
||||
{"\xdd\xdd\xdd"}, {"\xee\xee\xee"}, {"\xff\xff\xff"},
|
||||
{"\x92\x49\x24"}, {"\x49\x24\x92"}, {"\x24\x92\x49"},
|
||||
{"\x6d\xb6\xdb"}, {"\xb6\xdb\x6d"}, {"\xdb\x6d\xb6"}
|
||||
};
|
||||
|
||||
for(i = 0; i < buffer_size / 3; ++i) {
|
||||
memcpy(buffer, write_modes[turn], 3);
|
||||
buffer += 3;
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t _crypt_wipe_disk(int fd, char *buffer, uint64_t offset, uint64_t size)
|
||||
{
|
||||
int r;
|
||||
unsigned int i;
|
||||
ssize_t written;
|
||||
|
||||
for(i = 0; i < 39; ++i) {
|
||||
if (i < 5) {
|
||||
r = crypt_random_get(NULL, buffer, size, CRYPT_RND_NORMAL);
|
||||
} else if(i >= 5 && i < 32) {
|
||||
wipeSpecial(buffer, size, i - 5);
|
||||
r = 0;
|
||||
} else if(i >= 32 && i < 38) {
|
||||
r = crypt_random_get(NULL, buffer, size, CRYPT_RND_NORMAL);
|
||||
} else if(i >= 38 && i < 39) {
|
||||
memset(buffer, 0xFF, size);
|
||||
r = 0;
|
||||
}
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
written = write_lseek_blockwise(fd, buffer, size, offset);
|
||||
if (written < 0 || written != (ssize_t)size)
|
||||
return written;
|
||||
}
|
||||
|
||||
/* Rewrite it finally with random */
|
||||
return _crypt_wipe_random(fd, buffer, offset, size);
|
||||
}
|
||||
|
||||
static ssize_t _crypt_wipe_ssd(int fd, char *buffer, uint64_t offset, uint64_t size)
|
||||
{
|
||||
// FIXME: for now just rewrite it by random
|
||||
return _crypt_wipe_random(fd, buffer, offset, size);
|
||||
}
|
||||
|
||||
int crypt_wipe(const char *device,
|
||||
uint64_t offset,
|
||||
uint64_t size,
|
||||
crypt_wipe_type type,
|
||||
int exclusive)
|
||||
{
|
||||
struct stat st;
|
||||
char *buffer;
|
||||
int devfd, flags, rotational;
|
||||
ssize_t written;
|
||||
|
||||
if (!size || size % SECTOR_SIZE || (size > MAXIMUM_WIPE_BYTES)) {
|
||||
log_dbg("Unsuported wipe size for device %s: %ld.",
|
||||
device, (unsigned long)size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (stat(device, &st) < 0) {
|
||||
log_dbg("Device %s not found.", device);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (type == CRYPT_WIPE_DISK) {
|
||||
if (!crypt_sysfs_get_rotational(major(st.st_rdev),
|
||||
minor(st.st_rdev),
|
||||
&rotational))
|
||||
rotational = 1;
|
||||
log_dbg("Rotational flag is %d.", rotational);
|
||||
if (!rotational)
|
||||
type = CRYPT_WIPE_SSD;
|
||||
}
|
||||
|
||||
buffer = malloc(size);
|
||||
if (!buffer)
|
||||
return -ENOMEM;
|
||||
|
||||
flags = O_RDWR | O_DIRECT | O_SYNC;
|
||||
|
||||
/* use O_EXCL only for block devices */
|
||||
if (exclusive && S_ISBLK(st.st_mode))
|
||||
flags |= O_EXCL;
|
||||
|
||||
devfd = open(device, flags);
|
||||
if (devfd == -1) {
|
||||
free(buffer);
|
||||
return errno == EBUSY ? -EBUSY : -EINVAL;
|
||||
}
|
||||
|
||||
// FIXME: use fixed block size and loop here
|
||||
switch (type) {
|
||||
case CRYPT_WIPE_ZERO:
|
||||
written = _crypt_wipe_zero(devfd, buffer, offset, size);
|
||||
break;
|
||||
case CRYPT_WIPE_DISK:
|
||||
written = _crypt_wipe_disk(devfd, buffer, offset, size);
|
||||
break;
|
||||
case CRYPT_WIPE_SSD:
|
||||
written = _crypt_wipe_ssd(devfd, buffer, offset, size);
|
||||
break;
|
||||
case CRYPT_WIPE_RANDOM:
|
||||
written = _crypt_wipe_random(devfd, buffer, offset, size);
|
||||
break;
|
||||
default:
|
||||
log_dbg("Unsuported wipe type requested: (%d)", type);
|
||||
written = -1;
|
||||
}
|
||||
|
||||
close(devfd);
|
||||
free(buffer);
|
||||
|
||||
if (written != (ssize_t)size || written < 0)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
16
lib/verity/Makefile.am
Normal file
16
lib/verity/Makefile.am
Normal file
@@ -0,0 +1,16 @@
|
||||
moduledir = $(libdir)/cryptsetup
|
||||
|
||||
noinst_LTLIBRARIES = libverity.la
|
||||
|
||||
libverity_la_CFLAGS = -Wall @CRYPTO_CFLAGS@
|
||||
|
||||
libverity_la_SOURCES = \
|
||||
verity_hash.c \
|
||||
verity.c \
|
||||
verity.h
|
||||
|
||||
INCLUDES = -D_GNU_SOURCE \
|
||||
-D_LARGEFILE64_SOURCE \
|
||||
-D_FILE_OFFSET_BITS=64 \
|
||||
-I$(top_srcdir)/lib \
|
||||
-I$(top_srcdir)/lib/crypto_backend
|
||||
279
lib/verity/verity.c
Normal file
279
lib/verity/verity.c
Normal file
@@ -0,0 +1,279 @@
|
||||
/*
|
||||
* dm-verity volume handling
|
||||
*
|
||||
* Copyright (C) 2012, Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* 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 <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <netinet/in.h>
|
||||
#include <uuid/uuid.h>
|
||||
|
||||
#include "libcryptsetup.h"
|
||||
#include "verity.h"
|
||||
#include "internal.h"
|
||||
|
||||
#define VERITY_SIGNATURE "verity\0\0"
|
||||
|
||||
/* http://code.google.com/p/cryptsetup/wiki/DMVerity#Verity_superblock_format */
|
||||
struct verity_sb {
|
||||
uint8_t signature[8]; /* "verity\0\0" */
|
||||
uint32_t version; /* superblock version */
|
||||
uint32_t hash_type; /* 0 - Chrome OS, 1 - normal */
|
||||
uint8_t uuid[16]; /* UUID of hash device */
|
||||
uint8_t algorithm[32];/* hash algorithm name */
|
||||
uint32_t data_block_size; /* data block in bytes */
|
||||
uint32_t hash_block_size; /* hash block in bytes */
|
||||
uint64_t data_blocks; /* number of data blocks */
|
||||
uint16_t salt_size; /* salt size */
|
||||
uint8_t _pad1[6];
|
||||
uint8_t salt[256]; /* salt */
|
||||
uint8_t _pad2[168];
|
||||
} __attribute__((packed));
|
||||
|
||||
/* Read verity superblock from disk */
|
||||
int VERITY_read_sb(struct crypt_device *cd,
|
||||
const char *device,
|
||||
uint64_t sb_offset,
|
||||
char **uuid_string,
|
||||
struct crypt_params_verity *params)
|
||||
{
|
||||
struct verity_sb sb = {};
|
||||
ssize_t hdr_size = sizeof(struct verity_sb);
|
||||
int devfd = 0, sb_version;
|
||||
|
||||
log_dbg("Reading VERITY header of size %u on device %s, offset %" PRIu64 ".",
|
||||
sizeof(struct verity_sb), device, sb_offset);
|
||||
|
||||
if (params->flags & CRYPT_VERITY_NO_HEADER) {
|
||||
log_err(cd, _("Verity device doesn't use on-disk header.\n"), device);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (sb_offset % 512) {
|
||||
log_err(cd, _("Unsupported VERITY hash offset.\n"));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
devfd = open(device ,O_RDONLY | O_DIRECT);
|
||||
if(devfd == -1) {
|
||||
log_err(cd, _("Cannot open device %s.\n"), device);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if(lseek(devfd, sb_offset, SEEK_SET) < 0 ||
|
||||
read_blockwise(devfd, &sb, hdr_size) < hdr_size) {
|
||||
close(devfd);
|
||||
return -EIO;
|
||||
}
|
||||
close(devfd);
|
||||
|
||||
if (memcmp(sb.signature, VERITY_SIGNATURE, sizeof(sb.signature))) {
|
||||
log_err(cd, _("Device %s is not a valid VERITY device.\n"), device);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sb_version = le32_to_cpu(sb.version);
|
||||
if (sb_version != 1) {
|
||||
log_err(cd, _("Unsupported VERITY version %d.\n"), sb_version);
|
||||
return -EINVAL;
|
||||
}
|
||||
params->hash_type = le32_to_cpu(sb.hash_type);
|
||||
if (params->hash_type > VERITY_MAX_HASH_TYPE) {
|
||||
log_err(cd, _("Unsupported VERITY hash type %d.\n"), params->hash_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
params->data_block_size = le32_to_cpu(sb.data_block_size);
|
||||
params->hash_block_size = le32_to_cpu(sb.hash_block_size);
|
||||
if (VERITY_BLOCK_SIZE_OK(params->data_block_size) ||
|
||||
VERITY_BLOCK_SIZE_OK(params->hash_block_size)) {
|
||||
log_err(cd, _("Unsupported VERITY block size.\n"));
|
||||
return -EINVAL;
|
||||
}
|
||||
params->data_size = le64_to_cpu(sb.data_blocks);
|
||||
|
||||
params->hash_name = strndup((const char*)sb.algorithm, sizeof(sb.algorithm));
|
||||
if (!params->hash_name)
|
||||
return -ENOMEM;
|
||||
if (crypt_hash_size(params->hash_name) <= 0) {
|
||||
log_err(cd, _("Hash algorithm %s not supported.\n"),
|
||||
params->hash_name);
|
||||
free(CONST_CAST(char*)params->hash_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
params->salt_size = le16_to_cpu(sb.salt_size);
|
||||
if (params->salt_size > sizeof(sb.salt)) {
|
||||
log_err(cd, _("VERITY header corrupted.\n"));
|
||||
free(CONST_CAST(char*)params->hash_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
params->salt = malloc(params->salt_size);
|
||||
if (!params->salt) {
|
||||
free(CONST_CAST(char*)params->hash_name);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memcpy(CONST_CAST(char*)params->salt, sb.salt, params->salt_size);
|
||||
|
||||
if ((*uuid_string = malloc(40)))
|
||||
uuid_unparse(sb.uuid, *uuid_string);
|
||||
|
||||
params->hash_area_offset = sb_offset;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Write verity superblock to disk */
|
||||
int VERITY_write_sb(struct crypt_device *cd,
|
||||
const char *device,
|
||||
uint64_t sb_offset,
|
||||
const char *uuid_string,
|
||||
struct crypt_params_verity *params)
|
||||
{
|
||||
struct verity_sb sb = {};
|
||||
ssize_t hdr_size = sizeof(struct verity_sb);
|
||||
uuid_t uuid;
|
||||
int r, devfd = 0;
|
||||
|
||||
log_dbg("Updating VERITY header of size %u on device %s, offset %" PRIu64 ".",
|
||||
sizeof(struct verity_sb), device, sb_offset);
|
||||
|
||||
if (!uuid_string || uuid_parse(uuid_string, uuid) == -1) {
|
||||
log_err(cd, _("Wrong VERITY UUID format provided.\n"), device);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (params->flags & CRYPT_VERITY_NO_HEADER) {
|
||||
log_err(cd, _("Verity device doesn't use on-disk header.\n"), device);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
devfd = open(device, O_RDWR | O_DIRECT);
|
||||
if(devfd == -1) {
|
||||
log_err(cd, _("Cannot open device %s.\n"), device);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memcpy(&sb.signature, VERITY_SIGNATURE, sizeof(sb.signature));
|
||||
sb.version = cpu_to_le32(1);
|
||||
sb.hash_type = cpu_to_le32(params->hash_type);
|
||||
sb.data_block_size = cpu_to_le32(params->data_block_size);
|
||||
sb.hash_block_size = cpu_to_le32(params->hash_block_size);
|
||||
sb.salt_size = cpu_to_le16(params->salt_size);
|
||||
sb.data_blocks = cpu_to_le64(params->data_size);
|
||||
strncpy((char *)sb.algorithm, params->hash_name, sizeof(sb.algorithm));
|
||||
memcpy(sb.salt, params->salt, params->salt_size);
|
||||
memcpy(sb.uuid, uuid, sizeof(sb.uuid));
|
||||
|
||||
r = write_lseek_blockwise(devfd, (char*)&sb, hdr_size, sb_offset) < hdr_size ? -EIO : 0;
|
||||
if (r)
|
||||
log_err(cd, _("Error during update of verity header on device %s.\n"), device);
|
||||
close(devfd);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Calculate hash offset in hash blocks */
|
||||
uint64_t VERITY_hash_offset_block(struct crypt_params_verity *params)
|
||||
{
|
||||
uint64_t hash_offset = params->hash_area_offset;
|
||||
|
||||
if (params->flags & CRYPT_VERITY_NO_HEADER)
|
||||
return hash_offset / params->hash_block_size;
|
||||
|
||||
hash_offset += sizeof(struct verity_sb);
|
||||
hash_offset += params->hash_block_size - 1;
|
||||
|
||||
return hash_offset / params->hash_block_size;
|
||||
}
|
||||
|
||||
int VERITY_UUID_generate(struct crypt_device *cd, char **uuid_string)
|
||||
{
|
||||
uuid_t uuid;
|
||||
|
||||
if (!(*uuid_string = malloc(40)))
|
||||
return -ENOMEM;
|
||||
uuid_generate(uuid);
|
||||
uuid_unparse(uuid, *uuid_string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Activate verity device in kernel device-mapper */
|
||||
int VERITY_activate(struct crypt_device *cd,
|
||||
const char *name,
|
||||
const char *hash_device,
|
||||
const char *root_hash,
|
||||
size_t root_hash_size,
|
||||
struct crypt_params_verity *verity_hdr,
|
||||
uint32_t activation_flags)
|
||||
{
|
||||
struct crypt_dm_active_device dmd;
|
||||
uint64_t offset = 0;
|
||||
int r;
|
||||
|
||||
log_dbg("Trying to activate VERITY device %s using hash %s.",
|
||||
name ?: "[none]", verity_hdr->hash_name);
|
||||
|
||||
if (verity_hdr->flags & CRYPT_VERITY_CHECK_HASH) {
|
||||
log_dbg("Verification of data in userspace required.");
|
||||
r = VERITY_verify(cd, verity_hdr,
|
||||
crypt_get_device_name(cd), hash_device,
|
||||
root_hash, root_hash_size);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (!name)
|
||||
return 0;
|
||||
|
||||
dmd.target = DM_VERITY;
|
||||
dmd.data_device = crypt_get_device_name(cd);
|
||||
dmd.u.verity.hash_device = hash_device;
|
||||
dmd.u.verity.root_hash = root_hash;
|
||||
dmd.u.verity.root_hash_size = root_hash_size;
|
||||
dmd.u.verity.hash_offset = VERITY_hash_offset_block(verity_hdr),
|
||||
dmd.flags = activation_flags;
|
||||
dmd.size = verity_hdr->data_size * verity_hdr->data_block_size / 512;
|
||||
dmd.uuid = crypt_get_uuid(cd);
|
||||
dmd.u.verity.vp = verity_hdr;
|
||||
|
||||
r = device_check_and_adjust(cd, dmd.data_device, DEV_EXCL,
|
||||
&dmd.size, &offset, &dmd.flags);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = dm_create_device(name, CRYPT_VERITY, &dmd, 0);
|
||||
if (!r && !(dm_flags() & DM_VERITY_SUPPORTED)) {
|
||||
log_err(cd, _("Kernel doesn't support dm-verity mapping.\n"));
|
||||
return -ENOTSUP;
|
||||
}
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = dm_status_verity_ok(name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!r)
|
||||
log_err(cd, _("Verity device detected corruption after activation.\n"));
|
||||
return 0;
|
||||
}
|
||||
71
lib/verity/verity.h
Normal file
71
lib/verity/verity.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* dm-verity volume handling
|
||||
*
|
||||
* Copyright (C) 2012, Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef _VERITY_H
|
||||
#define _VERITY_H
|
||||
|
||||
#include <unistd.h>
|
||||
#include "config.h"
|
||||
|
||||
#define VERITY_MAX_HASH_TYPE 1
|
||||
#define VERITY_BLOCK_SIZE_OK(x) ((x) % 512 || (x) < 512 || \
|
||||
(x) > (512 * 1024) || (x) & ((x)-1))
|
||||
|
||||
struct crypt_device;
|
||||
struct crypt_params_verity;
|
||||
|
||||
int VERITY_read_sb(struct crypt_device *cd,
|
||||
const char *device,
|
||||
uint64_t sb_offset,
|
||||
char **uuid,
|
||||
struct crypt_params_verity *params);
|
||||
|
||||
int VERITY_write_sb(struct crypt_device *cd,
|
||||
const char *device,
|
||||
uint64_t sb_offset,
|
||||
const char *uuid_string,
|
||||
struct crypt_params_verity *params);
|
||||
|
||||
int VERITY_activate(struct crypt_device *cd,
|
||||
const char *name,
|
||||
const char *hash_device,
|
||||
const char *root_hash,
|
||||
size_t root_hash_size,
|
||||
struct crypt_params_verity *verity_hdr,
|
||||
uint32_t activation_flags);
|
||||
|
||||
int VERITY_verify(struct crypt_device *cd,
|
||||
struct crypt_params_verity *verity_hdr,
|
||||
const char *data_device,
|
||||
const char *hash_device,
|
||||
const char *root_hash,
|
||||
size_t root_hash_size);
|
||||
|
||||
int VERITY_create(struct crypt_device *cd,
|
||||
struct crypt_params_verity *verity_hdr,
|
||||
const char *data_device,
|
||||
const char *hash_device,
|
||||
char *root_hash,
|
||||
size_t root_hash_size);
|
||||
|
||||
uint64_t VERITY_hash_offset_block(struct crypt_params_verity *params);
|
||||
|
||||
int VERITY_UUID_generate(struct crypt_device *cd, char **uuid_string);
|
||||
|
||||
#endif
|
||||
431
lib/verity/verity_hash.c
Normal file
431
lib/verity/verity_hash.c
Normal file
@@ -0,0 +1,431 @@
|
||||
/*
|
||||
* dm-verity volume handling
|
||||
*
|
||||
* Copyright (C) 2012, Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* 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 <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "verity.h"
|
||||
#include "internal.h"
|
||||
|
||||
#define VERITY_MAX_LEVELS 63
|
||||
|
||||
static unsigned get_bits_up(size_t u)
|
||||
{
|
||||
unsigned i = 0;
|
||||
while ((1U << i) < u)
|
||||
i++;
|
||||
return i;
|
||||
}
|
||||
|
||||
static unsigned get_bits_down(size_t u)
|
||||
{
|
||||
unsigned i = 0;
|
||||
while ((u >> i) > 1U)
|
||||
i++;
|
||||
return i;
|
||||
}
|
||||
|
||||
static int verify_zero(struct crypt_device *cd, FILE *wr, size_t bytes)
|
||||
{
|
||||
char block[bytes];
|
||||
size_t i;
|
||||
|
||||
if (fread(block, bytes, 1, wr) != 1) {
|
||||
log_dbg("EIO while reading spare area.");
|
||||
return -EIO;
|
||||
}
|
||||
for (i = 0; i < bytes; i++)
|
||||
if (block[i]) {
|
||||
log_err(cd, _("Spare area is not zeroed at position %" PRIu64 ".\n"),
|
||||
ftello(wr) - bytes);
|
||||
return -EPERM;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int verify_hash_block(const char *hash_name, int version,
|
||||
char *hash, size_t hash_size,
|
||||
const char *data, size_t data_size,
|
||||
const char *salt, size_t salt_size)
|
||||
{
|
||||
struct crypt_hash *ctx = NULL;
|
||||
int r;
|
||||
|
||||
if (crypt_hash_init(&ctx, hash_name))
|
||||
return -EINVAL;
|
||||
|
||||
if (version == 1 && (r = crypt_hash_write(ctx, salt, salt_size)))
|
||||
goto out;
|
||||
|
||||
if ((r = crypt_hash_write(ctx, data, data_size)))
|
||||
goto out;
|
||||
|
||||
if (version == 0 && (r = crypt_hash_write(ctx, salt, salt_size)))
|
||||
goto out;
|
||||
|
||||
r = crypt_hash_final(ctx, hash, hash_size);
|
||||
out:
|
||||
crypt_hash_destroy(ctx);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int mult_overflow(off_t *u, off_t b, size_t size)
|
||||
{
|
||||
*u = (uint64_t)b * size;
|
||||
if ((off_t)(*u / size) != b || (off_t)*u < 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int create_or_verify(struct crypt_device *cd, FILE *rd, FILE *wr,
|
||||
off_t data_block, size_t data_block_size,
|
||||
off_t hash_block, size_t hash_block_size,
|
||||
off_t blocks, int version,
|
||||
const char *hash_name, int verify,
|
||||
char *calculated_digest, size_t digest_size,
|
||||
const char *salt, size_t salt_size)
|
||||
{
|
||||
char left_block[hash_block_size];
|
||||
char data_buffer[data_block_size];
|
||||
char read_digest[digest_size];
|
||||
size_t hash_per_block = 1 << get_bits_down(hash_block_size / digest_size);
|
||||
size_t digest_size_full = 1 << get_bits_up(digest_size);
|
||||
off_t blocks_to_write = (blocks + hash_per_block - 1) / hash_per_block;
|
||||
off_t seek_rd, seek_wr;
|
||||
size_t left_bytes;
|
||||
unsigned i;
|
||||
int r;
|
||||
|
||||
if (mult_overflow(&seek_rd, data_block, data_block_size) ||
|
||||
mult_overflow(&seek_wr, hash_block, hash_block_size)) {
|
||||
log_err(cd, _("Device offset overflow.\n"));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (fseeko(rd, seek_rd, SEEK_SET)) {
|
||||
log_dbg("Cannot seek to requested position in data device.");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (wr && fseeko(wr, seek_wr, SEEK_SET)) {
|
||||
log_dbg("Cannot seek to requested position in hash device.");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
memset(left_block, 0, hash_block_size);
|
||||
while (blocks_to_write--) {
|
||||
left_bytes = hash_block_size;
|
||||
for (i = 0; i < hash_per_block; i++) {
|
||||
if (!blocks)
|
||||
break;
|
||||
blocks--;
|
||||
if (fread(data_buffer, data_block_size, 1, rd) != 1) {
|
||||
log_dbg("Cannot read data device block.");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (verify_hash_block(hash_name, version,
|
||||
calculated_digest, digest_size,
|
||||
data_buffer, data_block_size,
|
||||
salt, salt_size))
|
||||
return -EINVAL;
|
||||
|
||||
if (!wr)
|
||||
break;
|
||||
if (verify) {
|
||||
if (fread(read_digest, digest_size, 1, wr) != 1) {
|
||||
log_dbg("Cannot read digest form hash device.");
|
||||
return -EIO;
|
||||
}
|
||||
if (memcmp(read_digest, calculated_digest, digest_size)) {
|
||||
log_err(cd, _("Verification failed at position %" PRIu64 ".\n"),
|
||||
ftello(rd) - data_block_size);
|
||||
return -EPERM;
|
||||
}
|
||||
} else {
|
||||
if (fwrite(calculated_digest, digest_size, 1, wr) != 1) {
|
||||
log_dbg("Cannot write digest to hash device.");
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
if (version == 0) {
|
||||
left_bytes -= digest_size;
|
||||
} else {
|
||||
if (digest_size_full - digest_size) {
|
||||
if (verify) {
|
||||
r = verify_zero(cd, wr, digest_size_full - digest_size);
|
||||
if (r)
|
||||
return r;
|
||||
} else if (fwrite(left_block, digest_size_full - digest_size, 1, wr) != 1) {
|
||||
log_dbg("Cannot write spare area to hash device.");
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
left_bytes -= digest_size_full;
|
||||
}
|
||||
}
|
||||
if (wr && left_bytes) {
|
||||
if (verify) {
|
||||
r = verify_zero(cd , wr, left_bytes);
|
||||
if (r)
|
||||
return r;
|
||||
} else if (fwrite(left_block, left_bytes, 1, wr) != 1) {
|
||||
log_dbg("Cannot write remaining spare area to hash device.");
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int VERITY_create_or_verify_hash(struct crypt_device *cd,
|
||||
int verify,
|
||||
int version,
|
||||
const char *hash_name,
|
||||
const char *hash_device,
|
||||
const char *data_device,
|
||||
size_t hash_block_size,
|
||||
size_t data_block_size,
|
||||
off_t data_blocks,
|
||||
off_t hash_position,
|
||||
char *root_hash,
|
||||
size_t digest_size,
|
||||
const char *salt,
|
||||
size_t salt_size)
|
||||
{
|
||||
char calculated_digest[digest_size];
|
||||
FILE *data_file = NULL;
|
||||
FILE *hash_file = NULL, *hash_file_2;
|
||||
off_t hash_level_block[VERITY_MAX_LEVELS];
|
||||
off_t hash_level_size[VERITY_MAX_LEVELS];
|
||||
off_t data_file_blocks, s;
|
||||
size_t hash_per_block, hash_per_block_bits;
|
||||
off_t data_device_size = 0, hash_device_size = 0;
|
||||
uint64_t dev_size;
|
||||
int levels, i, r;
|
||||
|
||||
log_dbg("Hash %s %s, data device %s, data blocks %" PRIu64
|
||||
", hash_device %s, offset %" PRIu64 ".",
|
||||
verify ? "verification" : "creation", hash_name,
|
||||
data_device, data_blocks, hash_device, hash_position);
|
||||
|
||||
if (data_blocks < 0 || hash_position < 0) {
|
||||
log_err(cd, _("Invalid size parameters for verity device.\n"));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!data_blocks) {
|
||||
r = device_size(data_device, &dev_size);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
data_file_blocks = dev_size / data_block_size;
|
||||
} else
|
||||
data_file_blocks = data_blocks;
|
||||
|
||||
if (mult_overflow(&data_device_size, data_blocks, data_block_size)) {
|
||||
log_err(cd, _("Device offset overflow.\n"));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
hash_per_block_bits = get_bits_down(hash_block_size / digest_size);
|
||||
hash_per_block = 1 << hash_per_block_bits;
|
||||
if (!hash_per_block_bits)
|
||||
return -EINVAL;
|
||||
|
||||
levels = 0;
|
||||
if (data_file_blocks) {
|
||||
while (hash_per_block_bits * levels < 64 &&
|
||||
(data_file_blocks - 1) >> (hash_per_block_bits * levels))
|
||||
levels++;
|
||||
}
|
||||
log_dbg("Using %d hash levels.", levels);
|
||||
|
||||
if (levels > VERITY_MAX_LEVELS) {
|
||||
log_err(cd, _("Too many tree levels for verity volume.\n"));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = levels - 1; i >= 0; i--) {
|
||||
hash_level_block[i] = hash_position;
|
||||
// verity position of block data_file_blocks at level i
|
||||
s = data_file_blocks >> (i * hash_per_block_bits);
|
||||
s = (s + hash_per_block - 1) / hash_per_block;
|
||||
hash_level_size[i] = s;
|
||||
if (hash_position + s < hash_position ||
|
||||
(hash_position + s) < 0 ||
|
||||
(hash_position + s) != hash_position + s) {
|
||||
log_err(cd, _("Device offset overflow.\n"));
|
||||
return -EINVAL;
|
||||
}
|
||||
hash_position += s;
|
||||
}
|
||||
|
||||
if (mult_overflow(&hash_device_size, hash_position, hash_block_size)) {
|
||||
log_err(cd, _("Device offset overflow.\n"));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
log_dbg("Data device size required: %" PRIu64 " bytes.",
|
||||
data_device_size);
|
||||
data_file = fopen(data_device, "r");
|
||||
if (!data_file) {
|
||||
log_err(cd, _("Cannot open device %s.\n"), data_device);
|
||||
r = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
log_dbg("Hash device size required: %" PRIu64 " bytes.",
|
||||
hash_device_size);
|
||||
hash_file = fopen(hash_device, verify ? "r" : "r+");
|
||||
if (!hash_file) {
|
||||
log_err(cd, _("Cannot open device %s.\n"), hash_device);
|
||||
r = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
memset(calculated_digest, 0, digest_size);
|
||||
|
||||
for (i = 0; i < levels; i++) {
|
||||
if (!i) {
|
||||
r = create_or_verify(cd, data_file, hash_file,
|
||||
0, data_block_size,
|
||||
hash_level_block[i], hash_block_size,
|
||||
data_file_blocks, version, hash_name, verify,
|
||||
calculated_digest, digest_size, salt, salt_size);
|
||||
if (r)
|
||||
goto out;
|
||||
} else {
|
||||
hash_file_2 = fopen(hash_device, "r");
|
||||
if (!hash_file_2) {
|
||||
log_err(cd, _("Cannot open device %s.\n"), hash_device);
|
||||
r = -EIO;
|
||||
goto out;
|
||||
}
|
||||
r = create_or_verify(cd, hash_file_2, hash_file,
|
||||
hash_level_block[i - 1], hash_block_size,
|
||||
hash_level_block[i], hash_block_size,
|
||||
hash_level_size[i - 1], version, hash_name, verify,
|
||||
calculated_digest, digest_size, salt, salt_size);
|
||||
fclose(hash_file_2);
|
||||
if (r)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (levels)
|
||||
r = create_or_verify(cd, hash_file, NULL,
|
||||
hash_level_block[levels - 1], hash_block_size,
|
||||
0, hash_block_size,
|
||||
1, version, hash_name, verify,
|
||||
calculated_digest, digest_size, salt, salt_size);
|
||||
else
|
||||
r = create_or_verify(cd, data_file, NULL,
|
||||
0, data_block_size,
|
||||
0, hash_block_size,
|
||||
data_file_blocks, version, hash_name, verify,
|
||||
calculated_digest, digest_size, salt, salt_size);
|
||||
out:
|
||||
if (verify) {
|
||||
if (r)
|
||||
log_err(cd, _("Verification of data area failed.\n"));
|
||||
else {
|
||||
log_dbg("Verification of data area succeeded.");
|
||||
r = memcmp(root_hash, calculated_digest, digest_size) ? -EPERM : 0;
|
||||
if (r)
|
||||
log_err(cd, _("Verification of root hash failed.\n"));
|
||||
else
|
||||
log_dbg("Verification of root hash succeeded.");
|
||||
}
|
||||
} else {
|
||||
if (r == -EIO)
|
||||
log_err(cd, _("Input/output error while creating hash area.\n"));
|
||||
else if (r)
|
||||
log_err(cd, _("Creation of hash area failed.\n"));
|
||||
else {
|
||||
fsync(fileno(hash_file));
|
||||
memcpy(root_hash, calculated_digest, digest_size);
|
||||
}
|
||||
}
|
||||
|
||||
if (data_file)
|
||||
fclose(data_file);
|
||||
if (hash_file)
|
||||
fclose(hash_file);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Verify verity device using userspace crypto backend */
|
||||
int VERITY_verify(struct crypt_device *cd,
|
||||
struct crypt_params_verity *verity_hdr,
|
||||
const char *data_device,
|
||||
const char *hash_device,
|
||||
const char *root_hash,
|
||||
size_t root_hash_size)
|
||||
{
|
||||
return VERITY_create_or_verify_hash(cd, 1,
|
||||
verity_hdr->hash_type,
|
||||
verity_hdr->hash_name,
|
||||
hash_device,
|
||||
data_device,
|
||||
verity_hdr->hash_block_size,
|
||||
verity_hdr->data_block_size,
|
||||
verity_hdr->data_size,
|
||||
VERITY_hash_offset_block(verity_hdr),
|
||||
CONST_CAST(char*)root_hash,
|
||||
root_hash_size,
|
||||
verity_hdr->salt,
|
||||
verity_hdr->salt_size);
|
||||
}
|
||||
|
||||
/* Create verity hash */
|
||||
int VERITY_create(struct crypt_device *cd,
|
||||
struct crypt_params_verity *verity_hdr,
|
||||
const char *data_device,
|
||||
const char *hash_device,
|
||||
char *root_hash,
|
||||
size_t root_hash_size)
|
||||
{
|
||||
unsigned pgsize = crypt_getpagesize();
|
||||
|
||||
if (verity_hdr->salt_size > 256)
|
||||
return -EINVAL;
|
||||
|
||||
if (verity_hdr->data_block_size > pgsize)
|
||||
log_err(cd, _("WARNING: Kernel cannot activate device if data "
|
||||
"block size exceeds page size (%u).\n"), pgsize);
|
||||
|
||||
return VERITY_create_or_verify_hash(cd, 0,
|
||||
verity_hdr->hash_type,
|
||||
verity_hdr->hash_name,
|
||||
hash_device,
|
||||
data_device,
|
||||
verity_hdr->hash_block_size,
|
||||
verity_hdr->data_block_size,
|
||||
verity_hdr->data_size,
|
||||
VERITY_hash_offset_block(verity_hdr),
|
||||
root_hash,
|
||||
root_hash_size,
|
||||
verity_hdr->salt,
|
||||
verity_hdr->salt_size);
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
* cryptsetup volume key implementation
|
||||
*
|
||||
* Copyright (C) 2004-2006, Clemens Fruhwirth <clemens@endorphin.org>
|
||||
* Copyright (C) 2010-2011, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2010-2012, Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -15,7 +15,7 @@
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
@@ -33,6 +33,8 @@ struct volume_key *crypt_alloc_volume_key(unsigned keylength, const char *key)
|
||||
vk->keylength = keylength;
|
||||
if (key)
|
||||
memcpy(&vk->key, key, keylength);
|
||||
else
|
||||
memset(&vk->key, 0, keylength);
|
||||
|
||||
return vk;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
man8_MANS = cryptsetup.8
|
||||
|
||||
EXTRA_DIST = cryptsetup.8
|
||||
if VERITYSETUP
|
||||
man8_MANS += veritysetup.8
|
||||
endif
|
||||
|
||||
if REENCRYPT
|
||||
man8_MANS += cryptsetup-reencrypt.8
|
||||
endif
|
||||
|
||||
EXTRA_DIST = cryptsetup.8 veritysetup.8 cryptsetup-reencrypt.8
|
||||
|
||||
210
man/cryptsetup-reencrypt.8
Normal file
210
man/cryptsetup-reencrypt.8
Normal file
@@ -0,0 +1,210 @@
|
||||
.TH CRYPTSETUP-REENCRYPT "8" "June 2012" "cryptsetup-reencrypt" "Maintenance Commands"
|
||||
.SH NAME
|
||||
cryptsetup-reencrypt - tool for offline LUKS device re-encryption
|
||||
.SH SYNOPSIS
|
||||
.B cryptsetup-reencrypt <options> <device>
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
Cryptsetup-reencrypt can be used to change reencryption parameters
|
||||
which otherwise require full on-disk data change (re-encryption).
|
||||
|
||||
You can regenerate \fBvolume key\fR (the real key used in on-disk encryption
|
||||
unclocked by passphrase), \fBcipher\fR, \fBcipher mode\fR.
|
||||
|
||||
Cryptsetup-reencrypt reencrypts data on LUKS device in-place. During
|
||||
reencryption process the LUKS device is marked unavailable.
|
||||
|
||||
\fIWARNING\fR: The cryptsetup-reencrypt program is not resistant to hardware
|
||||
or kernel failures during reencryption (you can lose you data in this case).
|
||||
|
||||
\fIALWAYS BE SURE YOU HAVE RELIABLE BACKUP BEFORE USING THIS TOOL.\fR
|
||||
.br
|
||||
\fITHIS TOOL IS EXPERIMENTAL.\fR
|
||||
|
||||
The reencryption can be temporarily suspended (by TERM signal or by
|
||||
using ctrl+c) but you need to retain temporary files named LUKS-<uuid>.[log|org|new].
|
||||
LUKS device is unavailable until reencryption is finished though.
|
||||
|
||||
Current working directory must by writable and temporary
|
||||
files created during reencryption must be present.
|
||||
|
||||
For more info about LUKS see cryptsetup(8).
|
||||
.PP
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
To start (or continue) re-encryption for <device> use:
|
||||
.PP
|
||||
\fIcryptsetup-reencrypt\fR <device>
|
||||
|
||||
\fB<options>\fR can be [\-\-block-size, \-\-cipher, \-\-hash, \-\-iter-time,
|
||||
\-\-use-random | \-\-use-urandom, \-\-key-file, \-\-key-slot, \-\-keyfile-offset,
|
||||
\-\-keyfile-size, \-\-tries, \-\-use-directio, \-\-use-fsync, \-\-write-log]
|
||||
|
||||
For detailed description of encryption and key file options see \fIcryptsetup(8)\fR
|
||||
man page.
|
||||
.TP
|
||||
.B "\-\-verbose, \-v"
|
||||
Print more information on command execution.
|
||||
.TP
|
||||
.B "\-\-debug"
|
||||
Run in debug mode with full diagnostic logs. Debug output
|
||||
lines are always prefixed by '#'.
|
||||
.TP
|
||||
.B "\-\-cipher, \-c" \fI<cipher-spec>\fR
|
||||
Set the cipher specification string.
|
||||
.TP
|
||||
.B "\-\-key-size, \-s \fI<bits>\fR"
|
||||
Set key size in bits. The argument has to be a multiple of 8.
|
||||
|
||||
The possible key-sizes are limited by the cipher and mode used.
|
||||
|
||||
If you are increasing key size, there must be enough space in the LUKS header
|
||||
for enlarged keyslots (data offset must be large enough) or reencryption
|
||||
cannot be performed.
|
||||
|
||||
If there is not enough space for keyslots with new key size,
|
||||
you can destructively shrink device with \-\-reduce-device-size option.
|
||||
.TP
|
||||
.B "\-\-hash, \-h \fI<hash-spec>\fR"
|
||||
Specifies the hash used in the LUKS key setup scheme and volume key digest.
|
||||
.TP
|
||||
.B "\-\-iter-time, \-i \fI<milliseconds>\fR"
|
||||
The number of milliseconds to spend with PBKDF2 passphrase processing for the
|
||||
new LUKS header.
|
||||
.TP
|
||||
.B "\-\-use-random"
|
||||
.TP
|
||||
.B "\-\-use-urandom"
|
||||
Define which kernel random number generator will be used to create the volume key.
|
||||
.TP
|
||||
.B "\-\-key-file, \-d \fIname\fR"
|
||||
Read the passphrase from file.
|
||||
|
||||
WARNING: \-\-key-file option can be used only if there only one active keyslot,
|
||||
or alternatively, also if \-\-key-slot option is specified (then all other keyslots
|
||||
will be disabled in new LUKS device).
|
||||
|
||||
If this option is not used, cryptsetup-reencrypt will ask for all active keyslot
|
||||
passphrases.
|
||||
.TP
|
||||
.B "\-\-key-slot, \-S <0-7>"
|
||||
Specify which key slot is used.
|
||||
|
||||
WARNING: All other keyslots will be disabled if this option is used.
|
||||
.TP
|
||||
.B "\-\-keyfile-offset \fIvalue\fR"
|
||||
Skip \fIvalue\fR bytes at the beginning of the key file.
|
||||
.TP
|
||||
.B "\-\-keyfile-size, \-l"
|
||||
Read a maximum of \fIvalue\fR bytes from the key file.
|
||||
Default is to read the whole file up to the compiled-in
|
||||
maximum.
|
||||
.TP
|
||||
.B "\-\-tries, \-T"
|
||||
Number of retries for invalid passphrase entry.
|
||||
.TP
|
||||
.B "\-\-block-size, \-B \fIvalue\fR"
|
||||
Use re-encryption block size of <value> in MiB.
|
||||
|
||||
Values can be between 1 and 64 MiB.
|
||||
.TP
|
||||
.B "\-\-device-size \fIsize[units]\fR"
|
||||
Instead of real device size, use specified value.
|
||||
|
||||
It means that only specified area (from the start of the device
|
||||
to the specified size) will be reencrypted.
|
||||
|
||||
WARNING: This is destructive operation.
|
||||
|
||||
If no unit suffix is specified, the size is in bytes.
|
||||
|
||||
Unit suffix can be S for 512 byte sectors, K/M/G/T (or KiB,MiB,GiB,TiB)
|
||||
for units with 1024 base or KB/MB/GB/TB for 1000 base (SI scale).
|
||||
|
||||
WARNING: This is destructive operation.
|
||||
.TP
|
||||
.B "\-\-reduce-device-size \fIsize[units]\fR"
|
||||
Enlarge data offset to specified value by shrinking device size.
|
||||
|
||||
This means that last sectors on the original device will be lost,
|
||||
ciphertext data will be effectively shifted by specified
|
||||
number of sectors.
|
||||
|
||||
It can be usefull if you e.g. added some space to underlying
|
||||
partition (so last sectors contains no data).
|
||||
|
||||
For units suffix see \-\-device-size parameter description.
|
||||
|
||||
WARNING: This is destructive operation and cannot be reverted.
|
||||
Use with extreme care - shrinked filesystems are usually unrecoverable.
|
||||
|
||||
You cannot shrink device more than by 64 MiB (131072 sectors).
|
||||
.TP
|
||||
.B "\-\-new, N"
|
||||
Create new header (encrypt not yet encrypted device).
|
||||
|
||||
This option must be used together with \-\-reduce-device-size.
|
||||
|
||||
WARNING: This is destructive operation and cannot be reverted.
|
||||
|
||||
.TP
|
||||
.B "\-\-use-directio"
|
||||
Use direct-io (O_DIRECT) for all read/write data operations.
|
||||
|
||||
Usefull if direct-io operations perform better than normal buffered
|
||||
operations (e.g. in virtual environments).
|
||||
.TP
|
||||
.B "\-\-use-fsync"
|
||||
Use fsync call after every written block.
|
||||
.TP
|
||||
.B "\-\-write-log"
|
||||
Update log file after every block write. This can slow down reencryption
|
||||
but will minimize data loss in the case of system crash.
|
||||
.TP
|
||||
.B "\-\-batch-mode, \-q"
|
||||
Suppresses all warnings and reencryption progress output.
|
||||
.TP
|
||||
.B "\-\-version"
|
||||
Show the program version.
|
||||
.SH RETURN CODES
|
||||
Cryptsetup-reencrypt returns 0 on success and a non-zero value on error.
|
||||
|
||||
Error codes are: 1 wrong parameters, 2 no permission,
|
||||
3 out of memory, 4 wrong device specified, 5 device already exists
|
||||
or device is busy.
|
||||
.SH EXAMPLES
|
||||
.TP
|
||||
Reencrypt /dev/sdb1 (change volume key)
|
||||
cryptsetup-reencrypt /dev/sdb1
|
||||
.TP
|
||||
Reencrypt and also change cipher and cipher mode
|
||||
cryptsetup-reencrypt /dev/sdb1 -c aes-xts-plain64
|
||||
.TP
|
||||
Add LUKS encryption to not yet encrypted device
|
||||
|
||||
First, be sure you have space added to disk.
|
||||
Or alternatively shrink filesystem in advance.
|
||||
.br
|
||||
Here we need 4096 512-bytes sectors (enough for 2x128 bit key).
|
||||
|
||||
fdisk -u /dev/sdb # move sdb1 partition end + 4096 sectors
|
||||
|
||||
cryptsetup-reencrypt /dev/sdb1 --new --reduce-device-size 4096
|
||||
|
||||
.SH REPORTING BUGS
|
||||
Report bugs, including ones in the documentation, on
|
||||
the cryptsetup mailing list at <dm-crypt@saout.de>
|
||||
or in the 'Issues' section on LUKS website.
|
||||
Please attach the output of the failed command with the
|
||||
\-\-debug option added.
|
||||
.SH AUTHORS
|
||||
Cryptsetup-reencrypt was written by Milan Broz <gmazyland@gmail.com>.
|
||||
.SH COPYRIGHT
|
||||
Copyright \(co 2012 Milan Broz
|
||||
.br
|
||||
Copyright \(co 2012 Red Hat, Inc.
|
||||
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
.SH SEE ALSO
|
||||
The project website at \fBhttp://code.google.com/p/cryptsetup/\fR
|
||||
894
man/cryptsetup.8
894
man/cryptsetup.8
File diff suppressed because it is too large
Load Diff
142
man/veritysetup.8
Normal file
142
man/veritysetup.8
Normal file
@@ -0,0 +1,142 @@
|
||||
.TH VERITYSETUP "8" "June 2012" "veritysetup" "Maintenance Commands"
|
||||
.SH NAME
|
||||
veritysetup - manage dm-verity (block level verification) volumes
|
||||
.SH SYNOPSIS
|
||||
.B veritysetup <options> <action> <action args>
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
Veritysetup is used to configure dm-verity managed device-mapper mappings.
|
||||
|
||||
Device-mapper verity target provides read-only transparent integrity
|
||||
checking of block devices using kernel crypto API.
|
||||
|
||||
The dm-verity devices are always read-only.
|
||||
|
||||
Veritysetup supports these operations:
|
||||
.PP
|
||||
\fIformat\fR <data_device> <hash_device>
|
||||
.IP
|
||||
Calculates and permanently stores hash verification data for data_device.
|
||||
Hash area can be located on the same device after data if specified
|
||||
by \-\-hash\-offset option.
|
||||
|
||||
Note you need to provide root hash string for device verification
|
||||
or activation. Root hash must be trusted.
|
||||
|
||||
If data or hash device argument points to regular file, veritysetup
|
||||
allocates loopback device. In this case, hash file size must be enough
|
||||
to store the hash area.
|
||||
|
||||
\fB<options>\fR can be [\-\-hash, \-\-no-superblock, \-\-format,
|
||||
\-\-data-block-size, \-\-hash-block-size, \-\-data-blocks, \-\-hash-offset,
|
||||
\-\-salt, \-\-uuid]
|
||||
.PP
|
||||
\fIcreate\fR <name> <data_device> <hash_device> <root_hash>
|
||||
.IP
|
||||
Creates a mapping with <name> backed by device <data_device> and using
|
||||
<hash_device> for in-kernel verification.
|
||||
|
||||
The <root_hash> is a hexadecimal string.
|
||||
|
||||
\fB<options>\fR can be [\-\-hash-offset, \-\-no-superblock]
|
||||
|
||||
If option \-\-no-superblock is used, you have to use as the same options
|
||||
as in initial format operation.
|
||||
.PP
|
||||
\fIverify\fR <data_device> <hash_device> <root_hash>
|
||||
.IP
|
||||
Verifies data on data_device with use of hash blocks stored on hash_device.
|
||||
|
||||
This command performs userspace verification, no kernel device is created.
|
||||
|
||||
The <root_hash> is a hexadecimal string.
|
||||
|
||||
\fB<options>\fR can be [\-\-hash-offset, \-\-no-superblock]
|
||||
|
||||
If option \-\-no-superblock is used, you have to use as the same options
|
||||
as in initial format operation.
|
||||
.PP
|
||||
\fIremove\fR <name>
|
||||
.IP
|
||||
Removes existing mapping <name>.
|
||||
.PP
|
||||
\fIstatus\fR <name>
|
||||
.IP
|
||||
Reports status for the active verity mapping <name>.
|
||||
.PP
|
||||
\fIdump\fR <hash_device>
|
||||
.IP
|
||||
Reports parameters of verity device from on-disk stored superblock.
|
||||
|
||||
\fB<options>\fR can be [\-\-no-superblock]
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.B "\-\-verbose, \-v"
|
||||
Print more information on command execution.
|
||||
.TP
|
||||
.B "\-\-debug"
|
||||
Run in debug mode with full diagnostic logs. Debug output
|
||||
lines are always prefixed by '#'.
|
||||
.TP
|
||||
.B "\-\-no-superblock"
|
||||
Create or use dm-verity without permanent on-disk superblock.
|
||||
.TP
|
||||
.B "\-\-format=number"
|
||||
Specifies the hash version type.
|
||||
Format type 0 is original Chrome OS verion. Format type 1 is current version.
|
||||
.TP
|
||||
.B "\-\-data-block-size=bytes"
|
||||
Used block size for the data device.
|
||||
(Note kernel supports only page-size as maximum here.)
|
||||
.TP
|
||||
.B "\-\-hash-block-size=bytes"
|
||||
Used block size for the hash device.
|
||||
(Note kernel supports only page-size as maximum here.)
|
||||
.TP
|
||||
.B "\-\-data-blocks=blocks"
|
||||
Size of data device used in verification.
|
||||
If not specified, the whole device is used.
|
||||
.TP
|
||||
.B "\-\-hash-offset=bytes"
|
||||
Offset of hash area/superblock on hash_device.
|
||||
Value must be aligned to disk sector offset.
|
||||
.TP
|
||||
.B "\-\-salt=hex string"
|
||||
Salt used for format or verification.
|
||||
Format is a hexadecimal string.
|
||||
.TP
|
||||
.B "\-\-uuid=UUID"
|
||||
Use the provided UUID for format command instead of generating new one.
|
||||
|
||||
The UUID must be provided in standard UUID format,
|
||||
e.g. 12345678-1234-1234-1234-123456789abc.
|
||||
.TP
|
||||
.B "\-\-version"
|
||||
Show the program version.
|
||||
.SH RETURN CODES
|
||||
Veritysetup returns 0 on success and a non-zero value on error.
|
||||
|
||||
Error codes are: 1 wrong parameters, 2 no permission,
|
||||
3 out of memory, 4 wrong device specified, 5 device already exists
|
||||
or device is busy.
|
||||
.SH REPORTING BUGS
|
||||
Report bugs, including ones in the documentation, on
|
||||
the cryptsetup mailing list at <dm-crypt@saout.de>
|
||||
or in the 'Issues' section on LUKS website.
|
||||
Please attach the output of the failed command with the
|
||||
\-\-debug option added.
|
||||
.SH AUTHORS
|
||||
The first implementation of veritysetup was written by Chrome OS authors.
|
||||
|
||||
This version is based on verification code written by Mikulas Patocka <mpatocka@redhat.com>
|
||||
and rewritten for libcryptsetup by Milan Broz <gmazyland@gmail.com>.
|
||||
.SH COPYRIGHT
|
||||
Copyright \(co 2012 Red Hat, Inc.
|
||||
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
.SH SEE ALSO
|
||||
The project website at \fBhttp://code.google.com/p/cryptsetup/\fR
|
||||
|
||||
The verity on-disk format specification available at
|
||||
\fBhttp://code.google.com/p/cryptsetup/wiki/DMVerity\fR
|
||||
23
misc/dracut_90reencrypt/README
Normal file
23
misc/dracut_90reencrypt/README
Normal file
@@ -0,0 +1,23 @@
|
||||
Example of simple dracut module for reencryption of system
|
||||
LUKS drive on-the-fly.
|
||||
|
||||
Install in /usr/[share|lib]/dracut/modules.d/90reencrypt, then
|
||||
rebuild intramfs "with dracut -f -a reencrypt".
|
||||
|
||||
Dracut then recognize argument rd_REENCRYPT=name:size,
|
||||
e.g. rd_REENCRYPT=sda2:52G means only 52G of device
|
||||
will be reencrypted (default is whole device).
|
||||
(Name is kernel name of device.)
|
||||
|
||||
Note that reencryption context is stored in ramdisk, any
|
||||
fail can mean complete lost of data!
|
||||
|
||||
Copyright (C) 2012 Milan Broz <asi@ucw.cz>
|
||||
|
||||
This copyrighted material is made available to anyone wishing to use,
|
||||
modify, copy, or redistribute it subject to the terms and conditions
|
||||
of the GNU General Public License v.2.
|
||||
|
||||
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.
|
||||
5
misc/dracut_90reencrypt/check.old
Executable file
5
misc/dracut_90reencrypt/check.old
Executable file
@@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
which cryptsetup-reencrypt >/dev/null 2>&1 || exit 1
|
||||
|
||||
exit 0
|
||||
6
misc/dracut_90reencrypt/install.old
Executable file
6
misc/dracut_90reencrypt/install.old
Executable file
@@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
inst cryptsetup-reencrypt
|
||||
|
||||
inst_hook cmdline 30 "$moddir/parse-reencrypt.sh"
|
||||
inst "$moddir"/reencrypt.sh /sbin/reencrypt
|
||||
22
misc/dracut_90reencrypt/module-setup.sh
Executable file
22
misc/dracut_90reencrypt/module-setup.sh
Executable file
@@ -0,0 +1,22 @@
|
||||
#!/bin/bash
|
||||
|
||||
check() {
|
||||
[ -x /sbin/cryptsetup-reencrypt ] || return 1
|
||||
return 255
|
||||
}
|
||||
|
||||
depends() {
|
||||
echo dm rootfs-block
|
||||
return 0
|
||||
}
|
||||
|
||||
installkernel() {
|
||||
instmods dm_crypt =crypto
|
||||
}
|
||||
|
||||
install() {
|
||||
dracut_install cryptsetup-reencrypt
|
||||
|
||||
inst_hook cmdline 30 "$moddir/parse-reencrypt.sh"
|
||||
inst_simple "$moddir"/reencrypt.sh /sbin/reencrypt
|
||||
}
|
||||
17
misc/dracut_90reencrypt/parse-reencrypt.sh
Executable file
17
misc/dracut_90reencrypt/parse-reencrypt.sh
Executable file
@@ -0,0 +1,17 @@
|
||||
#!/bin/sh
|
||||
|
||||
REENC=$(getargs rd_REENCRYPT=)
|
||||
REENC_DEV=$(echo $REENC | sed 's/:.*//')
|
||||
REENC_SIZE=$(echo $REENC | sed -n 's/.*://p')
|
||||
|
||||
if [ -n "$REENC_DEV" ] ; then
|
||||
{
|
||||
printf 'SUBSYSTEM!="block", GOTO="reenc_end"\n'
|
||||
printf 'ACTION!="add|change", GOTO="reenc_end"\n'
|
||||
printf 'KERNEL!="%s", GOTO="reenc_end"\n' $REENC_DEV
|
||||
printf 'ENV{ID_FS_TYPE}=="crypto_LUKS", RUN+="/sbin/initqueue \
|
||||
--unique --onetime --name crypt-reencrypt-%%k \
|
||||
/sbin/reencrypt $env{DEVNAME} %s"\n' "$REENC_SIZE"
|
||||
printf 'LABEL="reenc_end"\n'
|
||||
} > /etc/udev/rules.d/69-reencryption.rules
|
||||
fi
|
||||
34
misc/dracut_90reencrypt/reencrypt.sh
Executable file
34
misc/dracut_90reencrypt/reencrypt.sh
Executable file
@@ -0,0 +1,34 @@
|
||||
#!/bin/sh
|
||||
|
||||
[ -d /sys/module/dm_crypt ] || modprobe dm_crypt
|
||||
|
||||
[ -f /tmp/reencrypted ] && exit 0
|
||||
|
||||
. /lib/dracut-lib.sh
|
||||
|
||||
# if device name is /dev/dm-X, convert to /dev/mapper/name
|
||||
if [ "${1##/dev/dm-}" != "$1" ]; then
|
||||
device="/dev/mapper/$(dmsetup info -c --noheadings -o name "$1")"
|
||||
else
|
||||
device="$1"
|
||||
fi
|
||||
|
||||
PARAMS="$device -T 1 --use-fsync -B 32"
|
||||
if [ -n "$2" ]; then
|
||||
PARAMS="$PARAMS --device-size $2"
|
||||
fi
|
||||
|
||||
info "REENCRYPT $device requested"
|
||||
# flock against other interactive activities
|
||||
{ flock -s 9;
|
||||
CURR=$(pwd)
|
||||
cd /tmp
|
||||
/bin/plymouth ask-for-password --prompt "LUKS password for REENCRYPTING $device" \
|
||||
--command="/sbin/cryptsetup-reencrypt $PARAMS"
|
||||
cd $CURR
|
||||
} 9>/.console.lock
|
||||
|
||||
# do not ask again
|
||||
>> /tmp/reencrypted
|
||||
|
||||
exit 0
|
||||
59
misc/luks-header-from-active
Executable file
59
misc/luks-header-from-active
Executable file
@@ -0,0 +1,59 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Try to get LUKS info and master key from active mapping and prepare parameters for cryptsetup.
|
||||
#
|
||||
# Copyright (C) 2010,2011,2012 Milan Broz <asi@ucw.cz>
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
umask 0077
|
||||
|
||||
fail() { echo -e $1 ; exit 1 ; }
|
||||
field() { echo $(dmsetup table --target crypt --showkeys $DEVICE | sed 's/.*: //' | cut -d' ' -f$1) ; }
|
||||
field_uuid() { echo $(dmsetup info $1 --noheadings -c -o uuid) ; }
|
||||
field_device() {
|
||||
TEMP=$(readlink /sys/dev/block/$1 | sed -e 's/.*\///')
|
||||
if [ ${TEMP:0:3} = "dm-" -a -e /sys/block/$TEMP/dm/name ] ; then
|
||||
TEMP=/dev/mapper/$(cat /sys/block/$TEMP/dm/name)
|
||||
else
|
||||
TEMP=/dev/$TEMP
|
||||
fi
|
||||
echo $TEMP
|
||||
}
|
||||
|
||||
which readlink >/dev/null || fail "You need readlink (part of coreutils package)."
|
||||
which xxd >/dev/null || fail "You need xxd (part of vim package) installed to convert key."
|
||||
|
||||
[ -z "$2" ] && fail "Recover LUKS header from active mapping, use:\n $0 crypt_mapped_device mk_file_name"
|
||||
|
||||
DEVICE=$1
|
||||
MK_FILE=$2
|
||||
|
||||
[ -z "$(field 4)" ] && fail "Mapping $1 not active or it is not crypt target."
|
||||
|
||||
CIPHER=$(field 4)
|
||||
OFFSET=$(field 8)
|
||||
SYS_DEVICE=$(field 7)
|
||||
REAL_DEVICE=$(field_device $SYS_DEVICE)
|
||||
KEY=$(field 5)
|
||||
KEY_SIZE=$(( ${#KEY} / 2 * 8 ))
|
||||
SYS_UUID=$(field_uuid $DEVICE)
|
||||
UUID="${SYS_UUID:12:8}-${SYS_UUID:20:4}-${SYS_UUID:24:4}-${SYS_UUID:28:4}-${SYS_UUID:32:12}"
|
||||
|
||||
#echo "CIPHER=$CIPHER OFFSET=$OFFSET SYS_DEVICE=$SYS_DEVICE REAL_DEVICE=$REAL_DEVICE KEY_SIZE=$KEY_SIZE KEY=$KEY UUID=$UUID SYS_UUID=$SYS_UUID"
|
||||
|
||||
[ -z "$CIPHER" -o -z "$OFFSET" -o "$OFFSET" -le 383 -o \
|
||||
-z "$KEY" -o -z "$UUID" -o -z "$REAL_DEVICE" -o "${SYS_UUID:0:12}" != "CRYPT-LUKS1-" ] && \
|
||||
fail "Incompatible device, sorry."
|
||||
|
||||
echo "Generating master key to file $MK_FILE."
|
||||
echo -E -n $KEY| xxd -r -p >$MK_FILE
|
||||
|
||||
echo "You can now try to reformat LUKS device using:"
|
||||
echo " cryptsetup luksFormat -c $CIPHER -s $KEY_SIZE --align-payload=$OFFSET --master-key-file=$MK_FILE --uuid=$UUID $REAL_DEVICE"
|
||||
@@ -1,9 +1,11 @@
|
||||
cs
|
||||
de
|
||||
fi
|
||||
fr
|
||||
id
|
||||
it
|
||||
nl
|
||||
pl
|
||||
sv
|
||||
uk
|
||||
vi
|
||||
|
||||
@@ -5,10 +5,14 @@ lib/utils.c
|
||||
lib/crypt_plain.c
|
||||
lib/utils_crypt.c
|
||||
lib/utils_loop.c
|
||||
lib/utils_debug.c
|
||||
lib/utils_fips.c
|
||||
lib/luks1/af.c
|
||||
lib/luks1/keyencryption.c
|
||||
lib/luks1/keymanage.c
|
||||
lib/luks1/pbkdf.c
|
||||
lib/loopaes/loopaes.c
|
||||
lib/verity/verity.c
|
||||
lib/verity/verity_hash.c
|
||||
src/cryptsetup.c
|
||||
src/veritysetup.c
|
||||
src/cryptsetup_reencrypt.c
|
||||
|
||||
16
python/Makefile.am
Normal file
16
python/Makefile.am
Normal file
@@ -0,0 +1,16 @@
|
||||
INCLUDES = -I$(top_srcdir)/lib $(PYTHON_INCLUDES)
|
||||
EXTRA_DIST = pycryptsetup-test.py
|
||||
CLEANFILES = *.img
|
||||
|
||||
if PYTHON_CRYPTSETUP
|
||||
TESTS = pycryptsetup-test.py
|
||||
|
||||
pyexec_LTLIBRARIES = pycryptsetup.la
|
||||
|
||||
pycryptsetup_la_SOURCES = pycryptsetup.c
|
||||
pycryptsetup_la_CPPFLAGS = $(AM_CPPFLAGS) $(PYTHON_CPPFLAGS) -fno-strict-aliasing
|
||||
pycryptsetup_la_LDFLAGS = -avoid-version -module
|
||||
pycryptsetup_la_LIBADD = $(top_builddir)/lib/libcryptsetup.la -lpython$(PYTHON_VERSION)
|
||||
else
|
||||
all:
|
||||
endif
|
||||
131
python/pycryptsetup-test.py
Executable file
131
python/pycryptsetup-test.py
Executable file
@@ -0,0 +1,131 @@
|
||||
#!/usr/bin/python
|
||||
#
|
||||
# Python bindings to libcryptsetup test
|
||||
#
|
||||
# Copyright (C) 2011, 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.
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
sys.path.insert(0, ".libs")
|
||||
import pycryptsetup
|
||||
|
||||
IMG = "test.img"
|
||||
PASSWORD = "password"
|
||||
PASSWORD2 = "password2"
|
||||
DEVICE = "pycryptsetup_test_dev"
|
||||
|
||||
def log(level, txt):
|
||||
if level == pycryptsetup.CRYPT_LOG_ERROR:
|
||||
print txt,
|
||||
return
|
||||
|
||||
def askyes(txt):
|
||||
print "Question:", txt
|
||||
return 1
|
||||
|
||||
def askpassword(txt):
|
||||
return PASSWORD
|
||||
|
||||
def print_status(c):
|
||||
r = c.status()
|
||||
print "status :",
|
||||
if r == pycryptsetup.CRYPT_ACTIVE:
|
||||
print "ACTIVE"
|
||||
elif r == pycryptsetup.CRYPT_INACTIVE:
|
||||
print "INACTIVE"
|
||||
else:
|
||||
print "ERROR"
|
||||
return
|
||||
|
||||
if os.geteuid() != 0:
|
||||
print "WARNING: You must be root to run this test, test skipped."
|
||||
sys.exit(0)
|
||||
|
||||
os.system("dd if=/dev/zero of=" + IMG + " bs=1M count=32 >/dev/null 2>&1")
|
||||
|
||||
c = pycryptsetup.CryptSetup(
|
||||
device = IMG,
|
||||
name = DEVICE,
|
||||
yesDialog = askyes,
|
||||
logFunc = log,
|
||||
passwordDialog = askpassword)
|
||||
|
||||
#c.debugLevel(pycryptsetup.CRYPT_DEBUG_ALL);
|
||||
c.debugLevel(pycryptsetup.CRYPT_DEBUG_NONE);
|
||||
c.iterationTime(1)
|
||||
r = c.isLuks()
|
||||
print "isLuks :", r
|
||||
c.askyes(message = "Is there anybody out there?")
|
||||
c.log(priority = pycryptsetup.CRYPT_LOG_ERROR, message = "Nobody there...\n")
|
||||
c.luksFormat(cipher = "aes", cipherMode= "xts-plain64", keysize = 512)
|
||||
print "isLuks :", c.isLuks()
|
||||
print "luksUUID:", c.luksUUID()
|
||||
print "addKeyVK:", c.addKeyByVolumeKey(newPassphrase = PASSWORD, slot = 2)
|
||||
print "addKeyP :", c.addKeyByPassphrase(passphrase = PASSWORD,
|
||||
newPassphrase = PASSWORD2, slot = 3)
|
||||
print "removeP :", c.removePassphrase(passphrase = PASSWORD2)
|
||||
print "addKeyP :", c.addKeyByPassphrase(PASSWORD, PASSWORD2)
|
||||
# original api required wrong passphrase parameter here
|
||||
# print "killSlot:", c.killSlot(passphrase = "xxx", slot = 0)
|
||||
print "killSlot:", c.killSlot(slot = 0)
|
||||
print "activate:", c.activate(name = DEVICE, passphrase = PASSWORD)
|
||||
print "suspend :", c.suspend()
|
||||
# os.system("dmsetup info -c " + DEVICE)
|
||||
print "resume :", c.resume(passphrase = PASSWORD)
|
||||
print_status(c)
|
||||
info = c.info()
|
||||
print "cipher :", info["cipher"]
|
||||
print "cmode :", info["cipher_mode"]
|
||||
print "keysize :", info["keysize"]
|
||||
print "dir :", info["dir"]
|
||||
print "device :", info["device"]
|
||||
print "offset :", info["offset"]
|
||||
print "name :", info["name"]
|
||||
print "uuid :", info["uuid"]
|
||||
# os.system("cryptsetup luksDump " + info["device"])
|
||||
print "deact. :", c.deactivate()
|
||||
|
||||
del c
|
||||
|
||||
c = pycryptsetup.CryptSetup(
|
||||
device = IMG,
|
||||
name = DEVICE,
|
||||
yesDialog = askyes,
|
||||
logFunc = log,
|
||||
passwordDialog = askpassword)
|
||||
|
||||
print "activate:", c.activate(name = DEVICE, passphrase = PASSWORD)
|
||||
|
||||
c2 = pycryptsetup.CryptSetup(
|
||||
name = DEVICE,
|
||||
yesDialog = askyes,
|
||||
logFunc = log,
|
||||
passwordDialog = askpassword)
|
||||
|
||||
info = c2.info()
|
||||
print "cipher :", info["cipher"]
|
||||
print "cmode :", info["cipher_mode"]
|
||||
print "keysize :", info["keysize"]
|
||||
|
||||
print "deact. :", c.deactivate()
|
||||
r = c2.deactivate()
|
||||
print "deact. :", r
|
||||
del c
|
||||
del c2
|
||||
|
||||
os.remove(IMG)
|
||||
713
python/pycryptsetup.c
Normal file
713
python/pycryptsetup.c
Normal file
@@ -0,0 +1,713 @@
|
||||
/*
|
||||
* Python bindings to libcryptsetup
|
||||
*
|
||||
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
|
||||
* Written by Martin Sivak
|
||||
*
|
||||
* 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 <Python.h>
|
||||
#include <structmember.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "libcryptsetup.h"
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
|
||||
/* Type-specific fields go here. */
|
||||
struct crypt_device *device;
|
||||
char *activated_as;
|
||||
|
||||
/* Callbacks */
|
||||
PyObject *yesDialogCB;
|
||||
PyObject *cmdLineLogCB;
|
||||
PyObject *passwordDialogCB;
|
||||
} CryptSetupObject;
|
||||
|
||||
static int yesDialog(const char *msg, void *this)
|
||||
{
|
||||
CryptSetupObject *self = this;
|
||||
PyObject *result, *arglist;
|
||||
int r;
|
||||
|
||||
if (self->yesDialogCB){
|
||||
arglist = Py_BuildValue("(s)", msg);
|
||||
if (!arglist)
|
||||
return -ENOMEM;
|
||||
|
||||
result = PyEval_CallObject(self->yesDialogCB, arglist);
|
||||
Py_DECREF(arglist);
|
||||
|
||||
if (!result)
|
||||
return -EINVAL;
|
||||
|
||||
if (!PyArg_Parse(result, "i", &r))
|
||||
r = -EINVAL;
|
||||
|
||||
Py_DECREF(result);
|
||||
return r;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int passwordDialog(const char *msg, char *buf, size_t length, void *this)
|
||||
{
|
||||
CryptSetupObject *self = this;
|
||||
PyObject *result, *arglist;
|
||||
size_t len;
|
||||
char *res = NULL;
|
||||
|
||||
if(self->passwordDialogCB){
|
||||
arglist = Py_BuildValue("(s)", msg);
|
||||
if (!arglist)
|
||||
return -ENOMEM;
|
||||
|
||||
result = PyEval_CallObject(self->passwordDialogCB, arglist);
|
||||
Py_DECREF(arglist);
|
||||
|
||||
if (!result)
|
||||
return -EINVAL;
|
||||
|
||||
if (!PyArg_Parse(result, "z", &res)) {
|
||||
Py_DECREF(result);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
strncpy(buf, res, length - 1);
|
||||
len = strlen(res);
|
||||
|
||||
memset(res, 0, len);
|
||||
Py_DECREF(result);
|
||||
|
||||
return (int)len;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void cmdLineLog(int cls, const char *msg, void *this)
|
||||
{
|
||||
CryptSetupObject *self = this;
|
||||
PyObject *result, *arglist;
|
||||
|
||||
if(self->cmdLineLogCB) {
|
||||
arglist = Py_BuildValue("(is)", cls, msg);
|
||||
if(!arglist)
|
||||
return;
|
||||
|
||||
result = PyEval_CallObject(self->cmdLineLogCB, arglist);
|
||||
Py_DECREF(arglist);
|
||||
Py_XDECREF(result);
|
||||
}
|
||||
}
|
||||
|
||||
static void CryptSetup_dealloc(CryptSetupObject* self)
|
||||
{
|
||||
/* free the callbacks */
|
||||
Py_XDECREF(self->yesDialogCB);
|
||||
Py_XDECREF(self->cmdLineLogCB);
|
||||
Py_XDECREF(self->passwordDialogCB);
|
||||
|
||||
free(self->activated_as);
|
||||
|
||||
crypt_free(self->device);
|
||||
|
||||
/* free self */
|
||||
self->ob_type->tp_free((PyObject*)self);
|
||||
}
|
||||
|
||||
static PyObject *CryptSetup_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
CryptSetupObject *self = (CryptSetupObject *)type->tp_alloc(type, 0);
|
||||
|
||||
if (self) {
|
||||
self->yesDialogCB = NULL;
|
||||
self->passwordDialogCB = NULL;
|
||||
self->cmdLineLogCB = NULL;
|
||||
self->activated_as = NULL;
|
||||
}
|
||||
|
||||
return (PyObject *)self;
|
||||
}
|
||||
|
||||
static PyObject *PyObjectResult(int is)
|
||||
{
|
||||
PyObject *result = Py_BuildValue("i", is);
|
||||
|
||||
if (!result)
|
||||
PyErr_SetString(PyExc_RuntimeError, "Error during constructing values for return value");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#define CryptSetup_HELP "CryptSetup object\n\n\
|
||||
constructor takes one to five arguments:\n\
|
||||
__init__(device, name, yesDialog, passwordDialog, logFunc)\n\n\
|
||||
yesDialog - python function with func(text) signature, \n\
|
||||
which asks the user question text and returns 1\n\
|
||||
of the answer was positive or 0 if not\n\
|
||||
logFunc - python function with func(level, text) signature to log stuff somewhere"
|
||||
|
||||
static int CryptSetup_init(CryptSetupObject* self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
static char *kwlist[] = {"device", "name", "yesDialog", "passwordDialog", "logFunc", NULL};
|
||||
PyObject *yesDialogCB = NULL,
|
||||
*passwordDialogCB = NULL,
|
||||
*cmdLineLogCB = NULL,
|
||||
*tmp = NULL;
|
||||
char *device = NULL, *deviceName = NULL;
|
||||
int r;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|zzOOO", kwlist, &device, &deviceName,
|
||||
&yesDialogCB, &passwordDialogCB, &cmdLineLogCB))
|
||||
return -1;
|
||||
|
||||
if (device) {
|
||||
if (crypt_init(&(self->device), device)) {
|
||||
PyErr_SetString(PyExc_IOError, "Device cannot be opened");
|
||||
return -1;
|
||||
}
|
||||
/* Try to load header form device */
|
||||
r = crypt_load(self->device, NULL, NULL);
|
||||
if (r && r != -EINVAL) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "Cannot initialize device context");
|
||||
return -1;
|
||||
}
|
||||
} else if (deviceName) {
|
||||
if (crypt_init_by_name(&(self->device), deviceName)) {
|
||||
PyErr_SetString(PyExc_IOError, "Device cannot be opened");
|
||||
return -1;
|
||||
}
|
||||
/* Context is initialized automatically from active device */
|
||||
} else {
|
||||
PyErr_SetString(PyExc_RuntimeError, "Either device file or luks name has to be specified");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(deviceName)
|
||||
self->activated_as = strdup(deviceName);
|
||||
|
||||
if (yesDialogCB) {
|
||||
tmp = self->yesDialogCB;
|
||||
Py_INCREF(yesDialogCB);
|
||||
self->yesDialogCB = yesDialogCB;
|
||||
Py_XDECREF(tmp);
|
||||
crypt_set_confirm_callback(self->device, yesDialog, self);
|
||||
}
|
||||
|
||||
if (passwordDialogCB) {
|
||||
tmp = self->passwordDialogCB;
|
||||
Py_INCREF(passwordDialogCB);
|
||||
self->passwordDialogCB = passwordDialogCB;
|
||||
Py_XDECREF(tmp);
|
||||
crypt_set_password_callback(self->device, passwordDialog, self);
|
||||
}
|
||||
|
||||
if (cmdLineLogCB) {
|
||||
tmp = self->cmdLineLogCB;
|
||||
Py_INCREF(cmdLineLogCB);
|
||||
self->cmdLineLogCB = cmdLineLogCB;
|
||||
Py_XDECREF(tmp);
|
||||
crypt_set_log_callback(self->device, cmdLineLog, self);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define CryptSetup_activate_HELP "Activate LUKS device\n\n\
|
||||
activate(name)"
|
||||
|
||||
static PyObject *CryptSetup_activate(CryptSetupObject* self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
static char *kwlist[] = {"name", "passphrase", NULL};
|
||||
char *name = NULL, *passphrase = NULL;
|
||||
int is;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|s", kwlist, &name, &passphrase))
|
||||
return NULL;
|
||||
|
||||
// FIXME: allow keyfile and \0 in passphrase
|
||||
is = crypt_activate_by_passphrase(self->device, name, CRYPT_ANY_SLOT,
|
||||
passphrase, passphrase ? strlen(passphrase) : 0, 0);
|
||||
|
||||
if (is >= 0) {
|
||||
free(self->activated_as);
|
||||
self->activated_as = strdup(name);
|
||||
}
|
||||
|
||||
return PyObjectResult(is);
|
||||
}
|
||||
|
||||
#define CryptSetup_deactivate_HELP "Dectivate LUKS device\n\n\
|
||||
deactivate()"
|
||||
|
||||
static PyObject *CryptSetup_deactivate(CryptSetupObject* self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
int is = crypt_deactivate(self->device, self->activated_as);
|
||||
|
||||
if (!is) {
|
||||
free(self->activated_as);
|
||||
self->activated_as = NULL;
|
||||
}
|
||||
|
||||
return PyObjectResult(is);
|
||||
}
|
||||
|
||||
#define CryptSetup_askyes_HELP "Asks a question using the configured dialog CB\n\n\
|
||||
int askyes(message)"
|
||||
|
||||
static PyObject *CryptSetup_askyes(CryptSetupObject* self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
static char *kwlist[] = {"message", NULL};
|
||||
PyObject *message = NULL, *result, *arglist;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &message))
|
||||
return NULL;
|
||||
|
||||
Py_INCREF(message);
|
||||
|
||||
arglist = Py_BuildValue("(O)", message);
|
||||
if (!arglist){
|
||||
PyErr_SetString(PyExc_RuntimeError, "Error during constructing values for internal call");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result = PyEval_CallObject(self->yesDialogCB, arglist);
|
||||
Py_DECREF(arglist);
|
||||
Py_DECREF(message);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#define CryptSetup_log_HELP "Logs a string using the configured log CB\n\n\
|
||||
log(int level, message)"
|
||||
|
||||
static PyObject *CryptSetup_log(CryptSetupObject* self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
static char *kwlist[] = {"priority", "message", NULL};
|
||||
PyObject *message = NULL, *priority = NULL, *result, *arglist;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist, &message, &priority))
|
||||
return NULL;
|
||||
|
||||
Py_INCREF(message);
|
||||
Py_INCREF(priority);
|
||||
|
||||
arglist = Py_BuildValue("(OO)", message, priority);
|
||||
if (!arglist){
|
||||
PyErr_SetString(PyExc_RuntimeError, "Error during constructing values for internal call");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result = PyEval_CallObject(self->cmdLineLogCB, arglist);
|
||||
Py_DECREF(arglist);
|
||||
Py_DECREF(priority);
|
||||
Py_DECREF(message);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#define CryptSetup_luksUUID_HELP "Get UUID of the LUKS device\n\n\
|
||||
luksUUID()"
|
||||
|
||||
static PyObject *CryptSetup_luksUUID(CryptSetupObject* self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
PyObject *result;
|
||||
|
||||
result = Py_BuildValue("s", crypt_get_uuid(self->device));
|
||||
if (!result)
|
||||
PyErr_SetString(PyExc_RuntimeError, "Error during constructing values for return value");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#define CryptSetup_isLuks_HELP "Is the device LUKS?\n\n\
|
||||
isLuks()"
|
||||
|
||||
static PyObject *CryptSetup_isLuks(CryptSetupObject* self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
return PyObjectResult(crypt_load(self->device, CRYPT_LUKS1, NULL));
|
||||
}
|
||||
|
||||
#define CryptSetup_Info_HELP "Returns dictionary with info about opened device\nKeys:\n\
|
||||
dir\n name\n uuid\n cipher\n cipher_mode\n keysize\n device\n\
|
||||
offset\n size\n skip\n mode\n"
|
||||
|
||||
static PyObject *CryptSetup_Info(CryptSetupObject* self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
PyObject *result;
|
||||
|
||||
result = Py_BuildValue("{s:s,s:s,s:z,s:s,s:s,s:s,s:i,s:K}",
|
||||
"dir", crypt_get_dir(),
|
||||
"device", crypt_get_device_name(self->device),
|
||||
"name", self->activated_as,
|
||||
"uuid", crypt_get_uuid(self->device),
|
||||
"cipher", crypt_get_cipher(self->device),
|
||||
"cipher_mode", crypt_get_cipher_mode(self->device),
|
||||
"keysize", crypt_get_volume_key_size(self->device) * 8,
|
||||
//"size", co.size,
|
||||
//"mode", (co.flags & CRYPT_FLAG_READONLY) ? "readonly" : "read/write",
|
||||
"offset", crypt_get_data_offset(self->device)
|
||||
);
|
||||
|
||||
if (!result)
|
||||
PyErr_SetString(PyExc_RuntimeError, "Error during constructing values for return value");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#define CryptSetup_luksFormat_HELP "Format device to enable LUKS\n\n\
|
||||
luksFormat(cipher = 'aes', cipherMode = 'cbc-essiv:sha256', keysize = 256)\n\n\
|
||||
cipher - cipher specification, e.g. aes, serpent\n\
|
||||
cipherMode - cipher mode specification, e.g. cbc-essiv:sha256, xts-plain64\n\
|
||||
keysize - key size in bits"
|
||||
|
||||
static PyObject *CryptSetup_luksFormat(CryptSetupObject* self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
static char *kwlist[] = {"cipher", "cipherMode", "keysize", NULL};
|
||||
char *cipher_mode = NULL, *cipher = NULL;
|
||||
int keysize = 256;
|
||||
PyObject *keysize_object = NULL;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|zzO", kwlist,
|
||||
&cipher, &cipher_mode, &keysize_object))
|
||||
return NULL;
|
||||
|
||||
if (!keysize_object || keysize_object == Py_None) {
|
||||
/* use default value */
|
||||
} else if (!PyInt_Check(keysize_object)) {
|
||||
PyErr_SetString(PyExc_TypeError, "keysize must be an integer");
|
||||
return NULL;
|
||||
} else if (PyInt_AsLong(keysize_object) % 8) {
|
||||
PyErr_SetString(PyExc_TypeError, "keysize must have integer value dividable by 8");
|
||||
return NULL;
|
||||
} else if (PyInt_AsLong(keysize_object) <= 0) {
|
||||
PyErr_SetString(PyExc_TypeError, "keysize must be positive number bigger than 0");
|
||||
return NULL;
|
||||
} else
|
||||
keysize = PyInt_AsLong(keysize_object);
|
||||
|
||||
// FIXME use #defined defaults
|
||||
return PyObjectResult(crypt_format(self->device, CRYPT_LUKS1,
|
||||
cipher ?: "aes", cipher_mode ?: "cbc-essiv:sha256",
|
||||
NULL, NULL, keysize / 8, NULL));
|
||||
}
|
||||
|
||||
#define CryptSetup_addKeyByPassphrase_HELP "Initialize keyslot using passphrase\n\n\
|
||||
addKeyByPassphrase(passphrase, newPassphrase, slot)\n\n\
|
||||
passphrase - string or none to ask the user\n\
|
||||
newPassphrase - passphrase to add\n\
|
||||
slot - which slot to use (optional)"
|
||||
|
||||
static PyObject *CryptSetup_addKeyByPassphrase(CryptSetupObject* self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
static char *kwlist[] = {"passphrase", "newPassphrase", "slot", NULL};
|
||||
char *passphrase = NULL, *newpassphrase = NULL;
|
||||
size_t passphrase_len = 0, newpassphrase_len = 0;
|
||||
int slot = CRYPT_ANY_SLOT;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss|i", kwlist, &passphrase, &newpassphrase, &slot))
|
||||
return NULL;
|
||||
|
||||
if(passphrase)
|
||||
passphrase_len = strlen(passphrase);
|
||||
|
||||
if(newpassphrase)
|
||||
newpassphrase_len = strlen(newpassphrase);
|
||||
|
||||
return PyObjectResult(crypt_keyslot_add_by_passphrase(self->device, slot,
|
||||
passphrase, passphrase_len,
|
||||
newpassphrase, newpassphrase_len));
|
||||
}
|
||||
|
||||
#define CryptSetup_addKeyByVolumeKey_HELP "Initialize keyslot using cached volume key\n\n\
|
||||
addKeyByVolumeKey(passphrase, newPassphrase, slot)\n\n\
|
||||
newPassphrase - passphrase to add\n\
|
||||
slot - which slot to use (optional)"
|
||||
|
||||
static PyObject *CryptSetup_addKeyByVolumeKey(CryptSetupObject* self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
static char *kwlist[] = {"newPassphrase", "slot", NULL};
|
||||
char *newpassphrase = NULL;
|
||||
size_t newpassphrase_len = 0;
|
||||
int slot = CRYPT_ANY_SLOT;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|i", kwlist, &newpassphrase, &slot))
|
||||
return NULL;
|
||||
|
||||
if (newpassphrase)
|
||||
newpassphrase_len = strlen(newpassphrase);
|
||||
|
||||
return PyObjectResult(crypt_keyslot_add_by_volume_key(self->device, slot,
|
||||
NULL, 0, newpassphrase, newpassphrase_len));
|
||||
}
|
||||
|
||||
#define CryptSetup_removePassphrase_HELP "Destroy keyslot using passphrase\n\n\
|
||||
removePassphrase(passphrase)\n\n\
|
||||
passphrase - string or none to ask the user"
|
||||
|
||||
static PyObject *CryptSetup_removePassphrase(CryptSetupObject* self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
static char *kwlist[] = {"passphrase", NULL};
|
||||
char *passphrase = NULL;
|
||||
size_t passphrase_len = 0;
|
||||
int is;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &passphrase))
|
||||
return NULL;
|
||||
|
||||
if (passphrase)
|
||||
passphrase_len = strlen(passphrase);
|
||||
|
||||
is = crypt_activate_by_passphrase(self->device, NULL, CRYPT_ANY_SLOT,
|
||||
passphrase, passphrase_len, 0);
|
||||
if (is < 0)
|
||||
return PyObjectResult(is);
|
||||
|
||||
return PyObjectResult(crypt_keyslot_destroy(self->device, is));
|
||||
}
|
||||
|
||||
#define CryptSetup_killSlot_HELP "Destroy keyslot\n\n\
|
||||
killSlot(slot)\n\n\
|
||||
slot - the slot to remove"
|
||||
|
||||
static PyObject *CryptSetup_killSlot(CryptSetupObject* self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
static char *kwlist[] = {"slot", NULL};
|
||||
int slot = CRYPT_ANY_SLOT;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &slot))
|
||||
return NULL;
|
||||
|
||||
switch (crypt_keyslot_status(self->device, slot)) {
|
||||
case CRYPT_SLOT_ACTIVE:
|
||||
return PyObjectResult(crypt_keyslot_destroy(self->device, slot));
|
||||
case CRYPT_SLOT_ACTIVE_LAST:
|
||||
PyErr_SetString(PyExc_ValueError, "Last slot, removing it would render the device unusable");
|
||||
break;
|
||||
case CRYPT_SLOT_INACTIVE:
|
||||
PyErr_SetString(PyExc_ValueError, "Inactive slot");
|
||||
break;
|
||||
case CRYPT_SLOT_INVALID:
|
||||
PyErr_SetString(PyExc_ValueError, "Invalid slot");
|
||||
break;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define CryptSetup_Status_HELP "Status of LUKS device\n\n\
|
||||
luksStatus()"
|
||||
|
||||
static PyObject *CryptSetup_Status(CryptSetupObject* self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
if (!self->activated_as){
|
||||
PyErr_SetString(PyExc_IOError, "Device has not been activated yet.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return PyObjectResult(crypt_status(self->device, self->activated_as));
|
||||
}
|
||||
|
||||
#define CryptSetup_Resume_HELP "Resume LUKS device\n\n\
|
||||
luksOpen(passphrase)\n\n\
|
||||
passphrase - string or none to ask the user"
|
||||
|
||||
static PyObject *CryptSetup_Resume(CryptSetupObject* self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
static char *kwlist[] = {"passphrase", NULL};
|
||||
char* passphrase = NULL;
|
||||
size_t passphrase_len = 0;
|
||||
|
||||
if (!self->activated_as){
|
||||
PyErr_SetString(PyExc_IOError, "Device has not been activated yet.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (! PyArg_ParseTupleAndKeywords(args, kwds, "|s", kwlist, &passphrase))
|
||||
return NULL;
|
||||
|
||||
if (passphrase)
|
||||
passphrase_len = strlen(passphrase);
|
||||
|
||||
return PyObjectResult(crypt_resume_by_passphrase(self->device, self->activated_as,
|
||||
CRYPT_ANY_SLOT, passphrase, passphrase_len));
|
||||
}
|
||||
|
||||
#define CryptSetup_Suspend_HELP "Suspend LUKS device\n\n\
|
||||
luksSupsend()"
|
||||
|
||||
static PyObject *CryptSetup_Suspend(CryptSetupObject* self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
if (!self->activated_as){
|
||||
PyErr_SetString(PyExc_IOError, "Device has not been activated yet.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return PyObjectResult(crypt_suspend(self->device, self->activated_as));
|
||||
}
|
||||
|
||||
#define CryptSetup_debugLevel_HELP "Set debug level\n\n\
|
||||
debugLevel(level)\n\n\
|
||||
level - debug level"
|
||||
|
||||
static PyObject *CryptSetup_debugLevel(CryptSetupObject* self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
static char *kwlist[] = {"level", NULL};
|
||||
int level = 0;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &level))
|
||||
return NULL;
|
||||
|
||||
crypt_set_debug_level(level);
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
#define CryptSetup_iterationTime_HELP "Set iteration time\n\n\
|
||||
iterationTime(time_ms)\n\n\
|
||||
time_ms - time in miliseconds"
|
||||
|
||||
static PyObject *CryptSetup_iterationTime(CryptSetupObject* self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
static char *kwlist[] = {"time_ms", NULL};
|
||||
uint64_t time_ms = 0;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "K", kwlist, &time_ms))
|
||||
return NULL;
|
||||
|
||||
crypt_set_iteration_time(self->device, time_ms);
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyMemberDef CryptSetup_members[] = {
|
||||
{"yesDialogCB", T_OBJECT_EX, offsetof(CryptSetupObject, yesDialogCB), 0, "confirmation dialog callback"},
|
||||
{"cmdLineLogCB", T_OBJECT_EX, offsetof(CryptSetupObject, cmdLineLogCB), 0, "logging callback"},
|
||||
{"passwordDialogCB", T_OBJECT_EX, offsetof(CryptSetupObject, passwordDialogCB), 0, "password dialog callback"},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
static PyMethodDef CryptSetup_methods[] = {
|
||||
/* self-test methods */
|
||||
{"log", (PyCFunction)CryptSetup_log, METH_VARARGS|METH_KEYWORDS, CryptSetup_askyes_HELP},
|
||||
{"askyes", (PyCFunction)CryptSetup_askyes, METH_VARARGS|METH_KEYWORDS, CryptSetup_log_HELP},
|
||||
|
||||
/* activation and deactivation */
|
||||
{"deactivate", (PyCFunction)CryptSetup_deactivate, METH_NOARGS, CryptSetup_deactivate_HELP},
|
||||
{"activate", (PyCFunction)CryptSetup_activate, METH_VARARGS|METH_KEYWORDS, CryptSetup_activate_HELP},
|
||||
|
||||
/* cryptsetup info entrypoints */
|
||||
{"luksUUID", (PyCFunction)CryptSetup_luksUUID, METH_NOARGS, CryptSetup_luksUUID_HELP},
|
||||
{"isLuks", (PyCFunction)CryptSetup_isLuks, METH_NOARGS, CryptSetup_isLuks_HELP},
|
||||
{"info", (PyCFunction)CryptSetup_Info, METH_NOARGS, CryptSetup_Info_HELP},
|
||||
{"status", (PyCFunction)CryptSetup_Status, METH_NOARGS, CryptSetup_Status_HELP},
|
||||
|
||||
/* cryptsetup mgmt entrypoints */
|
||||
{"luksFormat", (PyCFunction)CryptSetup_luksFormat, METH_VARARGS|METH_KEYWORDS, CryptSetup_luksFormat_HELP},
|
||||
{"addKeyByPassphrase", (PyCFunction)CryptSetup_addKeyByPassphrase, METH_VARARGS|METH_KEYWORDS, CryptSetup_addKeyByPassphrase_HELP},
|
||||
{"addKeyByVolumeKey", (PyCFunction)CryptSetup_addKeyByVolumeKey, METH_VARARGS|METH_KEYWORDS, CryptSetup_addKeyByVolumeKey_HELP},
|
||||
{"removePassphrase", (PyCFunction)CryptSetup_removePassphrase, METH_VARARGS|METH_KEYWORDS, CryptSetup_removePassphrase_HELP},
|
||||
{"killSlot", (PyCFunction)CryptSetup_killSlot, METH_VARARGS|METH_KEYWORDS, CryptSetup_killSlot_HELP},
|
||||
|
||||
/* suspend resume */
|
||||
{"resume", (PyCFunction)CryptSetup_Resume, METH_VARARGS|METH_KEYWORDS, CryptSetup_Resume_HELP},
|
||||
{"suspend", (PyCFunction)CryptSetup_Suspend, METH_NOARGS, CryptSetup_Suspend_HELP},
|
||||
|
||||
/* misc */
|
||||
{"debugLevel", (PyCFunction)CryptSetup_debugLevel, METH_VARARGS|METH_KEYWORDS, CryptSetup_debugLevel_HELP},
|
||||
{"iterationTime", (PyCFunction)CryptSetup_iterationTime, METH_VARARGS|METH_KEYWORDS, CryptSetup_iterationTime_HELP},
|
||||
|
||||
{NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
static PyTypeObject CryptSetupType = {
|
||||
PyObject_HEAD_INIT(NULL)
|
||||
0, /*ob_size*/
|
||||
"pycryptsetup.CryptSetup", /*tp_name*/
|
||||
sizeof(CryptSetupObject), /*tp_basicsize*/
|
||||
0, /*tp_itemsize*/
|
||||
(destructor)CryptSetup_dealloc, /*tp_dealloc*/
|
||||
0, /*tp_print*/
|
||||
0, /*tp_getattr*/
|
||||
0, /*tp_setattr*/
|
||||
0, /*tp_compare*/
|
||||
0, /*tp_repr*/
|
||||
0, /*tp_as_number*/
|
||||
0, /*tp_as_sequence*/
|
||||
0, /*tp_as_mapping*/
|
||||
0, /*tp_hash */
|
||||
0, /*tp_call*/
|
||||
0, /*tp_str*/
|
||||
0, /*tp_getattro*/
|
||||
0, /*tp_setattro*/
|
||||
0, /*tp_as_buffer*/
|
||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
|
||||
CryptSetup_HELP, /* tp_doc */
|
||||
0, /* tp_traverse */
|
||||
0, /* tp_clear */
|
||||
0, /* tp_richcompare */
|
||||
0, /* tp_weaklistoffset */
|
||||
0, /* tp_iter */
|
||||
0, /* tp_iternext */
|
||||
CryptSetup_methods, /* tp_methods */
|
||||
CryptSetup_members, /* tp_members */
|
||||
0, /* tp_getset */
|
||||
0, /* tp_base */
|
||||
0, /* tp_dict */
|
||||
0, /* tp_descr_get */
|
||||
0, /* tp_descr_set */
|
||||
0, /* tp_dictoffset */
|
||||
(initproc)CryptSetup_init, /* tp_init */
|
||||
0, /* tp_alloc */
|
||||
CryptSetup_new, /* tp_new */
|
||||
};
|
||||
|
||||
static PyMethodDef pycryptsetup_methods[] = {
|
||||
{NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
PyMODINIT_FUNC initpycryptsetup(void);
|
||||
PyMODINIT_FUNC initpycryptsetup(void)
|
||||
{
|
||||
PyObject *m;
|
||||
|
||||
if (PyType_Ready(&CryptSetupType) < 0)
|
||||
return;
|
||||
|
||||
m = Py_InitModule3("pycryptsetup", pycryptsetup_methods, "CryptSetup pythonized API.");
|
||||
Py_INCREF(&CryptSetupType);
|
||||
|
||||
PyModule_AddObject(m, "CryptSetup", (PyObject *)&CryptSetupType);
|
||||
|
||||
/* debug constants */
|
||||
PyModule_AddIntConstant(m, "CRYPT_DEBUG_ALL", CRYPT_DEBUG_ALL);
|
||||
PyModule_AddIntConstant(m, "CRYPT_DEBUG_NONE", CRYPT_DEBUG_NONE);
|
||||
|
||||
/* log constants */
|
||||
PyModule_AddIntConstant(m, "CRYPT_LOG_NORMAL", CRYPT_LOG_NORMAL);
|
||||
PyModule_AddIntConstant(m, "CRYPT_LOG_ERROR", CRYPT_LOG_ERROR);
|
||||
PyModule_AddIntConstant(m, "CRYPT_LOG_VERBOSE", CRYPT_LOG_VERBOSE);
|
||||
PyModule_AddIntConstant(m, "CRYPT_LOG_DEBUG", CRYPT_LOG_DEBUG);
|
||||
|
||||
/* status constants */
|
||||
PyModule_AddIntConstant(m, "CRYPT_INVALID", CRYPT_INVALID);
|
||||
PyModule_AddIntConstant(m, "CRYPT_INACTIVE", CRYPT_INACTIVE);
|
||||
PyModule_AddIntConstant(m, "CRYPT_ACTIVE", CRYPT_ACTIVE);
|
||||
PyModule_AddIntConstant(m, "CRYPT_BUSY", CRYPT_BUSY);
|
||||
}
|
||||
@@ -9,21 +9,24 @@ INCLUDES = \
|
||||
-DVERSION=\""$(VERSION)"\" \
|
||||
-D_GNU_SOURCE
|
||||
|
||||
# cryptsetup
|
||||
cryptsetup_SOURCES = \
|
||||
$(top_builddir)/lib/utils_crypt.c \
|
||||
$(top_builddir)/lib/utils_loop.c \
|
||||
$(top_builddir)/lib/utils_fips.c \
|
||||
cryptsetup.c \
|
||||
cryptsetup.h
|
||||
|
||||
cryptsetup_LDADD = \
|
||||
$(top_builddir)/lib/libcryptsetup.la \
|
||||
@POPT_LIBS@
|
||||
@POPT_LIBS@ \
|
||||
@FIPSCHECK_LIBS@
|
||||
|
||||
cryptsetup_CFLAGS = -Wall
|
||||
|
||||
sbin_PROGRAMS=cryptsetup
|
||||
|
||||
if STATIC_CRYPTSETUP
|
||||
if STATIC_TOOLS
|
||||
sbin_PROGRAMS += cryptsetup.static
|
||||
cryptsetup_static_SOURCES = $(cryptsetup_SOURCES)
|
||||
cryptsetup_static_CFLAGS = $(cryptsetup_CFLAGS)
|
||||
@@ -33,3 +36,56 @@ cryptsetup_static_LDADD = $(cryptsetup_LDADD) \
|
||||
@DEVMAPPER_STATIC_LIBS@ \
|
||||
@UUID_LIBS@
|
||||
endif
|
||||
|
||||
# veritysetup
|
||||
if VERITYSETUP
|
||||
|
||||
veritysetup_SOURCES = \
|
||||
$(top_builddir)/lib/utils_crypt.c \
|
||||
$(top_builddir)/lib/utils_loop.c \
|
||||
veritysetup.c \
|
||||
cryptsetup.h
|
||||
|
||||
veritysetup_LDADD = \
|
||||
$(top_builddir)/lib/libcryptsetup.la \
|
||||
@POPT_LIBS@
|
||||
|
||||
veritysetup_CFLAGS = $(cryptsetup_CFLAGS)
|
||||
|
||||
sbin_PROGRAMS += veritysetup
|
||||
|
||||
if STATIC_TOOLS
|
||||
sbin_PROGRAMS += veritysetup.static
|
||||
veritysetup_static_SOURCES = $(veritysetup_SOURCES)
|
||||
veritysetup_static_CFLAGS = $(veritysetup_CFLAGS)
|
||||
veritysetup_static_LDFLAGS = -all-static
|
||||
veritysetup_static_LDADD = $(veritysetup_LDADD) \
|
||||
@CRYPTO_STATIC_LIBS@ \
|
||||
@DEVMAPPER_STATIC_LIBS@ \
|
||||
@UUID_LIBS@
|
||||
endif
|
||||
endif
|
||||
|
||||
# reencrypt
|
||||
if REENCRYPT
|
||||
cryptsetup_reencrypt_SOURCES = \
|
||||
$(top_builddir)/lib/utils_crypt.c \
|
||||
cryptsetup_reencrypt.c \
|
||||
cryptsetup.h
|
||||
|
||||
cryptsetup_reencrypt_LDADD = $(cryptsetup_LDADD)
|
||||
cryptsetup_reencrypt_CFLAGS = $(cryptsetup_CFLAGS)
|
||||
|
||||
sbin_PROGRAMS += cryptsetup-reencrypt
|
||||
|
||||
if STATIC_TOOLS
|
||||
sbin_PROGRAMS += cryptsetup-reencrypt.static
|
||||
cryptsetup_reencrypt_static_SOURCES = $(cryptsetup_reencrypt_SOURCES)
|
||||
cryptsetup_reencrypt_static_CFLAGS = $(cryptsetup_reencrypt_CFLAGS)
|
||||
cryptsetup_reencrypt_static_LDFLAGS = -all-static
|
||||
cryptsetup_reencrypt_static_LDADD = $(cryptsetup_reencrypt_LDADD) \
|
||||
@CRYPTO_STATIC_LIBS@ \
|
||||
@DEVMAPPER_STATIC_LIBS@ \
|
||||
@UUID_LIBS@
|
||||
endif
|
||||
endif
|
||||
|
||||
374
src/cryptsetup.c
374
src/cryptsetup.c
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 2004, Christophe Saout <christophe@saout.de>
|
||||
* Copyright (C) 2004-2007, Clemens Fruhwirth <clemens@endorphin.org>
|
||||
* Copyright (C) 2009-2011, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -16,7 +16,7 @@
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
@@ -27,9 +27,11 @@
|
||||
#include <inttypes.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
#include <libcryptsetup.h>
|
||||
#include <limits.h>
|
||||
#include <popt.h>
|
||||
|
||||
#include "cryptsetup.h"
|
||||
@@ -43,9 +45,12 @@ static const char *opt_key_file = NULL;
|
||||
static const char *opt_master_key_file = NULL;
|
||||
static const char *opt_header_backup_file = NULL;
|
||||
static const char *opt_uuid = NULL;
|
||||
static const char *opt_header_device = NULL;
|
||||
static int opt_key_size = 0;
|
||||
static long opt_keyfile_size = 0;
|
||||
static long opt_new_keyfile_size = 0;
|
||||
static long opt_keyfile_offset = 0;
|
||||
static long opt_new_keyfile_offset = 0;
|
||||
static int opt_key_slot = CRYPT_ANY_SLOT;
|
||||
static uint64_t opt_size = 0;
|
||||
static uint64_t opt_offset = 0;
|
||||
@@ -61,6 +66,9 @@ static int opt_align_payload = 0;
|
||||
static int opt_random = 0;
|
||||
static int opt_urandom = 0;
|
||||
static int opt_dump_master_key = 0;
|
||||
static int opt_shared = 0;
|
||||
static int opt_allow_discards = 0;
|
||||
static int opt_test_passphrase = 0;
|
||||
|
||||
static const char **action_argv;
|
||||
static int action_argc;
|
||||
@@ -83,6 +91,7 @@ static int action_luksResume(int arg);
|
||||
static int action_luksBackup(int arg);
|
||||
static int action_luksRestore(int arg);
|
||||
static int action_loopaesOpen(int arg);
|
||||
static int action_luksRepair(int arg);
|
||||
|
||||
static struct action_type {
|
||||
const char *type;
|
||||
@@ -97,6 +106,7 @@ static struct action_type {
|
||||
{ "remove", action_remove, 0, 1, 1, N_("<name>"), N_("remove device") },
|
||||
{ "resize", action_resize, 0, 1, 1, N_("<name>"), N_("resize active device") },
|
||||
{ "status", action_status, 0, 1, 0, N_("<name>"), N_("show device status") },
|
||||
{ "repair", action_luksRepair, 0, 1, 1, N_("<device>"), N_("try to repair on-disk metadata") },
|
||||
{ "luksFormat", action_luksFormat, 0, 1, 1, N_("<device> [<new key file>]"), N_("formats a LUKS device") },
|
||||
{ "luksOpen", action_luksOpen, 0, 2, 1, N_("<device> <name> "), N_("open LUKS device as mapping <name>") },
|
||||
{ "luksAddKey", action_luksAddKey, 0, 1, 1, N_("<device> [<new key file>]"), N_("add key to LUKS device") },
|
||||
@@ -147,7 +157,7 @@ static int _yesDialog(const char *msg, void *usrptr __attribute__((unused)))
|
||||
size_t size = 0;
|
||||
int r = 1;
|
||||
|
||||
if(isatty(0) && !opt_batch_mode) {
|
||||
if(isatty(STDIN_FILENO) && !opt_batch_mode) {
|
||||
log_std("\nWARNING!\n========\n");
|
||||
log_std("%s\n\nAre you sure? (Type uppercase yes): ", msg);
|
||||
if(getline(&answer, &size, stdin) == -1) {
|
||||
@@ -187,6 +197,31 @@ static void _log(int level, const char *msg, void *usrptr __attribute__((unused)
|
||||
}
|
||||
}
|
||||
|
||||
static void _quiet_log(int level, const char *msg, void *usrptr)
|
||||
{
|
||||
if (!opt_verbose && (level == CRYPT_LOG_ERROR || level == CRYPT_LOG_NORMAL))
|
||||
level = CRYPT_LOG_VERBOSE;
|
||||
_log(level, msg, usrptr);
|
||||
}
|
||||
|
||||
static int _verify_passphrase(int def)
|
||||
{
|
||||
/* Batch mode switch off verify - if not overrided by -y */
|
||||
if (opt_verify_passphrase)
|
||||
def = 1;
|
||||
else if (opt_batch_mode)
|
||||
def = 0;
|
||||
|
||||
/* Non-tty input doesn't allow verify */
|
||||
if (def && !isatty(STDIN_FILENO)) {
|
||||
if (opt_verify_passphrase)
|
||||
log_err(_("Can't do passphrase verification on non-tty inputs.\n"));
|
||||
def = 0;
|
||||
}
|
||||
|
||||
return def;
|
||||
}
|
||||
|
||||
static void show_status(int errcode)
|
||||
{
|
||||
char error[256], *error_;
|
||||
@@ -216,6 +251,31 @@ static void show_status(int errcode)
|
||||
log_err(".\n");
|
||||
}
|
||||
|
||||
static const char *uuid_or_device(const char *spec)
|
||||
{
|
||||
static char device[PATH_MAX];
|
||||
char s, *ptr;
|
||||
int i = 0, uuid_len = 5;
|
||||
|
||||
/* Check if it is correct UUID=<LUKS_UUID> format */
|
||||
if (spec && !strncmp(spec, "UUID=", uuid_len)) {
|
||||
strcpy(device, "/dev/disk/by-uuid/");
|
||||
ptr = &device[strlen(device)];
|
||||
i = uuid_len;
|
||||
while ((s = spec[i++]) && i < PATH_MAX) {
|
||||
if (!isxdigit(s) && s != '-')
|
||||
return spec; /* Bail it out */
|
||||
if (isalpha(s))
|
||||
s = tolower(s);
|
||||
*ptr++ = s;
|
||||
}
|
||||
*ptr = '\0';
|
||||
return device;
|
||||
}
|
||||
|
||||
return spec;
|
||||
}
|
||||
|
||||
static int action_create(int arg __attribute__((unused)))
|
||||
{
|
||||
struct crypt_device *cd = NULL;
|
||||
@@ -224,10 +284,12 @@ static int action_create(int arg __attribute__((unused)))
|
||||
.hash = opt_hash ?: DEFAULT_PLAIN_HASH,
|
||||
.skip = opt_skip,
|
||||
.offset = opt_offset,
|
||||
.size = opt_size,
|
||||
};
|
||||
char *password = NULL;
|
||||
size_t passwordLen;
|
||||
size_t key_size = (opt_key_size ?: DEFAULT_PLAIN_KEYBITS) / 8;
|
||||
uint32_t activate_flags = 0;
|
||||
int r;
|
||||
|
||||
if (params.hash && !strcmp(params.hash, "plain"))
|
||||
@@ -237,9 +299,9 @@ static int action_create(int arg __attribute__((unused)))
|
||||
if (opt_key_file && strcmp(opt_key_file, "-"))
|
||||
params.hash = NULL;
|
||||
|
||||
if (opt_keyfile_size && opt_key_file)
|
||||
log_std(("Ignoring keyfile size option, keyfile read size "
|
||||
"is always the same as encryption key size.\n"));
|
||||
if ((opt_keyfile_offset || opt_keyfile_size) && opt_key_file)
|
||||
log_std(("Ignoring keyfile offset and size options, keyfile read "
|
||||
"size is always the same as encryption key size.\n"));
|
||||
|
||||
r = crypt_parse_name_and_mode(opt_cipher ?: DEFAULT_CIPHER(PLAIN),
|
||||
cipher, NULL, cipher_mode);
|
||||
@@ -262,32 +324,34 @@ static int action_create(int arg __attribute__((unused)))
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
if (opt_readonly)
|
||||
activate_flags |= CRYPT_ACTIVATE_READONLY;
|
||||
|
||||
if (opt_shared)
|
||||
activate_flags |= CRYPT_ACTIVATE_SHARED;
|
||||
|
||||
if (opt_allow_discards)
|
||||
activate_flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS;
|
||||
|
||||
if (opt_key_file)
|
||||
/* With hashing, read the whole keyfile */
|
||||
r = crypt_activate_by_keyfile(cd, action_argv[0],
|
||||
CRYPT_ANY_SLOT, opt_key_file, params.hash ? 0 : key_size,
|
||||
opt_readonly ? CRYPT_ACTIVATE_READONLY : 0);
|
||||
r = crypt_activate_by_keyfile_offset(cd, action_argv[0],
|
||||
CRYPT_ANY_SLOT, opt_key_file,
|
||||
params.hash ? 0 : key_size, 0,
|
||||
activate_flags);
|
||||
else {
|
||||
r = crypt_get_key(_("Enter passphrase: "),
|
||||
&password, &passwordLen, opt_keyfile_size,
|
||||
&password, &passwordLen,
|
||||
opt_keyfile_offset, opt_keyfile_size,
|
||||
NULL, opt_timeout,
|
||||
opt_batch_mode ? 0 : opt_verify_passphrase,
|
||||
_verify_passphrase(0),
|
||||
cd);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
r = crypt_activate_by_passphrase(cd, action_argv[0],
|
||||
CRYPT_ANY_SLOT, password, passwordLen,
|
||||
opt_readonly ? CRYPT_ACTIVATE_READONLY : 0);
|
||||
CRYPT_ANY_SLOT, password, passwordLen, activate_flags);
|
||||
}
|
||||
|
||||
/* FIXME: workaround, new api missing format parameter for size.
|
||||
* Properly fix it after bumping library version,
|
||||
* add start_offset and size into "PLAIN" format specifiers.
|
||||
*/
|
||||
if (r >= 0 && opt_size)
|
||||
r = crypt_resize(cd, action_argv[0], opt_size);
|
||||
|
||||
out:
|
||||
crypt_free(cd);
|
||||
crypt_safe_free(password);
|
||||
@@ -304,6 +368,7 @@ static int action_loopaesOpen(int arg __attribute__((unused)))
|
||||
.skip = opt_skip_valid ? opt_skip : opt_offset,
|
||||
};
|
||||
unsigned int key_size = (opt_key_size ?: DEFAULT_LOOPAES_KEYBITS) / 8;
|
||||
uint32_t activate_flags = 0;
|
||||
int r;
|
||||
|
||||
if (!opt_key_file) {
|
||||
@@ -311,6 +376,12 @@ static int action_loopaesOpen(int arg __attribute__((unused)))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (opt_readonly)
|
||||
activate_flags |= CRYPT_ACTIVATE_READONLY;
|
||||
|
||||
if (opt_allow_discards)
|
||||
activate_flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS;
|
||||
|
||||
if ((r = crypt_init(&cd, action_argv[0])))
|
||||
goto out;
|
||||
|
||||
@@ -319,9 +390,9 @@ static int action_loopaesOpen(int arg __attribute__((unused)))
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
r = crypt_activate_by_keyfile(cd, action_argv[1],
|
||||
CRYPT_ANY_SLOT, opt_key_file, opt_keyfile_size,
|
||||
opt_readonly ? CRYPT_ACTIVATE_READONLY : 0);
|
||||
r = crypt_activate_by_keyfile_offset(cd, action_argv[1], CRYPT_ANY_SLOT,
|
||||
opt_key_file, opt_keyfile_size,
|
||||
opt_keyfile_size, activate_flags);
|
||||
out:
|
||||
crypt_free(cd);
|
||||
|
||||
@@ -346,7 +417,7 @@ static int action_resize(int arg __attribute__((unused)))
|
||||
struct crypt_device *cd = NULL;
|
||||
int r;
|
||||
|
||||
r = crypt_init_by_name(&cd, action_argv[0]);
|
||||
r = crypt_init_by_name_and_header(&cd, action_argv[0], opt_header_device);
|
||||
if (r == 0)
|
||||
r = crypt_resize(cd, action_argv[0], opt_size);
|
||||
|
||||
@@ -359,23 +430,37 @@ static int action_status(int arg __attribute__((unused)))
|
||||
crypt_status_info ci;
|
||||
struct crypt_active_device cad;
|
||||
struct crypt_device *cd = NULL;
|
||||
struct stat st;
|
||||
char *backing_file;
|
||||
const char *device;
|
||||
int r = 0;
|
||||
int path = 0, r = 0;
|
||||
|
||||
/* perhaps a path, not a dm device name */
|
||||
if (strchr(action_argv[0], '/') && !stat(action_argv[0], &st))
|
||||
path = 1;
|
||||
|
||||
ci = crypt_status(NULL, action_argv[0]);
|
||||
switch (ci) {
|
||||
case CRYPT_INVALID:
|
||||
r = -ENODEV;
|
||||
r = -EINVAL;
|
||||
break;
|
||||
case CRYPT_INACTIVE:
|
||||
log_std("%s/%s is inactive.\n", crypt_get_dir(), action_argv[0]);
|
||||
if (path)
|
||||
log_std("%s is inactive.\n", action_argv[0]);
|
||||
else
|
||||
log_std("%s/%s is inactive.\n", crypt_get_dir(), action_argv[0]);
|
||||
r = -ENODEV;
|
||||
break;
|
||||
case CRYPT_ACTIVE:
|
||||
case CRYPT_BUSY:
|
||||
log_std("%s/%s is active%s.\n", crypt_get_dir(), action_argv[0],
|
||||
ci == CRYPT_BUSY ? " and is in use" : "");
|
||||
r = crypt_init_by_name(&cd, action_argv[0]);
|
||||
if (path)
|
||||
log_std("%s is active%s.\n", action_argv[0],
|
||||
ci == CRYPT_BUSY ? " and is in use" : "");
|
||||
else
|
||||
log_std("%s/%s is active%s.\n", crypt_get_dir(), action_argv[0],
|
||||
ci == CRYPT_BUSY ? " and is in use" : "");
|
||||
|
||||
r = crypt_init_by_name_and_header(&cd, action_argv[0], opt_header_device);
|
||||
if (r < 0 || !crypt_get_type(cd))
|
||||
goto out;
|
||||
|
||||
@@ -400,9 +485,13 @@ static int action_status(int arg __attribute__((unused)))
|
||||
log_std(" skipped: %" PRIu64 " sectors\n", cad.iv_offset);
|
||||
log_std(" mode: %s\n", cad.flags & CRYPT_ACTIVATE_READONLY ?
|
||||
"readonly" : "read/write");
|
||||
if (cad.flags & CRYPT_ACTIVATE_ALLOW_DISCARDS)
|
||||
log_std(" flags: discards\n");
|
||||
}
|
||||
out:
|
||||
crypt_free(cd);
|
||||
if (r == -ENOTSUP)
|
||||
r = 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -432,9 +521,36 @@ fail:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int action_luksRepair(int arg __attribute__((unused)))
|
||||
{
|
||||
struct crypt_device *cd = NULL;
|
||||
int r;
|
||||
|
||||
if ((r = crypt_init(&cd, action_argv[0])))
|
||||
goto out;
|
||||
|
||||
/* Currently only LUKS1 allows repair */
|
||||
crypt_set_log_callback(cd, _quiet_log, NULL);
|
||||
r = crypt_load(cd, CRYPT_LUKS1, NULL);
|
||||
crypt_set_log_callback(cd, _log, NULL);
|
||||
if (r == 0) {
|
||||
log_verbose( _("No known problems detected for LUKS header.\n"));
|
||||
goto out;
|
||||
}
|
||||
|
||||
r = _yesDialog(_("Really try to repair LUKS device header?"),
|
||||
NULL) ? 0 : -EINVAL;
|
||||
if (r == 0)
|
||||
r = crypt_repair(cd, CRYPT_LUKS1, NULL);
|
||||
out:
|
||||
crypt_free(cd);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int action_luksFormat(int arg __attribute__((unused)))
|
||||
{
|
||||
int r = -EINVAL, keysize;
|
||||
const char *header_device;
|
||||
char *msg = NULL, *key = NULL, cipher [MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN];
|
||||
char *password = NULL;
|
||||
size_t passwordLen;
|
||||
@@ -442,9 +558,13 @@ static int action_luksFormat(int arg __attribute__((unused)))
|
||||
struct crypt_params_luks1 params = {
|
||||
.hash = opt_hash ?: DEFAULT_LUKS1_HASH,
|
||||
.data_alignment = opt_align_payload,
|
||||
.data_device = opt_header_device ? action_argv[0] : NULL,
|
||||
};
|
||||
|
||||
if(asprintf(&msg, _("This will overwrite data on %s irrevocably."), action_argv[0]) == -1) {
|
||||
header_device = opt_header_device ?: action_argv[0];
|
||||
|
||||
if(asprintf(&msg, _("This will overwrite data on %s irrevocably."),
|
||||
header_device) == -1) {
|
||||
log_err(_("memory allocation error in action_luksFormat"));
|
||||
r = -ENOMEM;
|
||||
goto out;
|
||||
@@ -457,19 +577,21 @@ static int action_luksFormat(int arg __attribute__((unused)))
|
||||
r = crypt_parse_name_and_mode(opt_cipher ?: DEFAULT_CIPHER(LUKS1),
|
||||
cipher, NULL, cipher_mode);
|
||||
if (r < 0) {
|
||||
log_err("No known cipher specification pattern detected.\n");
|
||||
log_err(_("No known cipher specification pattern detected.\n"));
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((r = crypt_init(&cd, action_argv[0])))
|
||||
if ((r = crypt_init(&cd, header_device))) {
|
||||
if (opt_header_device)
|
||||
log_err(_("Cannot use %s as on-disk header.\n"), header_device);
|
||||
goto out;
|
||||
}
|
||||
|
||||
keysize = (opt_key_size ?: DEFAULT_LUKS1_KEYBITS) / 8;
|
||||
|
||||
crypt_set_password_verify(cd, 1);
|
||||
crypt_set_timeout(cd, opt_timeout);
|
||||
if (opt_iteration_time)
|
||||
crypt_set_iterarion_time(cd, opt_iteration_time);
|
||||
crypt_set_iteration_time(cd, opt_iteration_time);
|
||||
|
||||
if (opt_random)
|
||||
crypt_set_rng_type(cd, CRYPT_RNG_RANDOM);
|
||||
@@ -477,8 +599,8 @@ static int action_luksFormat(int arg __attribute__((unused)))
|
||||
crypt_set_rng_type(cd, CRYPT_RNG_URANDOM);
|
||||
|
||||
r = crypt_get_key(_("Enter LUKS passphrase: "), &password, &passwordLen,
|
||||
opt_keyfile_size, opt_key_file, opt_timeout,
|
||||
opt_batch_mode ? 0 : 1 /* always verify */, cd);
|
||||
opt_keyfile_offset, opt_keyfile_size, opt_key_file,
|
||||
opt_timeout, _verify_passphrase(1), cd);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
@@ -507,39 +629,75 @@ out:
|
||||
static int action_luksOpen(int arg __attribute__((unused)))
|
||||
{
|
||||
struct crypt_device *cd = NULL;
|
||||
const char *data_device, *header_device, *activated_name;
|
||||
char *key = NULL;
|
||||
uint32_t flags = 0;
|
||||
int r;
|
||||
int r, keysize;
|
||||
|
||||
if ((r = crypt_init(&cd, action_argv[0])))
|
||||
if (opt_header_device) {
|
||||
header_device = uuid_or_device(opt_header_device);
|
||||
data_device = action_argv[0];
|
||||
} else {
|
||||
header_device = uuid_or_device(action_argv[0]);
|
||||
data_device = NULL;
|
||||
}
|
||||
|
||||
activated_name = opt_test_passphrase ? NULL : action_argv[1];
|
||||
|
||||
if ((r = crypt_init(&cd, header_device)))
|
||||
goto out;
|
||||
|
||||
if ((r = crypt_load(cd, CRYPT_LUKS1, NULL)))
|
||||
goto out;
|
||||
|
||||
if (data_device &&
|
||||
(r = crypt_set_data_device(cd, data_device)))
|
||||
goto out;
|
||||
|
||||
if (!data_device && (crypt_get_data_offset(cd) < 8)) {
|
||||
log_err(_("Reduced data offset is allowed only for detached LUKS header.\n"));
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
crypt_set_timeout(cd, opt_timeout);
|
||||
crypt_set_password_retry(cd, opt_tries);
|
||||
crypt_set_password_verify(cd, _verify_passphrase(0));
|
||||
|
||||
if (opt_iteration_time)
|
||||
crypt_set_iterarion_time(cd, opt_iteration_time);
|
||||
crypt_set_iteration_time(cd, opt_iteration_time);
|
||||
|
||||
if (opt_readonly)
|
||||
flags |= CRYPT_ACTIVATE_READONLY;
|
||||
|
||||
if (opt_key_file) {
|
||||
if (opt_allow_discards)
|
||||
flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS;
|
||||
|
||||
if (opt_master_key_file) {
|
||||
keysize = crypt_get_volume_key_size(cd);
|
||||
r = _read_mk(opt_master_key_file, &key, keysize);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
r = crypt_activate_by_volume_key(cd, activated_name,
|
||||
key, keysize, flags);
|
||||
} else if (opt_key_file) {
|
||||
crypt_set_password_retry(cd, 1);
|
||||
r = crypt_activate_by_keyfile(cd, action_argv[1],
|
||||
CRYPT_ANY_SLOT, opt_key_file, opt_keyfile_size,
|
||||
flags);
|
||||
r = crypt_activate_by_keyfile_offset(cd, activated_name,
|
||||
opt_key_slot, opt_key_file, opt_keyfile_size,
|
||||
opt_keyfile_offset, flags);
|
||||
} else
|
||||
r = crypt_activate_by_passphrase(cd, action_argv[1],
|
||||
CRYPT_ANY_SLOT, NULL, 0, flags);
|
||||
r = crypt_activate_by_passphrase(cd, activated_name,
|
||||
opt_key_slot, NULL, 0, flags);
|
||||
out:
|
||||
crypt_safe_free(key);
|
||||
crypt_free(cd);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int verify_keyslot(struct crypt_device *cd, int key_slot,
|
||||
char *msg_last, char *msg_pass,
|
||||
const char *key_file, int keyfile_size)
|
||||
const char *key_file, int keyfile_offset,
|
||||
int keyfile_size)
|
||||
{
|
||||
crypt_keyslot_info ki;
|
||||
char *password = NULL;
|
||||
@@ -551,8 +709,8 @@ static int verify_keyslot(struct crypt_device *cd, int key_slot,
|
||||
return -EPERM;
|
||||
|
||||
r = crypt_get_key(msg_pass, &password, &passwordLen,
|
||||
keyfile_size, key_file, opt_timeout,
|
||||
opt_batch_mode ? 0 : opt_verify_passphrase, cd);
|
||||
keyfile_offset, keyfile_size, key_file, opt_timeout,
|
||||
_verify_passphrase(0), cd);
|
||||
if(r < 0)
|
||||
goto out;
|
||||
|
||||
@@ -586,7 +744,7 @@ static int action_luksKillSlot(int arg __attribute__((unused)))
|
||||
struct crypt_device *cd = NULL;
|
||||
int r;
|
||||
|
||||
if ((r = crypt_init(&cd, action_argv[0])))
|
||||
if ((r = crypt_init(&cd, uuid_or_device(action_argv[0]))))
|
||||
goto out;
|
||||
|
||||
crypt_set_confirm_callback(cd, _yesDialog, NULL);
|
||||
@@ -603,6 +761,7 @@ static int action_luksKillSlot(int arg __attribute__((unused)))
|
||||
case CRYPT_SLOT_INACTIVE:
|
||||
log_err(_("Key %d not active. Can't wipe.\n"), opt_key_slot);
|
||||
case CRYPT_SLOT_INVALID:
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -610,7 +769,7 @@ static int action_luksKillSlot(int arg __attribute__((unused)))
|
||||
r = verify_keyslot(cd, opt_key_slot,
|
||||
_("This is the last keyslot. Device will become unusable after purging this key."),
|
||||
_("Enter any remaining LUKS passphrase: "),
|
||||
opt_key_file, opt_keyfile_size);
|
||||
opt_key_file, opt_keyfile_offset, opt_keyfile_size);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
}
|
||||
@@ -628,7 +787,7 @@ static int action_luksRemoveKey(int arg __attribute__((unused)))
|
||||
size_t passwordLen;
|
||||
int r;
|
||||
|
||||
if ((r = crypt_init(&cd, action_argv[0])))
|
||||
if ((r = crypt_init(&cd, uuid_or_device(action_argv[0]))))
|
||||
goto out;
|
||||
|
||||
crypt_set_confirm_callback(cd, _yesDialog, NULL);
|
||||
@@ -639,9 +798,9 @@ static int action_luksRemoveKey(int arg __attribute__((unused)))
|
||||
|
||||
r = crypt_get_key(_("Enter LUKS passphrase to be deleted: "),
|
||||
&password, &passwordLen,
|
||||
opt_keyfile_size, opt_key_file,
|
||||
opt_keyfile_offset, opt_keyfile_size, opt_key_file,
|
||||
opt_timeout,
|
||||
opt_batch_mode ? 0 : opt_verify_passphrase,
|
||||
_verify_passphrase(0),
|
||||
cd);
|
||||
if(r < 0)
|
||||
goto out;
|
||||
@@ -676,7 +835,7 @@ static int action_luksAddKey(int arg __attribute__((unused)))
|
||||
const char *opt_new_key_file = (action_argc > 1 ? action_argv[1] : NULL);
|
||||
struct crypt_device *cd = NULL;
|
||||
|
||||
if ((r = crypt_init(&cd, action_argv[0])))
|
||||
if ((r = crypt_init(&cd, uuid_or_device(action_argv[0]))))
|
||||
goto out;
|
||||
|
||||
crypt_set_confirm_callback(cd, _yesDialog, NULL);
|
||||
@@ -685,10 +844,11 @@ static int action_luksAddKey(int arg __attribute__((unused)))
|
||||
goto out;
|
||||
|
||||
keysize = crypt_get_volume_key_size(cd);
|
||||
crypt_set_password_verify(cd, opt_verify_passphrase ? 1 : 0);
|
||||
/* FIXME: lib cannot properly set verification for new/old passphrase */
|
||||
crypt_set_password_verify(cd, _verify_passphrase(0));
|
||||
crypt_set_timeout(cd, opt_timeout);
|
||||
if (opt_iteration_time)
|
||||
crypt_set_iterarion_time(cd, opt_iteration_time);
|
||||
crypt_set_iteration_time(cd, opt_iteration_time);
|
||||
|
||||
if (opt_master_key_file) {
|
||||
r = _read_mk(opt_master_key_file, &key, keysize);
|
||||
@@ -698,9 +858,9 @@ static int action_luksAddKey(int arg __attribute__((unused)))
|
||||
r = crypt_keyslot_add_by_volume_key(cd, opt_key_slot,
|
||||
key, keysize, NULL, 0);
|
||||
} else if (opt_key_file || opt_new_key_file) {
|
||||
r = crypt_keyslot_add_by_keyfile(cd, opt_key_slot,
|
||||
opt_key_file, opt_keyfile_size,
|
||||
opt_new_key_file, opt_new_keyfile_size);
|
||||
r = crypt_keyslot_add_by_keyfile_offset(cd, opt_key_slot,
|
||||
opt_key_file, opt_keyfile_size, opt_keyfile_offset,
|
||||
opt_new_key_file, opt_new_keyfile_size, opt_new_keyfile_offset);
|
||||
} else {
|
||||
r = crypt_keyslot_add_by_passphrase(cd, opt_key_slot,
|
||||
NULL, 0, NULL, 0);
|
||||
@@ -730,19 +890,19 @@ static int action_luksChangeKey(int arg __attribute__((unused)))
|
||||
size_t vk_size;
|
||||
int new_key_slot, old_key_slot, r;
|
||||
|
||||
if ((r = crypt_init(&cd, action_argv[0])))
|
||||
if ((r = crypt_init(&cd, uuid_or_device(action_argv[0]))))
|
||||
goto out;
|
||||
|
||||
if ((r = crypt_load(cd, CRYPT_LUKS1, NULL)))
|
||||
goto out;
|
||||
|
||||
if (opt_iteration_time)
|
||||
crypt_set_iterarion_time(cd, opt_iteration_time);
|
||||
crypt_set_iteration_time(cd, opt_iteration_time);
|
||||
|
||||
r = crypt_get_key(_("Enter LUKS passphrase to be changed: "),
|
||||
&password, &passwordLen,
|
||||
opt_keyfile_size, opt_key_file, opt_timeout,
|
||||
opt_batch_mode ? 0 : opt_verify_passphrase, cd);
|
||||
opt_keyfile_offset, opt_keyfile_size, opt_key_file,
|
||||
opt_timeout, _verify_passphrase(0), cd);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
@@ -778,8 +938,9 @@ static int action_luksChangeKey(int arg __attribute__((unused)))
|
||||
passwordLen = 0;
|
||||
r = crypt_get_key(_("Enter new LUKS passphrase: "),
|
||||
&password, &passwordLen,
|
||||
opt_new_keyfile_size, opt_new_key_file,
|
||||
opt_timeout, opt_batch_mode ? 0 : 1, cd);
|
||||
opt_new_keyfile_offset, opt_new_keyfile_size,
|
||||
opt_new_key_file,
|
||||
opt_timeout, _verify_passphrase(0), cd);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
@@ -816,6 +977,7 @@ static int action_isLuks(int arg __attribute__((unused)))
|
||||
if ((r = crypt_init(&cd, action_argv[0])))
|
||||
goto out;
|
||||
|
||||
crypt_set_log_callback(cd, _quiet_log, NULL);
|
||||
r = crypt_load(cd, CRYPT_LUKS1, NULL);
|
||||
out:
|
||||
crypt_free(cd);
|
||||
@@ -870,7 +1032,8 @@ static int luksDump_with_volume_key(struct crypt_device *cd)
|
||||
return -ENOMEM;
|
||||
|
||||
r = crypt_get_key(_("Enter LUKS passphrase: "), &password, &passwordLen,
|
||||
opt_keyfile_size, opt_key_file, opt_timeout, 0, cd);
|
||||
opt_keyfile_offset, opt_keyfile_size, opt_key_file,
|
||||
opt_timeout, 0, cd);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
@@ -905,7 +1068,7 @@ static int action_luksDump(int arg __attribute__((unused)))
|
||||
struct crypt_device *cd = NULL;
|
||||
int r;
|
||||
|
||||
if ((r = crypt_init(&cd, action_argv[0])))
|
||||
if ((r = crypt_init(&cd, uuid_or_device(action_argv[0]))))
|
||||
goto out;
|
||||
|
||||
if ((r = crypt_load(cd, CRYPT_LUKS1, NULL)))
|
||||
@@ -925,7 +1088,7 @@ static int action_luksSuspend(int arg __attribute__((unused)))
|
||||
struct crypt_device *cd = NULL;
|
||||
int r;
|
||||
|
||||
r = crypt_init_by_name(&cd, action_argv[0]);
|
||||
r = crypt_init_by_name_and_header(&cd, action_argv[0], opt_header_device);
|
||||
if (!r)
|
||||
r = crypt_suspend(cd, action_argv[0]);
|
||||
|
||||
@@ -938,15 +1101,16 @@ static int action_luksResume(int arg __attribute__((unused)))
|
||||
struct crypt_device *cd = NULL;
|
||||
int r;
|
||||
|
||||
if ((r = crypt_init_by_name(&cd, action_argv[0])))
|
||||
if ((r = crypt_init_by_name_and_header(&cd, action_argv[0], opt_header_device)))
|
||||
goto out;
|
||||
|
||||
if ((r = crypt_load(cd, CRYPT_LUKS1, NULL)))
|
||||
goto out;
|
||||
crypt_set_timeout(cd, opt_timeout);
|
||||
crypt_set_password_retry(cd, opt_tries);
|
||||
crypt_set_password_verify(cd, _verify_passphrase(0));
|
||||
|
||||
if (opt_key_file)
|
||||
r = crypt_resume_by_keyfile(cd, action_argv[0], CRYPT_ANY_SLOT,
|
||||
opt_key_file, opt_keyfile_size);
|
||||
r = crypt_resume_by_keyfile_offset(cd, action_argv[0], CRYPT_ANY_SLOT,
|
||||
opt_key_file, opt_keyfile_size, opt_keyfile_offset);
|
||||
else
|
||||
r = crypt_resume_by_passphrase(cd, action_argv[0], CRYPT_ANY_SLOT,
|
||||
NULL, 0);
|
||||
@@ -965,7 +1129,7 @@ static int action_luksBackup(int arg __attribute__((unused)))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((r = crypt_init(&cd, action_argv[0])))
|
||||
if ((r = crypt_init(&cd, uuid_or_device(action_argv[0]))))
|
||||
goto out;
|
||||
|
||||
crypt_set_confirm_callback(cd, _yesDialog, NULL);
|
||||
@@ -1003,6 +1167,7 @@ static __attribute__ ((noreturn)) void usage(poptContext popt_context,
|
||||
poptPrintUsage(popt_context, stderr, 0);
|
||||
if (error)
|
||||
log_err("%s: %s\n", more, error);
|
||||
poptFreeContext(popt_context);
|
||||
exit(exitcode);
|
||||
}
|
||||
|
||||
@@ -1122,7 +1287,9 @@ int main(int argc, const char **argv)
|
||||
{ "dump-master-key", '\0', POPT_ARG_NONE, &opt_dump_master_key, 0, N_("Dump volume (master) key instead of keyslots info."), NULL },
|
||||
{ "key-size", 's', POPT_ARG_INT, &opt_key_size, 0, N_("The size of the encryption key"), N_("BITS") },
|
||||
{ "keyfile-size", 'l', POPT_ARG_LONG, &opt_keyfile_size, 0, N_("Limits the read from keyfile"), N_("bytes") },
|
||||
{ "keyfile-offset", '\0', POPT_ARG_LONG, &opt_keyfile_offset, 0, N_("Number of bytes to skip in keyfile"), N_("bytes") },
|
||||
{ "new-keyfile-size", '\0', POPT_ARG_LONG, &opt_new_keyfile_size, 0, N_("Limits the read from newly added keyfile"), N_("bytes") },
|
||||
{ "new-keyfile-offset",'\0', POPT_ARG_LONG, &opt_new_keyfile_offset, 0, N_("Number of bytes to skip in newly added keyfile"), N_("bytes") },
|
||||
{ "key-slot", 'S', POPT_ARG_INT, &opt_key_slot, 0, N_("Slot number for new key (default is first free)"), NULL },
|
||||
{ "size", 'b', POPT_ARG_STRING, &popt_tmp, 1, N_("The size of the device"), N_("SECTORS") },
|
||||
{ "offset", 'o', POPT_ARG_STRING, &popt_tmp, 2, N_("The start offset in the backend device"), N_("SECTORS") },
|
||||
@@ -1136,7 +1303,11 @@ int main(int argc, const char **argv)
|
||||
{ "header-backup-file",'\0', POPT_ARG_STRING, &opt_header_backup_file, 0, N_("File with LUKS header and keyslots backup."), NULL },
|
||||
{ "use-random", '\0', POPT_ARG_NONE, &opt_random, 0, N_("Use /dev/random for generating volume key."), NULL },
|
||||
{ "use-urandom", '\0', POPT_ARG_NONE, &opt_urandom, 0, N_("Use /dev/urandom for generating volume key."), NULL },
|
||||
{ "uuid", '\0', POPT_ARG_STRING, &opt_uuid, 0, N_("UUID for device to use."), NULL },
|
||||
{ "shared", '\0', POPT_ARG_NONE, &opt_shared, 0, N_("Share device with another non-overlapping crypt segment."), NULL },
|
||||
{ "uuid", '\0', POPT_ARG_STRING, &opt_uuid, 0, N_("UUID for device to use."), NULL },
|
||||
{ "allow-discards", '\0', POPT_ARG_NONE, &opt_allow_discards, 0, N_("Allow discards (aka TRIM) requests for device."), NULL },
|
||||
{ "header", '\0', POPT_ARG_STRING, &opt_header_device, 0, N_("Device or file with separated LUKS header."), NULL },
|
||||
{ "test-passphrase", '\0', POPT_ARG_NONE, &opt_test_passphrase, 0, N_("Do not activate device, just check passphrase."), NULL },
|
||||
POPT_TABLEEND
|
||||
};
|
||||
poptContext popt_context;
|
||||
@@ -1151,16 +1322,21 @@ int main(int argc, const char **argv)
|
||||
bindtextdomain(PACKAGE, LOCALEDIR);
|
||||
textdomain(PACKAGE);
|
||||
|
||||
crypt_fips_self_check(NULL);
|
||||
|
||||
popt_context = poptGetContext(PACKAGE, argc, argv, popt_options, 0);
|
||||
poptSetOtherOptionHelp(popt_context,
|
||||
N_("[OPTION...] <action> <action-specific>]"));
|
||||
_("[OPTION...] <action> <action-specific>"));
|
||||
|
||||
while((r = poptGetNextOpt(popt_context)) > 0) {
|
||||
unsigned long long ull_value;
|
||||
char *endp;
|
||||
|
||||
errno = 0;
|
||||
ull_value = strtoull(popt_tmp, &endp, 0);
|
||||
if (*endp || !*popt_tmp)
|
||||
if (*endp || !*popt_tmp ||
|
||||
(errno == ERANGE && ull_value == ULLONG_MAX) ||
|
||||
(errno != 0 && ull_value == 0))
|
||||
r = POPT_ERROR_BADNUMBER;
|
||||
|
||||
switch(r) {
|
||||
@@ -1185,6 +1361,7 @@ int main(int argc, const char **argv)
|
||||
poptBadOption(popt_context, POPT_BADOPTION_NOALIAS));
|
||||
if (opt_version_mode) {
|
||||
log_std("%s %s\n", PACKAGE_NAME, PACKAGE_VERSION);
|
||||
poptFreeContext(popt_context);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
@@ -1217,15 +1394,33 @@ int main(int argc, const char **argv)
|
||||
|
||||
/* FIXME: rewrite this from scratch */
|
||||
|
||||
if (opt_shared && strcmp(aname, "create"))
|
||||
usage(popt_context, EXIT_FAILURE,
|
||||
_("Option --shared is allowed only for create operation.\n"),
|
||||
poptGetInvocationName(popt_context));
|
||||
|
||||
if (opt_allow_discards &&
|
||||
strcmp(aname, "luksOpen") &&
|
||||
strcmp(aname, "create") &&
|
||||
strcmp(aname, "loopaesOpen"))
|
||||
usage(popt_context, EXIT_FAILURE,
|
||||
_("Option --allow-discards is allowed only for luksOpen, loopaesOpen and create operation.\n"),
|
||||
poptGetInvocationName(popt_context));
|
||||
|
||||
if (opt_key_size &&
|
||||
strcmp(aname, "luksFormat") &&
|
||||
strcmp(aname, "create") &&
|
||||
strcmp(aname, "loopaesOpen")) {
|
||||
strcmp(aname, "loopaesOpen"))
|
||||
usage(popt_context, EXIT_FAILURE,
|
||||
_("Option --key-size is allowed only for luksFormat, create and loopaesOpen.\n"
|
||||
"To limit read from keyfile use --keyfile-size=(bytes)."),
|
||||
poptGetInvocationName(popt_context));
|
||||
}
|
||||
|
||||
if (opt_test_passphrase &&
|
||||
strcmp(aname, "luksOpen"))
|
||||
usage(popt_context, EXIT_FAILURE,
|
||||
_("Option --test-passphrase is allowed only for luksOpen.\n"),
|
||||
poptGetInvocationName(popt_context));
|
||||
|
||||
if (opt_key_size % 8)
|
||||
usage(popt_context, EXIT_FAILURE,
|
||||
@@ -1235,7 +1430,7 @@ int main(int argc, const char **argv)
|
||||
if (!strcmp(aname, "luksKillSlot") && action_argc > 1)
|
||||
opt_key_slot = atoi(action_argv[1]);
|
||||
if (opt_key_slot != CRYPT_ANY_SLOT &&
|
||||
(opt_key_slot < 0 || opt_key_slot > crypt_keyslot_max(CRYPT_LUKS1)))
|
||||
(opt_key_slot < 0 || opt_key_slot >= crypt_keyslot_max(CRYPT_LUKS1)))
|
||||
usage(popt_context, EXIT_FAILURE, _("Key slot is invalid."),
|
||||
poptGetInvocationName(popt_context));
|
||||
|
||||
@@ -1248,15 +1443,16 @@ int main(int argc, const char **argv)
|
||||
opt_key_file = action_argv[1];
|
||||
}
|
||||
|
||||
if (opt_keyfile_size < 0 || opt_new_keyfile_size < 0 || opt_key_size < 0) {
|
||||
if (opt_keyfile_size < 0 || opt_new_keyfile_size < 0 || opt_key_size < 0 ||
|
||||
opt_keyfile_offset < 0 || opt_new_keyfile_offset < 0)
|
||||
usage(popt_context, EXIT_FAILURE,
|
||||
_("Negative number for option not permitted."),
|
||||
poptGetInvocationName(popt_context));
|
||||
}
|
||||
|
||||
if (opt_random && opt_urandom)
|
||||
usage(popt_context, EXIT_FAILURE, _("Only one of --use-[u]random options is allowed."),
|
||||
poptGetInvocationName(popt_context));
|
||||
|
||||
if ((opt_random || opt_urandom) && strcmp(aname, "luksFormat"))
|
||||
usage(popt_context, EXIT_FAILURE, _("Option --use-[u]random is allowed only for luksFormat."),
|
||||
poptGetInvocationName(popt_context));
|
||||
@@ -1265,6 +1461,10 @@ int main(int argc, const char **argv)
|
||||
usage(popt_context, EXIT_FAILURE, _("Option --uuid is allowed only for luksFormat and luksUUID."),
|
||||
poptGetInvocationName(popt_context));
|
||||
|
||||
if (opt_align_payload && strcmp(aname, "luksFormat"))
|
||||
usage(popt_context, EXIT_FAILURE, _("Option --align-payload is allowed only for luksFormat."),
|
||||
poptGetInvocationName(popt_context));
|
||||
|
||||
if (opt_skip && strcmp(aname, "create") && strcmp(aname, "loopaesOpen"))
|
||||
usage(popt_context, EXIT_FAILURE,
|
||||
_("Option --skip is supported only for create and loopaesOpen commands.\n"),
|
||||
@@ -1281,5 +1481,7 @@ int main(int argc, const char **argv)
|
||||
_dbg_version_and_cmd(argc, argv);
|
||||
}
|
||||
|
||||
return run_action(action);
|
||||
r = run_action(action);
|
||||
poptFreeContext(popt_context);
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,24 @@
|
||||
/*
|
||||
* cryptsetup - setup cryptographic volumes for dm-crypt
|
||||
*
|
||||
* Copyright (C) 2004, Christophe Saout <christophe@saout.de>
|
||||
* Copyright (C) 2004-2007, Clemens Fruhwirth <clemens@endorphin.org>
|
||||
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef CRYPTSETUP_H
|
||||
#define CRYPTSETUP_H
|
||||
|
||||
@@ -6,6 +27,11 @@
|
||||
#include "lib/nls.h"
|
||||
#include "lib/utils_crypt.h"
|
||||
#include "lib/utils_loop.h"
|
||||
#include "lib/utils_fips.h"
|
||||
|
||||
#include "libcryptsetup.h"
|
||||
|
||||
#define CONST_CAST(x) (x)(uintptr_t)
|
||||
|
||||
#define DEFAULT_CIPHER(type) (DEFAULT_##type##_CIPHER "-" DEFAULT_##type##_MODE)
|
||||
|
||||
|
||||
1360
src/cryptsetup_reencrypt.c
Normal file
1360
src/cryptsetup_reencrypt.c
Normal file
File diff suppressed because it is too large
Load Diff
598
src/veritysetup.c
Normal file
598
src/veritysetup.c
Normal file
@@ -0,0 +1,598 @@
|
||||
/*
|
||||
* veritysetup - setup cryptographic volumes for dm-verity
|
||||
*
|
||||
* Copyright (C) 2012, Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <inttypes.h>
|
||||
#include <popt.h>
|
||||
#include <limits.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "cryptsetup.h"
|
||||
|
||||
#define PACKAGE_VERITY "veritysetup"
|
||||
|
||||
static int use_superblock = 1;
|
||||
|
||||
static const char *hash_algorithm = NULL;
|
||||
static int hash_type = 1;
|
||||
static int data_block_size = DEFAULT_VERITY_DATA_BLOCK;
|
||||
static int hash_block_size = DEFAULT_VERITY_HASH_BLOCK;
|
||||
static uint64_t data_blocks = 0;
|
||||
static const char *salt_string = NULL;
|
||||
static uint64_t hash_offset = 0;
|
||||
static const char *opt_uuid = NULL;
|
||||
|
||||
static int opt_verbose = 0;
|
||||
static int opt_debug = 0;
|
||||
static int opt_version_mode = 0;
|
||||
|
||||
static const char **action_argv;
|
||||
static int action_argc;
|
||||
|
||||
__attribute__((format(printf, 5, 6)))
|
||||
static void clogger(struct crypt_device *cd, int level, const char *file,
|
||||
int line, const char *format, ...)
|
||||
{
|
||||
va_list argp;
|
||||
char *target = NULL;
|
||||
|
||||
va_start(argp, format);
|
||||
|
||||
if (vasprintf(&target, format, argp) > 0) {
|
||||
if (level >= 0) {
|
||||
crypt_log(cd, level, target);
|
||||
#ifdef CRYPT_DEBUG
|
||||
} else if (opt_debug)
|
||||
printf("# %s:%d %s\n", file ?: "?", line, target);
|
||||
#else
|
||||
} else if (opt_debug)
|
||||
printf("# %s\n", target);
|
||||
#endif
|
||||
}
|
||||
|
||||
va_end(argp);
|
||||
free(target);
|
||||
}
|
||||
|
||||
static void _log(int level, const char *msg, void *usrptr __attribute__((unused)))
|
||||
{
|
||||
switch(level) {
|
||||
|
||||
case CRYPT_LOG_NORMAL:
|
||||
fputs(msg, stdout);
|
||||
break;
|
||||
case CRYPT_LOG_VERBOSE:
|
||||
if (opt_verbose)
|
||||
fputs(msg, stdout);
|
||||
break;
|
||||
case CRYPT_LOG_ERROR:
|
||||
fputs(msg, stderr);
|
||||
break;
|
||||
case CRYPT_LOG_DEBUG:
|
||||
if (opt_debug)
|
||||
printf("# %s\n", msg);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Internal error on logging class for msg: %s", msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int _prepare_format(struct crypt_params_verity *params,
|
||||
const char *data_device,
|
||||
uint32_t flags)
|
||||
{
|
||||
char *salt = NULL;
|
||||
int len;
|
||||
|
||||
params->hash_name = hash_algorithm ?: DEFAULT_VERITY_HASH;
|
||||
params->data_device = data_device;
|
||||
|
||||
if (salt_string && !strcmp(salt_string, "-")) {
|
||||
params->salt_size = 0;
|
||||
params->salt = NULL;
|
||||
} else if (salt_string) {
|
||||
len = crypt_hex_to_bytes(salt_string, &salt, 0);
|
||||
if (len < 0) {
|
||||
log_err(_("Invalid salt string specified.\n"));
|
||||
return -EINVAL;
|
||||
}
|
||||
params->salt_size = len;
|
||||
params->salt = salt;
|
||||
} else {
|
||||
params->salt_size = DEFAULT_VERITY_SALT_SIZE;
|
||||
params->salt = NULL;
|
||||
}
|
||||
|
||||
params->data_block_size = data_block_size;
|
||||
params->hash_block_size = hash_block_size;
|
||||
params->data_size = data_blocks;
|
||||
params->hash_area_offset = hash_offset;
|
||||
params->hash_type = hash_type;
|
||||
params->flags = flags;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int action_format(int arg)
|
||||
{
|
||||
struct crypt_device *cd = NULL;
|
||||
struct crypt_params_verity params = {};
|
||||
uint32_t flags = CRYPT_VERITY_CREATE_HASH;
|
||||
int r;
|
||||
|
||||
if ((r = crypt_init(&cd, action_argv[1])))
|
||||
goto out;
|
||||
|
||||
if (!use_superblock)
|
||||
flags |= CRYPT_VERITY_NO_HEADER;
|
||||
|
||||
r = _prepare_format(¶ms, action_argv[0], flags);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
r = crypt_format(cd, CRYPT_VERITY, NULL, NULL, opt_uuid, NULL, 0, ¶ms);
|
||||
if (!r)
|
||||
crypt_dump(cd);
|
||||
out:
|
||||
crypt_free(cd);
|
||||
free(CONST_CAST(char*)params.salt);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _activate(const char *dm_device,
|
||||
const char *data_device,
|
||||
const char *hash_device,
|
||||
const char *root_hash,
|
||||
uint32_t flags)
|
||||
{
|
||||
struct crypt_device *cd = NULL;
|
||||
struct crypt_params_verity params = {};
|
||||
uint32_t activate_flags = CRYPT_ACTIVATE_READONLY;
|
||||
char *root_hash_bytes = NULL;
|
||||
ssize_t hash_size;
|
||||
int r;
|
||||
|
||||
if ((r = crypt_init(&cd, hash_device)))
|
||||
goto out;
|
||||
|
||||
if (use_superblock) {
|
||||
params.flags = flags;
|
||||
params.hash_area_offset = hash_offset;
|
||||
r = crypt_load(cd, CRYPT_VERITY, ¶ms);
|
||||
} else {
|
||||
r = _prepare_format(¶ms, data_device, flags | CRYPT_VERITY_NO_HEADER);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
r = crypt_format(cd, CRYPT_VERITY, NULL, NULL, NULL, NULL, 0, ¶ms);
|
||||
}
|
||||
if (r < 0)
|
||||
goto out;
|
||||
r = crypt_set_data_device(cd, data_device);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
hash_size = crypt_get_volume_key_size(cd);
|
||||
if (crypt_hex_to_bytes(root_hash, &root_hash_bytes, 0) != hash_size) {
|
||||
log_err(_("Invalid root hash string specified.\n"));
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
r = crypt_activate_by_volume_key(cd, dm_device,
|
||||
root_hash_bytes,
|
||||
hash_size,
|
||||
activate_flags);
|
||||
out:
|
||||
crypt_free(cd);
|
||||
free(root_hash_bytes);
|
||||
free(CONST_CAST(char*)params.salt);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int action_create(int arg)
|
||||
{
|
||||
return _activate(action_argv[0],
|
||||
action_argv[1],
|
||||
action_argv[2],
|
||||
action_argv[3], 0);
|
||||
}
|
||||
|
||||
static int action_verify(int arg)
|
||||
{
|
||||
return _activate(NULL,
|
||||
action_argv[0],
|
||||
action_argv[1],
|
||||
action_argv[2],
|
||||
CRYPT_VERITY_CHECK_HASH);
|
||||
}
|
||||
|
||||
static int action_remove(int arg)
|
||||
{
|
||||
struct crypt_device *cd = NULL;
|
||||
int r;
|
||||
|
||||
r = crypt_init_by_name(&cd, action_argv[0]);
|
||||
if (r == 0)
|
||||
r = crypt_deactivate(cd, action_argv[0]);
|
||||
|
||||
crypt_free(cd);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int action_status(int arg)
|
||||
{
|
||||
crypt_status_info ci;
|
||||
struct crypt_active_device cad;
|
||||
struct crypt_params_verity vp = {};
|
||||
struct crypt_device *cd = NULL;
|
||||
struct stat st;
|
||||
char *backing_file;
|
||||
unsigned i, path = 0;
|
||||
int r = 0;
|
||||
|
||||
/* perhaps a path, not a dm device name */
|
||||
if (strchr(action_argv[0], '/') && !stat(action_argv[0], &st))
|
||||
path = 1;
|
||||
|
||||
ci = crypt_status(NULL, action_argv[0]);
|
||||
switch (ci) {
|
||||
case CRYPT_INVALID:
|
||||
r = -EINVAL;
|
||||
break;
|
||||
case CRYPT_INACTIVE:
|
||||
if (path)
|
||||
log_std("%s is inactive.\n", action_argv[0]);
|
||||
else
|
||||
log_std("%s/%s is inactive.\n", crypt_get_dir(), action_argv[0]);
|
||||
r = -ENODEV;
|
||||
break;
|
||||
case CRYPT_ACTIVE:
|
||||
case CRYPT_BUSY:
|
||||
if (path)
|
||||
log_std("%s is active%s.\n", action_argv[0],
|
||||
ci == CRYPT_BUSY ? " and is in use" : "");
|
||||
else
|
||||
log_std("%s/%s is active%s.\n", crypt_get_dir(), action_argv[0],
|
||||
ci == CRYPT_BUSY ? " and is in use" : "");
|
||||
|
||||
r = crypt_init_by_name_and_header(&cd, action_argv[0], NULL);
|
||||
if (r < 0 || !crypt_get_type(cd))
|
||||
goto out;
|
||||
|
||||
log_std(" type: %s\n", crypt_get_type(cd));
|
||||
|
||||
r = crypt_get_active_device(cd, action_argv[0], &cad);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
log_std(" status: %s\n",
|
||||
cad.flags & CRYPT_ACTIVATE_CORRUPTED ? "corrupted" : "verified");
|
||||
|
||||
r = crypt_get_verity_info(cd, &vp);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
log_std(" hash type: %u\n", vp.hash_type);
|
||||
log_std(" data block: %u\n", vp.data_block_size);
|
||||
log_std(" hash block: %u\n", vp.hash_block_size);
|
||||
log_std(" hash name: %s\n", vp.hash_name);
|
||||
log_std(" salt: ");
|
||||
if (vp.salt_size)
|
||||
for(i = 0; i < vp.salt_size; i++)
|
||||
log_std("%02hhx", (const char)vp.salt[i]);
|
||||
else
|
||||
log_std("-");
|
||||
log_std("\n");
|
||||
|
||||
log_std(" data device: %s\n", vp.data_device);
|
||||
if (crypt_loop_device(vp.data_device)) {
|
||||
backing_file = crypt_loop_backing_file(vp.data_device);
|
||||
log_std(" data loop: %s\n", backing_file);
|
||||
free(backing_file);
|
||||
}
|
||||
log_std(" size: %" PRIu64 " sectors\n", cad.size);
|
||||
log_std(" mode: %s\n", cad.flags & CRYPT_ACTIVATE_READONLY ?
|
||||
"readonly" : "read/write");
|
||||
|
||||
log_std(" hash device: %s\n", vp.hash_device);
|
||||
if (crypt_loop_device(vp.hash_device)) {
|
||||
backing_file = crypt_loop_backing_file(vp.hash_device);
|
||||
log_std(" hash loop: %s\n", backing_file);
|
||||
free(backing_file);
|
||||
}
|
||||
log_std(" hash offset: %" PRIu64 " sectors\n",
|
||||
vp.hash_area_offset * vp.hash_block_size / 512);
|
||||
}
|
||||
out:
|
||||
crypt_free(cd);
|
||||
if (r == -ENOTSUP)
|
||||
r = 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
static int action_dump(int arg)
|
||||
{
|
||||
struct crypt_device *cd = NULL;
|
||||
struct crypt_params_verity params = {};
|
||||
int r;
|
||||
|
||||
if ((r = crypt_init(&cd, action_argv[0])))
|
||||
return r;
|
||||
|
||||
params.hash_area_offset = hash_offset;
|
||||
r = crypt_load(cd, CRYPT_VERITY, ¶ms);
|
||||
if (!r)
|
||||
crypt_dump(cd);
|
||||
crypt_free(cd);
|
||||
return r;
|
||||
}
|
||||
|
||||
static __attribute__ ((noreturn)) void usage(poptContext popt_context,
|
||||
int exitcode, const char *error,
|
||||
const char *more)
|
||||
{
|
||||
poptPrintUsage(popt_context, stderr, 0);
|
||||
if (error)
|
||||
log_err("%s: %s\n", more, error);
|
||||
poptFreeContext(popt_context);
|
||||
exit(exitcode);
|
||||
}
|
||||
|
||||
static void _dbg_version_and_cmd(int argc, const char **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
log_std("# %s %s processing \"", PACKAGE_VERITY, PACKAGE_VERSION);
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (i)
|
||||
log_std(" ");
|
||||
log_std("%s", argv[i]);
|
||||
}
|
||||
log_std("\"\n");
|
||||
}
|
||||
|
||||
static struct action_type {
|
||||
const char *type;
|
||||
int (*handler)(int);
|
||||
int required_action_argc;
|
||||
const char *arg_desc;
|
||||
const char *desc;
|
||||
} action_types[] = {
|
||||
{ "format", action_format, 2, N_("<data_device> <hash_device>"),N_("format device") },
|
||||
{ "verify", action_verify, 3, N_("<data_device> <hash_device> <root_hash>"),N_("verify device") },
|
||||
{ "create", action_create, 4, N_("<name> <data_device> <hash_device> <root_hash>"),N_("create active device") },
|
||||
{ "remove", action_remove, 1, N_("<name>"),N_("remove (deactivate) device") },
|
||||
{ "status", action_status, 1, N_("<name>"),N_("show active device status") },
|
||||
{ "dump", action_dump, 1, N_("<hash_device>"),N_("show on-disk information") },
|
||||
{ NULL, NULL, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static void help(poptContext popt_context,
|
||||
enum poptCallbackReason reason __attribute__((unused)),
|
||||
struct poptOption *key,
|
||||
const char *arg __attribute__((unused)),
|
||||
void *data __attribute__((unused)))
|
||||
{
|
||||
struct action_type *action;
|
||||
|
||||
if (key->shortName == '?') {
|
||||
log_std("%s %s\n", PACKAGE_VERITY, PACKAGE_VERSION);
|
||||
poptPrintHelp(popt_context, stdout, 0);
|
||||
log_std(_("\n"
|
||||
"<action> is one of:\n"));
|
||||
for(action = action_types; action->type; action++)
|
||||
log_std("\t%s %s - %s\n", action->type, _(action->arg_desc), _(action->desc));
|
||||
log_std(_("\n"
|
||||
"<name> is the device to create under %s\n"
|
||||
"<data_device> is the data device\n"
|
||||
"<hash_device> is the device containing verification data\n"
|
||||
"<root_hash> hash of the root node on <hash_device>\n"),
|
||||
crypt_get_dir());
|
||||
|
||||
log_std(_("\nDefault compiled-in dm-verity parameters:\n"
|
||||
"\tHash: %s, Data block (bytes): %u, "
|
||||
"Hash block (bytes): %u, Salt size: %u, Hash format: %u\n"),
|
||||
DEFAULT_VERITY_HASH, DEFAULT_VERITY_DATA_BLOCK,
|
||||
DEFAULT_VERITY_HASH_BLOCK, DEFAULT_VERITY_SALT_SIZE,
|
||||
1);
|
||||
exit(EXIT_SUCCESS);
|
||||
} else
|
||||
usage(popt_context, EXIT_SUCCESS, NULL, NULL);
|
||||
}
|
||||
|
||||
static void show_status(int errcode)
|
||||
{
|
||||
char error[256], *error_;
|
||||
|
||||
if(!opt_verbose)
|
||||
return;
|
||||
|
||||
if(!errcode) {
|
||||
log_std(_("Command successful.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
crypt_get_error(error, sizeof(error));
|
||||
|
||||
if (!error[0]) {
|
||||
error_ = strerror_r(-errcode, error, sizeof(error));
|
||||
if (error_ != error) {
|
||||
strncpy(error, error_, sizeof(error));
|
||||
error[sizeof(error) - 1] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
log_err(_("Command failed with code %i"), -errcode);
|
||||
if (*error)
|
||||
log_err(": %s\n", error);
|
||||
else
|
||||
log_err(".\n");
|
||||
}
|
||||
|
||||
static int run_action(struct action_type *action)
|
||||
{
|
||||
int r;
|
||||
|
||||
log_dbg("Running command %s.", action->type);
|
||||
|
||||
r = action->handler(0);
|
||||
|
||||
show_status(r);
|
||||
|
||||
/* Translate exit code to simple codes */
|
||||
switch (r) {
|
||||
case 0: r = EXIT_SUCCESS; break;
|
||||
case -EEXIST:
|
||||
case -EBUSY: r = 5; break;
|
||||
case -ENOTBLK:
|
||||
case -ENODEV: r = 4; break;
|
||||
case -ENOMEM: r = 3; break;
|
||||
case -EPERM: r = 2; break;
|
||||
case -EINVAL:
|
||||
case -ENOENT:
|
||||
case -ENOSYS:
|
||||
default: r = EXIT_FAILURE;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
static char *popt_tmp;
|
||||
static const char *null_action_argv[] = {NULL};
|
||||
static struct poptOption popt_help_options[] = {
|
||||
{ NULL, '\0', POPT_ARG_CALLBACK, help, 0, NULL, NULL },
|
||||
{ "help", '?', POPT_ARG_NONE, NULL, 0, N_("Show this help message"), NULL },
|
||||
{ "usage", '\0', POPT_ARG_NONE, NULL, 0, N_("Display brief usage"), NULL },
|
||||
POPT_TABLEEND
|
||||
};
|
||||
static struct poptOption popt_options[] = {
|
||||
{ NULL, '\0', POPT_ARG_INCLUDE_TABLE, popt_help_options, 0, N_("Help options:"), NULL },
|
||||
{ "version", '\0', POPT_ARG_NONE, &opt_version_mode, 0, N_("Print package version"), NULL },
|
||||
{ "verbose", 'v', POPT_ARG_NONE, &opt_verbose, 0, N_("Shows more detailed error messages"), NULL },
|
||||
{ "debug", '\0', POPT_ARG_NONE, &opt_debug, 0, N_("Show debug messages"), NULL },
|
||||
{ "no-superblock", 0, POPT_ARG_VAL, &use_superblock, 0, N_("Do not use verity superblock"), NULL },
|
||||
{ "format", 0, POPT_ARG_INT, &hash_type, 0, N_("Format type (1 - normal, 0 - original Chrome OS)"), N_("number") },
|
||||
{ "data-block-size", 0, POPT_ARG_INT, &data_block_size, 0, N_("Block size on the data device"), N_("bytes") },
|
||||
{ "hash-block-size", 0, POPT_ARG_INT, &hash_block_size, 0, N_("Block size on the hash device"), N_("bytes") },
|
||||
{ "data-blocks", 0, POPT_ARG_STRING, &popt_tmp, 1, N_("The number of blocks in the data file"), N_("blocks") },
|
||||
{ "hash-offset", 0, POPT_ARG_STRING, &popt_tmp, 2, N_("Starting offset on the hash device"), N_("bytes") },
|
||||
{ "hash", 'h', POPT_ARG_STRING, &hash_algorithm, 0, N_("Hash algorithm"), N_("string") },
|
||||
{ "salt", 's', POPT_ARG_STRING, &salt_string, 0, N_("Salt"), N_("hex string") },
|
||||
{ "uuid", '\0', POPT_ARG_STRING, &opt_uuid, 0, N_("UUID for device to use."), NULL },
|
||||
POPT_TABLEEND
|
||||
};
|
||||
|
||||
poptContext popt_context;
|
||||
struct action_type *action;
|
||||
const char *aname;
|
||||
int r;
|
||||
|
||||
crypt_set_log_callback(NULL, _log, NULL);
|
||||
|
||||
setlocale(LC_ALL, "");
|
||||
bindtextdomain(PACKAGE, LOCALEDIR);
|
||||
textdomain(PACKAGE);
|
||||
|
||||
popt_context = poptGetContext("verity", argc, argv, popt_options, 0);
|
||||
poptSetOtherOptionHelp(popt_context,
|
||||
_("[OPTION...] <action> <action-specific>"));
|
||||
|
||||
while((r = poptGetNextOpt(popt_context)) > 0) {
|
||||
unsigned long long ull_value;
|
||||
char *endp;
|
||||
|
||||
errno = 0;
|
||||
ull_value = strtoull(popt_tmp, &endp, 10);
|
||||
if (*endp || !*popt_tmp || !isdigit(*popt_tmp) ||
|
||||
(errno == ERANGE && ull_value == ULLONG_MAX) ||
|
||||
(errno != 0 && ull_value == 0))
|
||||
r = POPT_ERROR_BADNUMBER;
|
||||
|
||||
switch(r) {
|
||||
case 1:
|
||||
data_blocks = ull_value;
|
||||
break;
|
||||
case 2:
|
||||
hash_offset = ull_value;
|
||||
break;
|
||||
}
|
||||
|
||||
if (r < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (r < -1)
|
||||
usage(popt_context, EXIT_FAILURE, poptStrerror(r),
|
||||
poptBadOption(popt_context, POPT_BADOPTION_NOALIAS));
|
||||
|
||||
if (opt_version_mode) {
|
||||
log_std("%s %s\n", PACKAGE_VERITY, PACKAGE_VERSION);
|
||||
poptFreeContext(popt_context);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
if (!(aname = poptGetArg(popt_context)))
|
||||
usage(popt_context, EXIT_FAILURE, _("Argument <action> missing."),
|
||||
poptGetInvocationName(popt_context));
|
||||
for(action = action_types; action->type; action++)
|
||||
if (strcmp(action->type, aname) == 0)
|
||||
break;
|
||||
if (!action->type)
|
||||
usage(popt_context, EXIT_FAILURE, _("Unknown action."),
|
||||
poptGetInvocationName(popt_context));
|
||||
|
||||
action_argc = 0;
|
||||
action_argv = poptGetArgs(popt_context);
|
||||
/* Make return values of poptGetArgs more consistent in case of remaining argc = 0 */
|
||||
if(!action_argv)
|
||||
action_argv = null_action_argv;
|
||||
|
||||
/* Count args, somewhat unnice, change? */
|
||||
while(action_argv[action_argc] != NULL)
|
||||
action_argc++;
|
||||
|
||||
if(action_argc < action->required_action_argc) {
|
||||
char buf[128];
|
||||
snprintf(buf, 128,_("%s: requires %s as arguments"), action->type, action->arg_desc);
|
||||
usage(popt_context, EXIT_FAILURE, buf,
|
||||
poptGetInvocationName(popt_context));
|
||||
}
|
||||
|
||||
if (data_block_size < 0 || hash_block_size < 0 || hash_type < 0) {
|
||||
usage(popt_context, EXIT_FAILURE,
|
||||
_("Negative number for option not permitted."),
|
||||
poptGetInvocationName(popt_context));
|
||||
}
|
||||
|
||||
if (opt_debug) {
|
||||
opt_verbose = 1;
|
||||
crypt_set_debug_level(-1);
|
||||
_dbg_version_and_cmd(argc, argv);
|
||||
}
|
||||
|
||||
r = run_action(action);
|
||||
poptFreeContext(popt_context);
|
||||
return r;
|
||||
}
|
||||
@@ -1,7 +1,24 @@
|
||||
TESTS = api-test compat-test loopaes-test align-test mode-test password-hash-test
|
||||
TESTS = api-test compat-test loopaes-test align-test discards-test mode-test password-hash-test
|
||||
|
||||
EXTRA_DIST = compatimage.img.bz2 \
|
||||
compat-test loopaes-test align-test mode-test password-hash-test
|
||||
if VERITYSETUP
|
||||
TESTS += verity-compat-test
|
||||
endif
|
||||
|
||||
if REENCRYPT
|
||||
TESTS += reencryption-compat-test
|
||||
endif
|
||||
|
||||
EXTRA_DIST = compatimage.img.bz2 valid_header_file.bz2 \
|
||||
evil_hdr-payload_overwrite.bz2 \
|
||||
evil_hdr-stripes_payload_dmg.bz2 \
|
||||
evil_hdr-luks_hdr_damage.bz2 \
|
||||
evil_hdr-small_luks_device.bz2 \
|
||||
compat-test loopaes-test align-test discards-test mode-test password-hash-test \
|
||||
verity-compat-test \
|
||||
reencryption-compat-test \
|
||||
cryptsetup-valg-supps valg.sh valg-api.sh
|
||||
|
||||
CLEANFILES = cryptsetup-tst* valglog*
|
||||
|
||||
differ_SOURCES = differ.c
|
||||
differ_CFLAGS = -Wall -O2
|
||||
@@ -9,9 +26,15 @@ differ_CFLAGS = -Wall -O2
|
||||
api_test_SOURCES = api-test.c $(top_srcdir)/lib/utils_loop.c
|
||||
api_test_LDADD = ../lib/libcryptsetup.la
|
||||
api_test_LDFLAGS = -static
|
||||
api_test_CFLAGS = -g -Wall -O0 -I$(top_srcdir)/lib/
|
||||
api_test_CFLAGS = -g -Wall -O0 -I$(top_srcdir)/lib/ -I$(top_srcdir)/lib/luks1
|
||||
|
||||
check_PROGRAMS = api-test differ
|
||||
|
||||
compatimage.img:
|
||||
@bzip2 -k -d compatimage.img.bz2
|
||||
|
||||
valgrind-check: api-test differ
|
||||
@VALG=1 ./compat-test
|
||||
@INFOSTRING="api-test-000" ./valg-api.sh ./api-test
|
||||
|
||||
.PHONY: valgrind-check
|
||||
|
||||
@@ -58,6 +58,19 @@ format() # key_bits expected [forced]
|
||||
echo "FAIL"
|
||||
fail "Expected alignment differs: expected $2 != detected $ALIGN"
|
||||
fi
|
||||
|
||||
# test some operation, just in case
|
||||
echo -e "xxx\naaa" | $CRYPTSETUP luksAddKey $DEV -i1 --key-slot 1
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "FAIL"
|
||||
fail "Keyslot add failed."
|
||||
fi
|
||||
$CRYPTSETUP -q luksKillSlot $DEV 1
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "FAIL"
|
||||
fail "Keyslot removal failed."
|
||||
fi
|
||||
|
||||
echo "PASSED"
|
||||
}
|
||||
|
||||
|
||||
1351
tests/api-test.c
1351
tests/api-test.c
File diff suppressed because it is too large
Load Diff
@@ -2,12 +2,19 @@
|
||||
|
||||
CRYPTSETUP=../src/cryptsetup
|
||||
|
||||
CRYPTSETUP_VALGRIND=../src/.libs/cryptsetup
|
||||
CRYPTSETUP_LIB_VALGRIND=../lib/.libs
|
||||
|
||||
DEV_NAME=dummy
|
||||
DEV_NAME2=dummy2
|
||||
DEV_NAME3=dummy3
|
||||
ORIG_IMG=luks-test-orig
|
||||
IMG=luks-test
|
||||
HEADER_IMG=luks-header
|
||||
KEY1=key1
|
||||
KEY2=key2
|
||||
KEY5=key5
|
||||
KEYE=keye
|
||||
|
||||
LUKS_HEADER="S0-5 S6-7 S8-39 S40-71 S72-103 S104-107 S108-111 R112-131 R132-163 S164-167 S168-207 A0-591"
|
||||
KEY_SLOT0="S208-211 S212-215 R216-247 A248-251 A251-255"
|
||||
@@ -18,20 +25,32 @@ KEY_SLOT1="S256-259 S260-263 R264-295 A296-299 A300-303"
|
||||
KEY_MATERIAL1="R69632-133632"
|
||||
KEY_MATERIAL1_EXT="S69632-133632"
|
||||
|
||||
KEY_SLOT5="S448-451 S452-455 R456-487 A488-491 A492-495"
|
||||
KEY_MATERIAL5="R331776-395264"
|
||||
KEY_MATERIAL5_EXT="S331776-395264"
|
||||
|
||||
TEST_UUID="12345678-1234-1234-1234-123456789abc"
|
||||
|
||||
LOOPDEV=$(losetup -f 2>/dev/null)
|
||||
|
||||
function remove_mapping()
|
||||
{
|
||||
[ -b /dev/mapper/$DEV_NAME3 ] && dmsetup remove $DEV_NAME3
|
||||
[ -b /dev/mapper/$DEV_NAME2 ] && dmsetup remove $DEV_NAME2
|
||||
[ -b /dev/mapper/$DEV_NAME ] && dmsetup remove $DEV_NAME
|
||||
losetup -d $LOOPDEV >/dev/null 2>&1
|
||||
rm -f $ORIG_IMG $IMG $KEY1 $KEY2 >/dev/null 2>&1
|
||||
rm -f $ORIG_IMG $IMG $KEY1 $KEY2 $KEY5 $KEYE $HEADER_IMG >/dev/null 2>&1
|
||||
}
|
||||
|
||||
function force_uevent()
|
||||
{
|
||||
DNAME=$(echo $LOOPDEV | cut -f3 -d /)
|
||||
echo "change" >/sys/block/$DNAME/uevent
|
||||
}
|
||||
|
||||
function fail()
|
||||
{
|
||||
[ -n "$1" ] && echo "$1"
|
||||
remove_mapping
|
||||
echo "FAILED"
|
||||
exit 2
|
||||
@@ -75,6 +94,14 @@ function prepare()
|
||||
dd if=/dev/urandom of=$KEY2 count=1 bs=16 >/dev/null 2>&1
|
||||
fi
|
||||
|
||||
if [ ! -e $KEY5 ]; then
|
||||
dd if=/dev/urandom of=$KEY5 count=1 bs=16 >/dev/null 2>&1
|
||||
fi
|
||||
|
||||
if [ ! -e $KEYE ]; then
|
||||
touch $KEYE
|
||||
fi
|
||||
|
||||
cp $IMG $ORIG_IMG
|
||||
[ -n "$1" ] && echo "CASE: $1"
|
||||
}
|
||||
@@ -92,14 +119,30 @@ function check_exists()
|
||||
check $1
|
||||
}
|
||||
|
||||
function valgrind_setup()
|
||||
{
|
||||
which valgrind >/dev/null 2>&1 || fail "Cannot find valgrind."
|
||||
[ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable."
|
||||
export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH"
|
||||
}
|
||||
|
||||
function valgrind_run()
|
||||
{
|
||||
INFOSTRING="$(basename ${BASH_SOURCE[1]})-line-${BASH_LINENO[0]}" ./valg.sh ${CRYPTSETUP_VALGRIND} "$@"
|
||||
}
|
||||
|
||||
[ $(id -u) != 0 ] && skip "WARNING: You must be root to run this test, test skipped."
|
||||
[ -z "$LOOPDEV" ] && skip "Cannot find free loop device, test skipped."
|
||||
|
||||
[ -n "$VALG" ] && valgrind_setup && CRYPTSETUP=valgrind_run
|
||||
|
||||
# LUKS tests
|
||||
|
||||
prepare "[1] open - compat image - acceptance check" new
|
||||
echo "compatkey" | $CRYPTSETUP luksOpen $LOOPDEV $DEV_NAME || fail
|
||||
check_exists
|
||||
ORG_SHA1=$(sha1sum -b /dev/mapper/$DEV_NAME | cut -f 1 -d' ')
|
||||
[ "$ORG_SHA1" = 676062b66ebf36669dab705442ea0762dfc091b0 ] || fail
|
||||
|
||||
prepare "[2] open - compat image - denial check" new
|
||||
echo "wrongkey" | $CRYPTSETUP luksOpen $LOOPDEV $DEV_NAME 2>/dev/null && fail
|
||||
@@ -115,6 +158,8 @@ echo "key0" | $CRYPTSETUP -i 1000 -h sha512 -c aes-cbc-essiv:sha256 -s 128 luksF
|
||||
check "$LUKS_HEADER $KEY_SLOT0 $KEY_MATERIAL0"
|
||||
|
||||
prepare "[5] open"
|
||||
echo "key0" | $CRYPTSETUP luksOpen $LOOPDEV $DEV_NAME --test-passphrase || fail
|
||||
echo "blah" | $CRYPTSETUP luksOpen $LOOPDEV $DEV_NAME --test-passphrase 2>/dev/null && fail
|
||||
echo "key0" | $CRYPTSETUP luksOpen $LOOPDEV $DEV_NAME || fail
|
||||
check_exists
|
||||
|
||||
@@ -127,6 +172,8 @@ echo "key1" | $CRYPTSETUP luksOpen $LOOPDEV $DEV_NAME || fail
|
||||
# Unsuccessful Key Delete - nothing may change
|
||||
prepare "[7] unsuccessful delete"
|
||||
echo "invalid" | $CRYPTSETUP luksKillSlot $LOOPDEV 1 2>/dev/null && fail
|
||||
$CRYPTSETUP -q luksKillSlot $LOOPDEV 8 2>/dev/null && fail
|
||||
$CRYPTSETUP -q luksKillSlot $LOOPDEV 7 2>/dev/null && fail
|
||||
check
|
||||
|
||||
# Delete Key Test
|
||||
@@ -202,6 +249,20 @@ echo "key0" | $CRYPTSETUP -q luksFormat --master-key-file /dev/urandom $LOOPDEV
|
||||
$CRYPTSETUP -q luksFormat --master-key-file /dev/urandom -s 256 --uuid $TEST_UUID $LOOPDEV $KEY1 || fail
|
||||
$CRYPTSETUP luksOpen -d $KEY1 $LOOPDEV $DEV_NAME || fail
|
||||
$CRYPTSETUP -q luksClose $DEV_NAME || fail
|
||||
# open by UUID
|
||||
force_uevent # some systems do not update loop by-uuid
|
||||
$CRYPTSETUP luksOpen -d $KEY1 UUID=X$TEST_UUID $DEV_NAME 2>/dev/null && fail
|
||||
$CRYPTSETUP luksOpen -d $KEY1 UUID=$TEST_UUID $DEV_NAME || fail
|
||||
$CRYPTSETUP -q luksClose $DEV_NAME || fail
|
||||
# empty keyfile
|
||||
$CRYPTSETUP -q luksFormat $LOOPDEV $KEYE || fail
|
||||
$CRYPTSETUP luksOpen -d $KEYE $LOOPDEV $DEV_NAME || fail
|
||||
$CRYPTSETUP -q luksClose $DEV_NAME || fail
|
||||
# open by volume key
|
||||
echo "key0" | $CRYPTSETUP -q luksFormat -s 256 --master-key-file $KEY1 $LOOPDEV || fail
|
||||
$CRYPTSETUP luksOpen --master-key-file /dev/urandom $LOOPDEV $DEV_NAME 2>/dev/null && fail
|
||||
$CRYPTSETUP luksOpen --master-key-file $KEY1 $LOOPDEV $DEV_NAME || fail
|
||||
$CRYPTSETUP -q luksClose $DEV_NAME || fail
|
||||
|
||||
prepare "[17] AddKey volume key, passphrase and keyfile" wipe
|
||||
# masterkey
|
||||
@@ -255,6 +316,7 @@ $CRYPTSETUP -q status $DEV_NAME | grep "size:" | grep -q "100 sectors" || fail
|
||||
$CRYPTSETUP -q resize $DEV_NAME || fail
|
||||
$CRYPTSETUP -q status $DEV_NAME | grep "size:" | grep -q "19997 sectors" || fail
|
||||
$CRYPTSETUP -q remove $DEV_NAME || fail
|
||||
$CRYPTSETUP -q status $DEV_NAME >/dev/null && fail
|
||||
echo "key0" | $CRYPTSETUP create $DEV_NAME --hash sha1 $LOOPDEV || fail
|
||||
$CRYPTSETUP -q remove $DEV_NAME || fail
|
||||
echo "key0" | $CRYPTSETUP -q create $DEV_NAME --hash sha1 $LOOPDEV || fail
|
||||
@@ -263,7 +325,7 @@ echo "key0" | $CRYPTSETUP -q create $DEV_NAME --hash sha1 --size 100 $LOOPDEV ||
|
||||
$CRYPTSETUP -q status $DEV_NAME | grep "size:" | grep -q "100 sectors" || fail
|
||||
$CRYPTSETUP -q remove $DEV_NAME || fail
|
||||
# verify is ignored on non-tty input
|
||||
echo "key0" | $CRYPTSETUP create $DEV_NAME $LOOPDEV --hash sha1 --verify-passphrase || fail
|
||||
echo "key0" | $CRYPTSETUP create $DEV_NAME $LOOPDEV --hash sha1 --verify-passphrase 2>/dev/null || fail
|
||||
$CRYPTSETUP -q remove $DEV_NAME || fail
|
||||
$CRYPTSETUP create $DEV_NAME $LOOPDEV -d $KEY1 --key-size 255 2>/dev/null && fail
|
||||
$CRYPTSETUP create $DEV_NAME $LOOPDEV -d $KEY1 --key-size -1 2>/dev/null && fail
|
||||
@@ -336,6 +398,8 @@ $CRYPTSETUP --key-file=$KEY1 luksOpen $LOOPDEV $DEV_NAME 2>/dev/null && fail
|
||||
$CRYPTSETUP --key-file=$KEY1 -l 0 luksOpen $LOOPDEV $DEV_NAME 2>/dev/null && fail
|
||||
$CRYPTSETUP --key-file=$KEY1 -l -1 luksOpen $LOOPDEV $DEV_NAME 2>/dev/null && fail
|
||||
$CRYPTSETUP --key-file=$KEY1 -l 14 luksOpen $LOOPDEV $DEV_NAME 2>/dev/null && fail
|
||||
$CRYPTSETUP --key-file=$KEY1 -l 13 --keyfile-offset 1 luksOpen $LOOPDEV $DEV_NAME 2>/dev/null && fail
|
||||
$CRYPTSETUP --key-file=$KEY1 -l 13 --keyfile-offset -1 luksOpen $LOOPDEV $DEV_NAME 2>/dev/null && fail
|
||||
$CRYPTSETUP --key-file=$KEY1 -l 13 luksOpen $LOOPDEV $DEV_NAME || fail
|
||||
$CRYPTSETUP luksClose $DEV_NAME || fail
|
||||
$CRYPTSETUP luksAddKey $LOOPDEV -d $KEY1 $KEY2 2>/dev/null && fail
|
||||
@@ -353,6 +417,89 @@ echo "key0" | $CRYPTSETUP luksAddKey $LOOPDEV -d $KEY2 -i1 || fail
|
||||
echo "key0" | $CRYPTSETUP luksRemoveKey $LOOPDEV -l 2 2>/dev/null && fail
|
||||
echo "key01" | $CRYPTSETUP luksRemoveKey $LOOPDEV -d 4 2>/dev/null && fail
|
||||
echo -e "key0\n" | $CRYPTSETUP luksRemoveKey $LOOPDEV -d- -l 4 || fail
|
||||
# offset
|
||||
$CRYPTSETUP -q luksFormat -i1 $LOOPDEV $KEY1 --key-slot 0 -l 13 --keyfile-offset 16 || fail
|
||||
$CRYPTSETUP --key-file=$KEY1 -l 13 --keyfile-offset 15 luksOpen $LOOPDEV $DEV_NAME 2>/dev/null && fail
|
||||
$CRYPTSETUP --key-file=$KEY1 -l 13 --keyfile-offset 16 luksOpen $LOOPDEV $DEV_NAME || fail
|
||||
$CRYPTSETUP luksClose $DEV_NAME || fail
|
||||
$CRYPTSETUP luksAddKey $LOOPDEV -i1 -d $KEY1 -l 13 --keyfile-offset 16 $KEY2 --new-keyfile-offset 1 || fail
|
||||
$CRYPTSETUP --key-file=$KEY2 --keyfile-offset 11 luksOpen $LOOPDEV $DEV_NAME 2>/dev/null && fail
|
||||
$CRYPTSETUP --key-file=$KEY2 --keyfile-offset 1 luksOpen $LOOPDEV $DEV_NAME || fail
|
||||
$CRYPTSETUP luksClose $DEV_NAME || fail
|
||||
$CRYPTSETUP luksChangeKey $LOOPDEV -i1 -d $KEY2 --keyfile-offset 1 $KEY2 --new-keyfile-offset 0 || fail
|
||||
$CRYPTSETUP luksOpen -d $KEY2 $LOOPDEV $DEV_NAME || fail
|
||||
$CRYPTSETUP luksClose $DEV_NAME || fail
|
||||
|
||||
prepare "[25] Create shared segments" wipe
|
||||
echo "key0" | $CRYPTSETUP create $DEV_NAME $LOOPDEV --hash sha1 --offset 0 --size 256 || fail
|
||||
echo "key0" | $CRYPTSETUP create $DEV_NAME2 $LOOPDEV --hash sha1 --offset 512 --size 256 2>/dev/null && fail
|
||||
echo "key0" | $CRYPTSETUP create $DEV_NAME2 $LOOPDEV --hash sha1 --offset 512 --size 256 --shared || fail
|
||||
$CRYPTSETUP -q remove $DEV_NAME2 || fail
|
||||
$CRYPTSETUP -q remove $DEV_NAME || fail
|
||||
|
||||
prepare "[26] Suspend/Resume" wipe
|
||||
# only LUKS is supported
|
||||
echo "key0" | $CRYPTSETUP create $DEV_NAME --hash sha1 $LOOPDEV || fail
|
||||
$CRYPTSETUP luksSuspend $DEV_NAME 2>/dev/null && fail
|
||||
$CRYPTSETUP luksResume $DEV_NAME 2>/dev/null && fail
|
||||
$CRYPTSETUP -q remove $DEV_NAME || fail
|
||||
$CRYPTSETUP luksSuspend $DEV_NAME 2>/dev/null && fail
|
||||
# LUKS
|
||||
echo "key0" | $CRYPTSETUP -q luksFormat $LOOPDEV || fail
|
||||
echo "key0" | $CRYPTSETUP -q luksOpen $LOOPDEV $DEV_NAME || fail
|
||||
$CRYPTSETUP luksSuspend $DEV_NAME || fail
|
||||
$CRYPTSETUP -q resize $DEV_NAME 2>/dev/null && fail
|
||||
echo "xxx" | $CRYPTSETUP luksResume $DEV_NAME -T 1 2>/dev/null && fail
|
||||
echo "key0" | $CRYPTSETUP luksResume $DEV_NAME || fail
|
||||
$CRYPTSETUP -q luksClose $DEV_NAME || fail
|
||||
|
||||
prepare "[27] luksOpen with specified key slot number" wipe
|
||||
# first, let's try passphrase option
|
||||
echo "key5" | $CRYPTSETUP luksFormat -S 5 $LOOPDEV || fail
|
||||
check $LUKS_HEADER $KEY_SLOT5 $KEY_MATERIAL5
|
||||
echo "key5" | $CRYPTSETUP luksOpen -S 4 $LOOPDEV $DEV_NAME && fail
|
||||
[ -b /dev/mapper/$DEV_NAME ] && fail
|
||||
echo "key5" | $CRYPTSETUP luksOpen -S 5 $LOOPDEV $DEV_NAME || fail
|
||||
check_exists
|
||||
$CRYPTSETUP luksClose $DEV_NAME || fail
|
||||
echo -e "key5\nkey0" | $CRYPTSETUP luksAddKey -S 0 $LOOPDEV || fail
|
||||
check $LUKS_HEADER $KEY_SLOT0 $KEY_MATERIAL0
|
||||
echo "key5" | $CRYPTSETUP luksOpen -S 0 $LOOPDEV $DEV_NAME && fail
|
||||
[ -b /dev/mapper/$DEV_NAME ] && fail
|
||||
echo "key0" | $CRYPTSETUP luksOpen -S 5 $LOOPDEV $DEV_NAME && fail
|
||||
[ -b /dev/mapper/$DEV_NAME ] && fail
|
||||
# second, try it with keyfiles
|
||||
$CRYPTSETUP luksFormat -q -S 5 -d $KEY5 $LOOPDEV || fail
|
||||
check $LUKS_HEADER $KEY_SLOT5 $KEY_MATERIAL5
|
||||
$CRYPTSETUP luksAddKey -S 1 -d $KEY5 $LOOPDEV $KEY1 || fail
|
||||
check $LUKS_HEADER $KEY_SLOT1 $KEY_MATERIAL1
|
||||
$CRYPTSETUP luksOpen -S 5 -d $KEY5 $LOOPDEV $DEV_NAME || fail
|
||||
check_exists
|
||||
$CRYPTSETUP luksClose $DEV_NAME || fail
|
||||
$CRYPTSETUP luksOpen -S 1 -d $KEY5 $LOOPDEV $DEV_NAME && fail
|
||||
[ -b /dev/mapper/$DEV_NAME ] && fail
|
||||
$CRYPTSETUP luksOpen -S 5 -d $KEY1 $LOOPDEV $DEV_NAME && fail
|
||||
[ -b /dev/mapper/$DEV_NAME ] && fail
|
||||
|
||||
prepare "[28] Detached LUKS header" wipe
|
||||
dd if=/dev/zero of=$HEADER_IMG bs=1M count=4 >/dev/null 2>&1
|
||||
echo "key0" | $CRYPTSETUP luksFormat -i1 $LOOPDEV --header $HEADER_IMG || fail
|
||||
echo "key0" | $CRYPTSETUP luksFormat -i1 $LOOPDEV --header $HEADER_IMG --align-payload 0 || fail
|
||||
echo "key0" | $CRYPTSETUP luksOpen $LOOPDEV --header $HEADER_IMG $DEV_NAME || fail
|
||||
$CRYPTSETUP -q resize $DEV_NAME --size 100 --header $HEADER_IMG || fail
|
||||
$CRYPTSETUP -q status $DEV_NAME --header $HEADER_IMG | grep "size:" | grep -q "100 sectors" || fail
|
||||
$CRYPTSETUP luksSuspend $DEV_NAME --header $HEADER_IMG || fail
|
||||
echo "key0" | $CRYPTSETUP luksResume $DEV_NAME --header $HEADER_IMG || fail
|
||||
$CRYPTSETUP luksClose $DEV_NAME || fail
|
||||
|
||||
prepare "[29] Repair metadata" wipe
|
||||
$CRYPTSETUP -q luksFormat -i1 $LOOPDEV $KEY1 --key-slot 0 || fail
|
||||
# second sector overwrite should corrupt keyslot 6+7
|
||||
dd if=/dev/urandom of=$LOOPDEV bs=512 seek=1 count=1 >/dev/null 2>&1
|
||||
$CRYPTSETUP luksOpen -d $KEY1 $LOOPDEV $DEV_NAME >/dev/null 2>&1 && fail
|
||||
$CRYPTSETUP -q repair $LOOPDEV >/dev/null 2>&1 || fail
|
||||
$CRYPTSETUP luksOpen -d $KEY1 $LOOPDEV $DEV_NAME || fail
|
||||
$CRYPTSETUP luksClose $DEV_NAME || fail
|
||||
|
||||
remove_mapping
|
||||
exit 0
|
||||
|
||||
36
tests/cryptsetup-valg-supps
Normal file
36
tests/cryptsetup-valg-supps
Normal file
@@ -0,0 +1,36 @@
|
||||
# Supresion file for valgrind
|
||||
|
||||
# known problem in libgcrypt
|
||||
{
|
||||
leak_in_libgcrypt_00
|
||||
Memcheck:Leak
|
||||
fun:malloc
|
||||
obj:/lib64/libgcrypt.so*
|
||||
...
|
||||
obj:/lib64/libgcrypt.so*
|
||||
fun:crypt_backend_init
|
||||
fun:init_crypto
|
||||
...
|
||||
}
|
||||
# following leaks/errors are addressed to libpopt...
|
||||
{
|
||||
popt_read_error
|
||||
Memcheck:Addr4
|
||||
obj:/lib*/libpopt.so*
|
||||
fun:poptGetNextOpt
|
||||
fun:main
|
||||
}
|
||||
{
|
||||
popt_leak_poptGetNextOpt_00
|
||||
Memcheck:Leak
|
||||
fun:realloc
|
||||
fun:poptGetNextOpt
|
||||
fun:main
|
||||
}
|
||||
{
|
||||
popt_leak_poptGetNextOpt_01
|
||||
Memcheck:Leak
|
||||
fun:malloc
|
||||
fun:poptGetNextOpt
|
||||
fun:main
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* cryptsetup file differ check (rewritten Clemens' fileDiffer in Python)
|
||||
*
|
||||
* Copyright (C) 2010 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2010-2012 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
81
tests/discards-test
Executable file
81
tests/discards-test
Executable file
@@ -0,0 +1,81 @@
|
||||
#!/bin/bash
|
||||
|
||||
CRYPTSETUP="../src/cryptsetup"
|
||||
DEV_NAME="discard-t3st"
|
||||
DEV=""
|
||||
|
||||
cleanup() {
|
||||
[ -b /dev/mapper/$DEV_NAME ] && dmsetup remove $DEV_NAME
|
||||
udevadm settle >/dev/null 2>&1
|
||||
rmmod scsi_debug 2>/dev/null
|
||||
sleep 2
|
||||
}
|
||||
|
||||
fail()
|
||||
{
|
||||
echo "FAILED"
|
||||
cleanup
|
||||
exit 100
|
||||
}
|
||||
|
||||
add_device() {
|
||||
modprobe scsi_debug $@
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "This kernel seems to not support proper scsi_debug module, test skipped."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
sleep 2
|
||||
DEV=$(grep scsi_debug /sys/block/*/device/model | cut -f4 -d /)
|
||||
|
||||
DEV="/dev/$DEV"
|
||||
[ -b $DEV ] || fail "Cannot find $DEV."
|
||||
}
|
||||
|
||||
function check_version()
|
||||
{
|
||||
VER_STR=$(dmsetup targets | grep crypt | cut -f 2 -dv)
|
||||
VER_MAJ=$(echo $VER_STR | cut -f 1 -d.)
|
||||
VER_MIN=$(echo $VER_STR | cut -f 2 -d.)
|
||||
|
||||
# option supported in 1.11
|
||||
test $VER_MAJ -gt 1 && return 0
|
||||
test $VER_MIN -ge 11 && return 0
|
||||
return 1
|
||||
}
|
||||
|
||||
if [ $(id -u) != 0 ]; then
|
||||
echo "WARNING: You must be root to run this test, test skipped."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
modprobe --dry-run scsi_debug || exit 0
|
||||
modprobe dm-crypt >/dev/null 2>&1
|
||||
if ! check_version ; then
|
||||
echo "Probably old kernel, test skipped."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
add_device dev_size_mb=16 sector_size=512 num_tgts=1 lbpu=1
|
||||
|
||||
# FIXME test hash of device (unmap -> zero)
|
||||
# for now just check that flag is enabled
|
||||
|
||||
echo "[1] Allowing discards for LUKS device"
|
||||
echo xxx | $CRYPTSETUP luksFormat $DEV -q -i1 || fail
|
||||
echo xxx | $CRYPTSETUP luksOpen $DEV $DEV_NAME --allow-discards || fail
|
||||
$CRYPTSETUP status $DEV_NAME | grep flags | grep discards >/dev/null || fail
|
||||
$CRYPTSETUP resize $DEV_NAME --size 100 || fail
|
||||
$CRYPTSETUP status $DEV_NAME | grep flags | grep discards >/dev/null || fail
|
||||
dmsetup table $DEV_NAME | grep allow_discards >/dev/null || fail
|
||||
$CRYPTSETUP luksClose $DEV_NAME || fail
|
||||
|
||||
echo "[2] Allowing discards for plain device"
|
||||
echo xxx | $CRYPTSETUP create $DEV_NAME $DEV --hash sha1 --allow-discards || fail
|
||||
$CRYPTSETUP status $DEV_NAME | grep flags | grep discards >/dev/null || fail
|
||||
$CRYPTSETUP resize $DEV_NAME --size 100 || fail
|
||||
$CRYPTSETUP status $DEV_NAME | grep flags | grep discards >/dev/null || fail
|
||||
dmsetup table $DEV_NAME | grep allow_discards >/dev/null || fail
|
||||
$CRYPTSETUP remove $DEV_NAME || fail
|
||||
|
||||
cleanup
|
||||
BIN
tests/evil_hdr-luks_hdr_damage.bz2
Normal file
BIN
tests/evil_hdr-luks_hdr_damage.bz2
Normal file
Binary file not shown.
BIN
tests/evil_hdr-payload_overwrite.bz2
Normal file
BIN
tests/evil_hdr-payload_overwrite.bz2
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user