Compare commits

..

1 Commits

Author SHA1 Message Date
Milan Broz
e4410550dc Release 1.3.0
git-svn-id: https://cryptsetup.googlecode.com/svn/tags/v1_3_0@493 36d66b0a-2a48-0410-832c-cd162a569da5
2011-04-05 19:23:16 +00:00
123 changed files with 7020 additions and 25810 deletions

41
COPYING
View File

@@ -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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 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 Lesser General Public License instead.) You can apply it to
the GNU Library 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,16 +303,17 @@ 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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
@@ -335,7 +336,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 Lesser General
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.
-----

View File

@@ -1,502 +0,0 @@
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!

175
ChangeLog
View File

@@ -1,170 +1,3 @@
2012-10-11 Milan Broz <gmazyland@gmail.com>
* Added keyslot checker (by Arno Wagner).
* Version 1.5.1.
2012-09-11 Milan Broz <gmazyland@gmail.com>
* Add crypt_keyslot_area() API call.
2012-08-27 Milan Broz <gmazyland@gmail.com>
* Optimize seek to keyfile-offset (Issue #135, thx to dreisner).
* Fix luksHeaderBackup for very old v1.0 unaligned LUKS headers.
2012-08-12 Milan Broz <gmazyland@gmail.com>
* Allocate loop device late (only when real block device needed).
* Rework underlying device/file access functions.
* Create hash image if doesn't exist in veritysetup format.
* Provide better error message if running as non-root user (device-mapper, loop).
2012-07-10 Milan Broz <gmazyland@gmail.com>
* Version 1.5.0.
2012-06-25 Milan Broz <gmazyland@gmail.com>
* Add --device-size option for reencryption tool.
* Switch to use unit suffix for --reduce-device-size option.
* Remove open device debugging feature (no longer needed).
* Fix library name for FIPS check.
2012-06-20 Milan Broz <gmazyland@gmail.com>
* Version 1.5.0-rc2.
2012-06-18 Milan Broz <gmazyland@gmail.com>
* Introduce cryptsetup-reencrypt - experimental offline LUKS reencryption tool.
* Fix luks-header-from-active script (do not use LUKS header on-disk, add UUID).
* Add --test-passphrase option for luksOpen (check passphrase only).
2012-06-11 Milan Broz <gmazyland@gmail.com>
* Introduce veritysetup for dm-verity target management.
* Version 1.5.0-rc1.
2012-06-10 Milan Broz <gmazyland@gmail.com>
* Both data and header device can now be a file.
* Loop is automatically allocated in crypt_set_data_device().
* Require only up to last keyslot area for header device (ignore data offset).
* Fix header backup and restore to work on files with large data offset.
2012-05-27 Milan Broz <gmazyland@gmail.com>
* Fix readonly activation if underlying device is readonly (1.4.0).
* Include stddef.h in libdevmapper.h (size_t definition).
* Version 1.4.3.
2012-05-21 Milan Broz <gmazyland@gmail.com>
* Add --enable-fips for linking with fipscheck library.
* Initialize binary and library selfcheck if running in FIPS mode.
* Use FIPS RNG in FIPS mode for KEY and SALT (only gcrypt backend supported).
2012-05-09 Milan Broz <gmazyland@gmail.com>
* Fix keyslot removal (wipe keyslot) for device with 4k hw block (1.4.0).
* Allow empty cipher (cipher_null) for testing.
2012-05-02 Milan Broz <gmazyland@gmail.com>
* Fix loop mapping on readonly file.
* Relax --shared test, allow mapping even for overlapping segments.
* Support shared flag for LUKS devices (dangerous).
* Switch on retry on device remove for libdevmapper.
* Allow "private" activation (skip some udev global rules) flag.
2012-04-09 Milan Broz <gmazyland@gmail.com>
* Fix header check to support old (cryptsetup 1.0.0) header alignment. (1.4.0)
* Version 1.4.2.
2012-03-16 Milan Broz <gmazyland@gmail.com>
* Add --keyfile-offset and --new-keyfile-offset parameters to API and CLI.
* Add repair command and crypt_repair() for known LUKS metadata problems repair.
* Allow to specify --align-payload only for luksFormat.
2012-03-16 Milan Broz <mbroz@redhat.com>
* Unify password verification option.
* Support password verification with quiet flag if possible. (1.2.0)
* Fix retry if entered passphrases (with verify option) do not match.
* Support UUID=<LUKS_UUID> format for device specification.
2012-02-11 Milan Broz <mbroz@redhat.com>
* Add --master-key-file option to luksOpen (open using volume key).
2012-01-12 Milan Broz <mbroz@redhat.com>
* Fix use of empty keyfile.
2011-11-13 Milan Broz <mbroz@redhat.com>
* Fix error message for luksClose and detached LUKS header.
* Allow --header for status command to get full info with detached header.
2011-11-09 Milan Broz <mbroz@redhat.com>
* Version 1.4.1.
2011-11-05 Milan Broz <mbroz@redhat.com>
* Merge pycryptsetup (Python libcryptsetup bindings).
* Fix stupid typo in set_iteration_time API call.
* Fix cryptsetup status output if parameter is device path.
2011-10-27 Milan Broz <mbroz@redhat.com>
* Fix crypt_get_volume_key_size() for plain device.
* Fix FSF address in license text.
2011-10-25 Milan Broz <mbroz@redhat.com>
* Print informative message in isLuks only in verbose mode.
* Version 1.4.0.
2011-10-10 Milan Broz <mbroz@redhat.com>
* Version 1.4.0-rc1.
2011-10-05 Milan Broz <mbroz@redhat.com>
* Support Nettle 2.4 crypto backend (for ripemd160).
* If device is not rotational, do not use Gutmann wipe method.
* Add crypt_last_error() API call.
* Fix luksKillSLot exit code if slot is inactive or invalid.
* Fix exit code if passphrases do not match in luksAddKey.
* Add LUKS on-disk format description into package.
2011-09-22 Milan Broz <mbroz@redhat.com>
* Support key-slot option for luksOpen (use only explicit keyslot).
2011-08-22 Milan Broz <mbroz@redhat.com>
* Add more paranoid checks for LUKS header and keyslot attributes.
* Fix crypt_load to properly check device size.
* Use new /dev/loop-control (kernel 3.1) if possible.
* Enhance check of device size before writing LUKS header.
* Do not allow context format of already formatted device.
2011-07-25 Milan Broz <mbroz@redhat.com>
* Remove hash/hmac restart from crypto backend and make it part of hash/hmac final.
* Improve check for invalid offset and size values.
2011-07-19 Milan Broz <mbroz@redhat.com>
* Revert default initialisation of volume key in crypt_init_by_name().
* Do not allow key retrieval while suspended (key could be wiped).
* Do not allow suspend for non-LUKS devices.
* Support retries and timeout parameters for luksSuspend.
* Add --header option for detached metadata (on-disk LUKS header) device.
* Add crypt_init_by_name_and_header() and crypt_set_data_device() to API.
* Allow different data offset setting for detached header.
2011-07-07 Milan Broz <mbroz@redhat.com>
* Remove old API functions (all functions using crypt_options).
* Add --enable-discards option to allow discards/TRIM requests.
* Add crypt_get_iv_offset() function to API.
2011-07-01 Milan Broz <mbroz@redhat.com>
* Add --shared option for creating non-overlapping crypt segments.
* Add shared flag to libcryptsetup api.
* Fix plain crypt format parameters to include size option (API change).
2011-06-08 Milan Broz <mbroz@redhat.com>
* Fix return code for status command when device doesn't exists.
2011-05-24 Milan Broz <mbroz@redhat.com>
* Version 1.3.1.
2011-05-17 Milan Broz <mbroz@redhat.com>
* Fix keyfile=- processing in create command (1.3.0).
* Simplify device path status check.
2011-05-03 Milan Broz <mbroz@redhat.com>
* Do not ignore size argument for create command (1.2.0).
2011-04-18 Milan Broz <mbroz@redhat.com>
* Fix error paths in blockwise code and lseek_write call.
* Add Nettle crypto backend support.
2011-04-05 Milan Broz <mbroz@redhat.com>
* Version 1.3.0.
@@ -516,7 +349,7 @@
* configure.in (AC_OUTPUT): Add m4/Makefile.
(AM_GNU_GETTEXT_VERSION): Bump to 0.15.
2006-10-22 David Härdeman <david@hardeman.nu>
2006-10-22 David H<EFBFBD>rdeman <david@hardeman.nu>
* Allow hashing of keys passed through stdin.
@@ -583,7 +416,7 @@
2006-08-04 Clemens Fruhwirth <clemens@endorphin.org>
* lib/setup.c (get_key): Applied patch from David Härdeman
* lib/setup.c (get_key): Applied patch from David H<EFBFBD>rdeman
<david@2gen.com> for reading binary keys from stdin using
the "-" as key file.
@@ -600,7 +433,7 @@
2006-07-23 Clemens Fruhwirth <clemens@endorphin.org>
* Applied patches from David Härdeman <david@2gen.com> to fix 64
* Applied patches from David H<EFBFBD>rdeman <david@2gen.com> to fix 64
bit compiler warning issues.
2006-05-19 Clemens Fruhwirth <clemens@endorphin.org>
@@ -619,7 +452,7 @@
* configure.in: Release 1.0.3.
* Applied patch by Johannes Weißl for more meaningful exit codes
* Applied patch by Johannes Wei<EFBFBD>l for more meaningful exit codes
and password retries
2006-03-30 Clemens Fruhwirth <clemens@endorphin.org>

1116
FAQ

File diff suppressed because it is too large Load Diff

View File

@@ -1,13 +1,9 @@
EXTRA_DIST = COPYING.LGPL FAQ docs misc
EXTRA_DIST = FAQ docs
SUBDIRS = \
lib \
src \
man \
python \
tests \
po
ACLOCAL_AMFLAGS = -I m4
clean-local:
-rm -rf docs/doxygen_api_docs

2
README
View File

@@ -23,7 +23,7 @@ DOWNLOAD:
SOURCE CODE:
URL: http://code.google.com/p/cryptsetup/source/browse/
Checkout: git clone https://code.google.com/p/cryptsetup/
Checkout: svn checkout http://cryptsetup.googlecode.com/svn/trunk/ cryptsetup
NLS (PO TRANSLATIONS):

12
TODO
View File

@@ -1,7 +1,5 @@
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
Version 1.4.0:
- Remove old API (all calls using crypt_options)
- Support separation of metadata device
- Wipe device flag
- Add Natty crypto backend

53
acinclude.m4 Normal file
View File

@@ -0,0 +1,53 @@
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
])

View File

@@ -1,11 +1,9 @@
AC_PREREQ([2.67])
AC_INIT([cryptsetup],[1.5.1])
AC_INIT([cryptsetup],[1.3.0])
dnl library version from <major>.<minor>.<release>[-<suffix>]
LIBCRYPTSETUP_VERSION=$(echo $PACKAGE_VERSION | cut -f1 -d-)
LIBCRYPTSETUP_VERSION_INFO=8:0:4
dnl library file name for FIPS selfcheck
LIBCRYPTSETUP_VERSION_FIPS="libcryptsetup.so.4"
LIBCRYPTSETUP_VERSION_INFO=3:0:2
AC_CONFIG_SRCDIR(src/cryptsetup.c)
AC_CONFIG_MACRO_DIR([m4])
@@ -33,11 +31,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
@@ -63,44 +61,11 @@ 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], [
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.])])
AM_PATH_LIBGCRYPT(1.1.42,,[AC_MSG_ERROR('You need the gcrypt library')])
if test x$enable_static_cryptsetup = xyes; then
saved_LIBS=$LIBS
@@ -115,13 +80,11 @@ 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
@@ -132,50 +95,28 @@ 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.]))
saved_CFLAGS=$CFLAGS
CFLAGS="$CFLAGS $NSS_CFLAGS"
AC_CHECK_DECLS([NSS_GetVersion], [], [], [#include <nss.h>])
CFLAGS=$saved_CFLAGS
AC_MSG_ERROR('You need nss library'))
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.])])
saved_LIBS=$LIBS
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
CRYPTO_STATIC_LIBS=$CRYPTO_LIBS
NO_FIPS([])
])
dnl ==========================================================================
@@ -190,17 +131,7 @@ if test x$enable_static_cryptsetup = xyes; then
enable_static=yes
fi
fi
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)
AM_CONDITIONAL(STATIC_CRYPTSETUP, test x$enable_static_cryptsetup = xyes)
AC_ARG_ENABLE(selinux,
AS_HELP_STRING([--disable-selinux],
@@ -222,7 +153,6 @@ 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
@@ -235,7 +165,7 @@ LIBS=$saved_LIBS
dnl Crypto backend configuration.
AC_ARG_WITH([crypto_backend],
AS_HELP_STRING([--with-crypto_backend=BACKEND], [crypto backend (gcrypt/openssl/nss/kernel/nettle) [gcrypt]]),
AS_HELP_STRING([--with-crypto_backend=BACKEND], [crypto backend (gcrypt/openssl/nss/kernel) [gcrypt]]),
[], with_crypto_backend=gcrypt
)
case $with_crypto_backend in
@@ -243,14 +173,12 @@ case $with_crypto_backend in
openssl) CONFIGURE_OPENSSL([]) ;;
nss) CONFIGURE_NSS([]) ;;
kernel) CONFIGURE_KERNEL([]) ;;
nettle) CONFIGURE_NETTLE([]) ;;
*) AC_MSG_ERROR([Unknown crypto backend.]) ;;
esac
AM_CONDITIONAL(CRYPTO_BACKEND_GCRYPT, test $with_crypto_backend = gcrypt)
AM_CONDITIONAL(CRYPTO_BACKEND_OPENSSL, test $with_crypto_backend = openssl)
AM_CONDITIONAL(CRYPTO_BACKEND_NSS, test $with_crypto_backend = nss)
AM_CONDITIONAL(CRYPTO_BACKEND_KERNEL, test $with_crypto_backend = kernel)
AM_CONDITIONAL(CRYPTO_BACKEND_NETTLE, test $with_crypto_backend = nettle)
dnl Magic for cryptsetup.static build.
if test x$enable_static_cryptsetup = xyes; then
@@ -275,11 +203,6 @@ 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
@@ -293,7 +216,6 @@ 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],
@@ -318,25 +240,6 @@ 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])
@@ -350,13 +253,8 @@ 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 KiB)], [8192])
CS_NUM_WITH([passphrase-size-max],[maximum keyfile size (in characters)], [512])
CS_STR_WITH([verity-hash], [hash function for verity mode], [sha256])
CS_NUM_WITH([verity-data-block], [data block size for verity mode], [4096])
CS_NUM_WITH([verity-hash-block], [hash block size for verity mode], [4096])
CS_NUM_WITH([verity-salt-size], [salt size for verity mode], [32])
CS_NUM_WITH([keyfile-size-maxkb],[maximum keyfile size (in kilobytes)], [8192])
CS_NUM_WITH([passphrase-size-max],[maximum keyfile size (in kilobytes)], [512])
dnl ==========================================================================
@@ -366,11 +264,9 @@ 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

View File

@@ -1,280 +0,0 @@
# 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

View File

@@ -1,125 +0,0 @@
/**
* @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
*/

View File

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

View File

@@ -1,96 +0,0 @@
/*
* 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;
}

View File

@@ -1,294 +0,0 @@
/*
* 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 */
&params); /* 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;
}

Binary file not shown.

View File

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

View File

@@ -1,131 +0,0 @@
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).

View File

@@ -1,25 +0,0 @@
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.

View File

@@ -1,44 +0,0 @@
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.

View File

@@ -1,62 +0,0 @@
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.

View File

@@ -1,241 +0,0 @@
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

View File

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

View File

@@ -1,4 +1,4 @@
SUBDIRS = crypto_backend luks1 loopaes verity
SUBDIRS = crypto_backend luks1 loopaes
moduledir = $(libdir)/cryptsetup
@@ -10,7 +10,6 @@ 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)"\" \
@@ -25,8 +24,7 @@ lib_LTLIBRARIES = libcryptsetup.la
common_ldadd = \
crypto_backend/libcrypto_backend.la \
luks1/libluks1.la \
loopaes/libloopaes.la \
verity/libverity.la
loopaes/libloopaes.la
libcryptsetup_la_DEPENDENCIES = $(common_ldadd) libcryptsetup.sym
@@ -40,28 +38,22 @@ libcryptsetup_la_LIBADD = \
@UUID_LIBS@ \
@DEVMAPPER_LIBS@ \
@CRYPTO_LIBS@ \
@FIPSCHECK_LIBS@ \
$(common_ldadd)
libcryptsetup_la_SOURCES = \
setup.c \
internal.h \
bitops.h \
nls.h \
blockdev.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 \
utils_device.c \
libdevmapper.c \
utils_dm.h \
volumekey.c \
random.c \
crypt_plain.c

View File

@@ -1,83 +0,0 @@
#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 */

16
lib/blockdev.h Normal file
View File

@@ -0,0 +1,16 @@
#ifndef BLOCKDEV_H
#define BLOCKDEV_H
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <unistd.h>
#include <asm/types.h>
#include <sys/ioctl.h>
#include <sys/mount.h>
#if defined(__linux__) && defined(_IOR) && !defined(BLKGETSIZE64)
# define BLKGETSIZE64 _IOR(0x12, 114, size_t)
#endif
#endif /* BLOCKDEV_H */

View File

@@ -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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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,6 +54,8 @@ 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);
@@ -62,7 +64,7 @@ static int hash(const char *hash_name, size_t key_size, char *key,
#define PLAIN_HASH_LEN_MAX 256
int crypt_plain_hash(struct crypt_device *ctx __attribute__((unused)),
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)

View File

@@ -18,8 +18,5 @@ endif
if CRYPTO_BACKEND_KERNEL
libcrypto_backend_la_SOURCES += crypto_kernel.c
endif
if CRYPTO_BACKEND_NETTLE
libcrypto_backend_la_SOURCES += crypto_nettle.c
endif
INCLUDES = -D_GNU_SOURCE -I$(top_srcdir)/lib

View File

@@ -1,28 +1,9 @@
/*
* 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 <stdint.h>
#include "config.h"
#include "libcryptsetup.h"
#include "internal.h"
struct crypt_device;
struct crypt_hash;
struct crypt_hmac;
@@ -31,11 +12,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);
@@ -44,12 +25,9 @@ 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 */

View File

@@ -1,7 +1,7 @@
/*
* GCRYPT crypto backend implementation
*
* Copyright (C) 2010-2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-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
@@ -14,19 +14,18 @@
*
* 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.
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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;
@@ -45,6 +44,7 @@ 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)
* 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,18 +68,10 @@ int crypt_backend_init(struct crypt_device *ctx)
gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
}
snprintf(version, 64, "gcrypt %s%s",
gcry_check_version(NULL),
crypto_backend_secmem ? "" : ", secmem disabled");
crypto_backend_initialised = 1;
return 0;
}
const char *crypt_backend_version(void)
{
return crypto_backend_initialised ? version : "";
}
uint32_t crypt_backend_flags(void)
{
return 0;
@@ -125,9 +117,10 @@ int crypt_hash_init(struct crypt_hash **ctx, const char *name)
return 0;
}
static void crypt_hash_restart(struct crypt_hash *ctx)
int 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)
@@ -140,7 +133,7 @@ int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length)
{
unsigned char *hash;
if (length > (size_t)ctx->hash_len)
if (length > ctx->hash_len)
return -EINVAL;
hash = gcry_md_read(ctx->hd, ctx->hash_id);
@@ -148,8 +141,6 @@ 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;
}
@@ -200,9 +191,10 @@ int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
return 0;
}
static void crypt_hmac_restart(struct crypt_hmac *ctx)
int 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,7 +207,7 @@ int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length)
{
unsigned char *hash;
if (length > (size_t)ctx->hash_len)
if (length > ctx->hash_len)
return -EINVAL;
hash = gcry_md_read(ctx->hd, ctx->hash_id);
@@ -223,8 +215,6 @@ 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;
}
@@ -235,19 +225,3 @@ 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;
}

View File

@@ -1,7 +1,7 @@
/*
* Linux kernel userspace API crypto backend implementation
*
* Copyright (C) 2010-2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-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
@@ -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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <string.h>
@@ -30,13 +30,10 @@
/* FIXME: remove later */
#ifndef AF_ALG
#define AF_ALG 38
#endif
#ifndef SOL_ALG
#define SOL_ALG 279
#endif
static int crypto_backend_initialised = 0;
static char version[64];
struct hash_alg {
const char *name;
@@ -94,6 +91,7 @@ bad:
int crypt_backend_init(struct crypt_device *ctx)
{
struct utsname uts;
struct sockaddr_alg sa = {
.salg_family = AF_ALG,
.salg_type = "hash",
@@ -104,8 +102,11 @@ 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;
@@ -113,9 +114,6 @@ 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,11 +123,6 @@ 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;
@@ -181,12 +174,17 @@ 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;
r = send(ctx->opfd, buffer, length, MSG_MORE);
if (r < 0 || (size_t)r < length)
if (r < 0 || r < length)
return -EIO;
return 0;
@@ -196,7 +194,7 @@ int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length)
{
ssize_t r;
if (length > (size_t)ctx->hash_len)
if (length > ctx->hash_len)
return -EINVAL;
r = read(ctx->opfd, buffer, length);
@@ -261,12 +259,17 @@ 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;
r = send(ctx->opfd, buffer, length, MSG_MORE);
if (r < 0 || (size_t)r < length)
if (r < 0 || r < length)
return -EIO;
return 0;
@@ -276,7 +279,7 @@ int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length)
{
ssize_t r;
if (length > (size_t)ctx->hash_len)
if (length > ctx->hash_len)
return -EINVAL;
r = read(ctx->opfd, buffer, length);
@@ -296,9 +299,3 @@ 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;
}

View File

@@ -1,276 +0,0 @@
/*
* Nettle crypto backend implementation
*
* 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 <string.h>
#include <errno.h>
#include <nettle/sha.h>
#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 *);
typedef void (*set_key_func) (void *, unsigned, const uint8_t *);
struct hash_alg {
const char *name;
int length;
init_func init;
update_func update;
digest_func digest;
update_func hmac_update;
digest_func hmac_digest;
set_key_func hmac_set_key;
};
static struct hash_alg hash_algs[] = {
{ "sha1", SHA1_DIGEST_SIZE,
(init_func) sha1_init,
(update_func) sha1_update,
(digest_func) sha1_digest,
(update_func) hmac_sha1_update,
(digest_func) hmac_sha1_digest,
(set_key_func) hmac_sha1_set_key,
},
{ "sha224", SHA224_DIGEST_SIZE,
(init_func) sha224_init,
(update_func) sha224_update,
(digest_func) sha224_digest,
(update_func) hmac_sha224_update,
(digest_func) hmac_sha224_digest,
(set_key_func) hmac_sha224_set_key,
},
{ "sha256", SHA256_DIGEST_SIZE,
(init_func) sha256_init,
(update_func) sha256_update,
(digest_func) sha256_digest,
(update_func) hmac_sha256_update,
(digest_func) hmac_sha256_digest,
(set_key_func) hmac_sha256_set_key,
},
{ "sha384", SHA384_DIGEST_SIZE,
(init_func) sha384_init,
(update_func) sha384_update,
(digest_func) sha384_digest,
(update_func) hmac_sha384_update,
(digest_func) hmac_sha384_digest,
(set_key_func) hmac_sha384_set_key,
},
{ "sha512", SHA512_DIGEST_SIZE,
(init_func) sha512_init,
(update_func) sha512_update,
(digest_func) sha512_digest,
(update_func) hmac_sha512_update,
(digest_func) hmac_sha512_digest,
(set_key_func) hmac_sha512_set_key,
},
{ "ripemd160", RIPEMD160_DIGEST_SIZE,
(init_func) ripemd160_init,
(update_func) ripemd160_update,
(digest_func) ripemd160_digest,
(update_func) hmac_ripemd160_update,
(digest_func) hmac_ripemd160_digest,
(set_key_func) hmac_ripemd160_set_key,
},
{ NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, }
};
struct crypt_hash {
const struct hash_alg *hash;
union {
struct sha1_ctx sha1;
struct sha224_ctx sha224;
struct sha256_ctx sha256;
struct sha384_ctx sha384;
struct sha512_ctx sha512;
} nettle_ctx;
};
struct crypt_hmac {
const struct hash_alg *hash;
union {
struct hmac_sha1_ctx sha1;
struct hmac_sha224_ctx sha224;
struct hmac_sha256_ctx sha256;
struct hmac_sha384_ctx sha384;
struct hmac_sha512_ctx sha512;
} nettle_ctx;
size_t key_length;
uint8_t *key;
};
uint32_t crypt_backend_flags(void)
{
return 0;
}
static struct hash_alg *_get_alg(const char *name)
{
int i = 0;
while (name && hash_algs[i].name) {
if (!strcmp(name, hash_algs[i].name))
return &hash_algs[i];
i++;
}
return NULL;
}
int crypt_backend_init(struct crypt_device *ctx)
{
return 0;
}
const char *crypt_backend_version(void)
{
return version;
}
/* HASH */
int crypt_hash_size(const char *name)
{
struct hash_alg *ha = _get_alg(name);
return ha ? ha->length : -EINVAL;
}
int crypt_hash_init(struct crypt_hash **ctx, const char *name)
{
struct crypt_hash *h;
h = malloc(sizeof(*h));
if (!h)
return -ENOMEM;
h->hash = _get_alg(name);
if (!h->hash) {
free(h);
return -EINVAL;
}
h->hash->init(&h->nettle_ctx);
*ctx = h;
return 0;
}
static void crypt_hash_restart(struct crypt_hash *ctx)
{
ctx->hash->init(&ctx->nettle_ctx);
}
int crypt_hash_write(struct crypt_hash *ctx, const char *buffer, size_t length)
{
ctx->hash->update(&ctx->nettle_ctx, length, (const uint8_t*)buffer);
return 0;
}
int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length)
{
if (length > (size_t)ctx->hash->length)
return -EINVAL;
ctx->hash->digest(&ctx->nettle_ctx, length, (uint8_t *)buffer);
crypt_hash_restart(ctx);
return 0;
}
int crypt_hash_destroy(struct crypt_hash *ctx)
{
memset(ctx, 0, sizeof(*ctx));
free(ctx);
return 0;
}
/* HMAC */
int crypt_hmac_size(const char *name)
{
return crypt_hash_size(name);
}
int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
const void *buffer, size_t length)
{
struct crypt_hmac *h;
h = malloc(sizeof(*h));
if (!h)
return -ENOMEM;
memset(ctx, 0, sizeof(*ctx));
h->hash = _get_alg(name);
if (!h->hash)
goto bad;
h->key = malloc(length);
if (!h->key)
goto bad;
memcpy(h->key, buffer, length);
h->key_length = length;
h->hash->init(&h->nettle_ctx);
h->hash->hmac_set_key(&h->nettle_ctx, h->key_length, h->key);
*ctx = h;
return 0;
bad:
free(h);
return -EINVAL;
}
static void crypt_hmac_restart(struct crypt_hmac *ctx)
{
ctx->hash->hmac_set_key(&ctx->nettle_ctx, ctx->key_length, ctx->key);
}
int crypt_hmac_write(struct crypt_hmac *ctx, const char *buffer, size_t length)
{
ctx->hash->hmac_update(&ctx->nettle_ctx, length, (const uint8_t *)buffer);
return 0;
}
int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length)
{
if (length > (size_t)ctx->hash->length)
return -EINVAL;
ctx->hash->hmac_digest(&ctx->nettle_ctx, length, (uint8_t *)buffer);
crypt_hmac_restart(ctx);
return 0;
}
int crypt_hmac_destroy(struct crypt_hmac *ctx)
{
memset(ctx->key, 0, ctx->key_length);
memset(ctx, 0, sizeof(*ctx));
free(ctx->key);
free(ctx);
return 0;
}
/* RNG - N/A */
int crypt_backend_rng(char *buffer, size_t length, int quality, int fips)
{
return -EINVAL;
}

View File

@@ -1,7 +1,7 @@
/*
* NSS crypto backend implementation
*
* Copyright (C) 2010-2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-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
@@ -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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <string.h>
@@ -23,10 +23,7 @@
#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;
@@ -73,14 +70,10 @@ 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;
}
@@ -90,11 +83,6 @@ 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)
{
@@ -133,7 +121,7 @@ int crypt_hash_init(struct crypt_hash **ctx, const char *name)
return 0;
}
static int crypt_hash_restart(struct crypt_hash *ctx)
int crypt_hash_restart(struct crypt_hash *ctx)
{
if (PK11_DigestBegin(ctx->md) != SECSuccess)
return -EINVAL;
@@ -143,7 +131,7 @@ static int crypt_hash_restart(struct crypt_hash *ctx)
int crypt_hash_write(struct crypt_hash *ctx, const char *buffer, size_t length)
{
if (PK11_DigestOp(ctx->md, CONST_CAST(unsigned char *)buffer, length) != SECSuccess)
if (PK11_DigestOp(ctx->md, (unsigned char *)buffer, length) != SECSuccess)
return -EINVAL;
return 0;
@@ -154,7 +142,7 @@ int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length)
unsigned char tmp[64];
unsigned int tmp_len;
if (length > (size_t)ctx->hash->length)
if (length > ctx->hash->length)
return -EINVAL;
if (PK11_DigestFinal(ctx->md, tmp, &tmp_len, length) != SECSuccess)
@@ -166,9 +154,6 @@ 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;
}
@@ -194,7 +179,7 @@ int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
SECItem noParams;
keyItem.type = siBuffer;
keyItem.data = CONST_CAST(unsigned char *)buffer;
keyItem.data = (unsigned char *)buffer;
keyItem.len = (int)length;
noParams.type = siBuffer;
@@ -235,7 +220,7 @@ bad:
return -EINVAL;
}
static int crypt_hmac_restart(struct crypt_hmac *ctx)
int crypt_hmac_restart(struct crypt_hmac *ctx)
{
if (PK11_DigestBegin(ctx->md) != SECSuccess)
return -EINVAL;
@@ -245,7 +230,7 @@ static 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, CONST_CAST(unsigned char *)buffer, length) != SECSuccess)
if (PK11_DigestOp(ctx->md, (unsigned char *)buffer, length) != SECSuccess)
return -EINVAL;
return 0;
@@ -256,7 +241,7 @@ int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length)
unsigned char tmp[64];
unsigned int tmp_len;
if (length > (size_t)ctx->hash->length)
if (length > ctx->hash->length)
return -EINVAL;
if (PK11_DigestFinal(ctx->md, tmp, &tmp_len, length) != SECSuccess)
@@ -268,9 +253,6 @@ 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;
}
@@ -286,15 +268,3 @@ 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;
}

View File

@@ -1,7 +1,7 @@
/*
* OPENSSL crypto backend implementation
*
* Copyright (C) 2010-2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-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
@@ -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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
@@ -30,7 +30,6 @@
#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;
@@ -53,6 +52,7 @@ 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,11 +63,6 @@ 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)
{
@@ -103,7 +98,7 @@ int crypt_hash_init(struct crypt_hash **ctx, const char *name)
return 0;
}
static int crypt_hash_restart(struct crypt_hash *ctx)
int crypt_hash_restart(struct crypt_hash *ctx)
{
if (EVP_DigestInit(&ctx->md, ctx->hash_id) != 1)
return -EINVAL;
@@ -124,7 +119,7 @@ int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length)
unsigned char tmp[EVP_MAX_MD_SIZE];
unsigned int tmp_len = 0;
if (length > (size_t)ctx->hash_len)
if (length > ctx->hash_len)
return -EINVAL;
if (EVP_DigestFinal_ex(&ctx->md, tmp, &tmp_len) != 1)
@@ -136,9 +131,6 @@ 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,9 +171,10 @@ int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
return 0;
}
static void crypt_hmac_restart(struct crypt_hmac *ctx)
int 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)
@@ -195,7 +188,7 @@ int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length)
unsigned char tmp[EVP_MAX_MD_SIZE];
unsigned int tmp_len = 0;
if (length > (size_t)ctx->hash_len)
if (length > ctx->hash_len)
return -EINVAL;
HMAC_Final(&ctx->md, tmp, &tmp_len);
@@ -206,8 +199,6 @@ 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;
}
@@ -218,15 +209,3 @@ 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;
}

View File

@@ -1,24 +1,3 @@
/*
* 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
@@ -32,28 +11,38 @@
#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
#define MAX_ERROR_LENGTH 512
/* 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 at_least(a, b) ({ __typeof__(a) __at_least = (a); (__at_least >= (b))?__at_least:(b); })
struct crypt_device;
struct hash_type {
char *name;
void *private;
int (*fn)(void *data, int size, char *key,
int sizep, const char *passphrase);
};
struct hash_backend {
const char *name;
struct hash_type * (*get_hashes)(void);
void (*free_hashes)(struct hash_type *hashes);
};
struct volume_key {
size_t keylength;
char key[];
@@ -63,56 +52,82 @@ struct volume_key *crypt_alloc_volume_key(unsigned keylength, const char *key);
struct volume_key *crypt_generate_volume_key(struct crypt_device *cd, unsigned keylength);
void crypt_free_volume_key(struct volume_key *vk);
/* Device backend */
struct device;
int device_alloc(struct device **device, const char *path);
void device_free(struct device *device);
const char *device_path(const struct device *device);
const char *device_block_path(const struct device *device);
void device_topology_alignment(struct device *device,
unsigned long *required_alignment, /* bytes */
unsigned long *alignment_offset, /* bytes */
unsigned long default_alignment);
int device_block_size(struct device *device);
int device_read_ahead(struct device *device, uint32_t *read_ahead);
int device_size(struct device *device, uint64_t *size);
enum devcheck { DEV_OK = 0, DEV_EXCL = 1, DEV_SHARED = 2 };
int device_block_adjust(struct crypt_device *cd,
struct device *device,
enum devcheck device_check,
uint64_t device_offset,
uint64_t *size,
uint32_t *flags);
size_t size_round_up(size_t size, unsigned int block);
/* Receive backend devices from context helpers */
struct device *crypt_metadata_device(struct crypt_device *cd);
struct device *crypt_data_device(struct crypt_device *cd);
int crypt_confirm(struct crypt_device *cd, const char *msg);
char *crypt_lookup_dev(const char *dev_id);
int crypt_sysfs_get_rotational(int major, int minor, int *rotational);
void set_error_va(const char *fmt, va_list va);
void set_error(const char *fmt, ...);
const char *get_error(void);
ssize_t write_blockwise(int fd, int bsize, void *buf, size_t count);
ssize_t read_blockwise(int fd, int bsize, void *_buf, size_t count);
ssize_t write_lseek_blockwise(int fd, int bsize, char *buf, size_t count, off_t offset);
/* 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 */
uint32_t dm_flags(void);
unsigned crypt_getpagesize(void);
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_suspend_and_wipe_key(const char *name);
int dm_resume_and_reinstate_key(const char *name,
size_t key_size,
const char *key);
int sector_size_for_device(const char *device);
ssize_t write_blockwise(int fd, const void *buf, size_t count);
ssize_t read_blockwise(int fd, void *_buf, size_t count);
ssize_t write_lseek_blockwise(int fd, const 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_check_and_adjust(struct crypt_device *cd,
const char *device,
int open_exclusive,
uint64_t *size,
uint64_t *offset,
int *read_only);
int wipe_device_header(const char *device, int sectors);
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...) logger(c, CRYPT_LOG_ERROR, __FILE__, __LINE__, x)
#define log_err(c, x...) do { \
logger(c, CRYPT_LOG_ERROR, __FILE__, __LINE__, x); \
set_error(x); } while(0)
int crypt_get_debug_level(void);
void debug_processes_using_device(const char *name);
int crypt_memlock_inc(struct crypt_device *ctx);
int crypt_memlock_dec(struct crypt_device *ctx);
void get_topology_alignment(const char *device,
unsigned long *required_alignment, /* bytes */
unsigned long *alignment_offset, /* bytes */
unsigned long default_alignment);
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);
@@ -122,29 +137,5 @@ 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(struct device *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

View File

@@ -2,37 +2,30 @@ 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;
@@ -43,10 +36,8 @@ 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;
@@ -55,9 +46,7 @@ CRYPTSETUP_1.0 {
crypt_get_rng_type;
crypt_keyslot_max;
crypt_keyslot_area;
crypt_keyslot_status;
crypt_last_error;
crypt_get_error;
crypt_get_dir;
crypt_set_debug_level;
@@ -65,6 +54,22 @@ 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:
*;
};

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
/*
* loop-AES compatible volume handling
*
* Copyright (C) 2011-2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 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
@@ -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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <errno.h>
@@ -22,13 +22,12 @@
#include <stdlib.h>
#include <string.h>
#include "libcryptsetup.h"
#include "crypto_backend.h"
#include "loopaes.h"
#include "internal.h"
static const char *get_hash(unsigned int key_size)
{
const char *hash;
char *hash;
switch (key_size) {
case 16: hash = "sha256"; break;
@@ -77,8 +76,7 @@ static int hash_keys(struct crypt_device *cd,
{
const char *hash_name;
char tweak, *key_ptr;
unsigned i, key_len_input;
int r;
int r, i, key_len_input;
hash_name = hash_override ?: get_hash(key_len_output);
tweak = get_tweak(keys_count);
@@ -132,7 +130,7 @@ int LOOPAES_parse_keyfile(struct crypt_device *cd,
size_t buffer_len)
{
const char *keys[LOOPAES_KEYS_MAX];
unsigned i, key_index, key_len, offset;
int i, key_index, key_len, offset;
log_dbg("Parsing loop-AES keyfile of size %d.", buffer_len);
@@ -186,27 +184,22 @@ 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)
{
char *cipher = NULL;
uint64_t size;
uint32_t req_flags;
int r;
struct crypt_dm_active_device dmd = {
.target = DM_CRYPT,
.uuid = crypt_get_uuid(cd),
.size = 0,
.flags = flags,
.data_device = crypt_data_device(cd),
.u.crypt = {
.cipher = NULL,
.vk = vk,
.offset = crypt_get_data_offset(cd),
.iv_offset = crypt_get_iv_offset(cd),
}
};
char *cipher;
const char *device;
int read_only, r;
r = device_block_adjust(cd, dmd.data_device, DEV_EXCL,
dmd.u.crypt.offset, &dmd.size, &dmd.flags);
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);
if (r)
return r;
@@ -220,11 +213,12 @@ int LOOPAES_activate(struct crypt_device *cd,
if (r < 0)
return -ENOMEM;
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(cd, name, CRYPT_LOOPAES, &dmd, 0);
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);
if (!r && !(dm_flags() & req_flags)) {
log_err(cd, _("Kernel doesn't support loop-AES compatible mapping.\n"));

View File

@@ -1,31 +1,9 @@
/*
* 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,
@@ -40,5 +18,7 @@ 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

View File

@@ -2,7 +2,7 @@
* AFsplitter - Anti forensic information splitter
*
* Copyright (C) 2004, Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2011, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stddef.h>
@@ -26,8 +26,8 @@
#include <string.h>
#include <netinet/in.h>
#include <errno.h>
#include "crypto_backend.h"
#include "internal.h"
#include "af.h"
static void XORblock(const char *src1, const char *src2, char *dst, size_t n)
{
@@ -66,14 +66,9 @@ out:
static int diffuse(char *src, char *dst, size_t size, const char *hash_name)
{
int hash_size = crypt_hash_size(hash_name);
unsigned int digest_size;
unsigned int digest_size = crypt_hash_size(hash_name);
unsigned int i, blocks, padding;
if (hash_size <= 0)
return 1;
digest_size = hash_size;
blocks = size / digest_size;
padding = size % digest_size;
@@ -146,17 +141,3 @@ out:
free(bufblock);
return r;
}
/* Size of final split data including sector alignment */
size_t AF_split_sectors(size_t blocksize, unsigned int blocknumbers)
{
size_t af_size;
/* data material * stripes */
af_size = blocksize * blocknumbers;
/* round up to sector */
af_size = (af_size + (SECTOR_SIZE - 1)) / SECTOR_SIZE;
return af_size;
}

View File

@@ -1,28 +1,11 @@
/*
* AFsplitter - Anti forensic information splitter
*
* 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
/*
* AFsplitter - Anti forensic information splitter
* Copyright 2004, Clemens Fruhwirth <clemens@endorphin.org>
*/
/*
* AF_split operates on src and produces information split data in
* dst. src is assumed to be of the length blocksize. The data stripe
@@ -38,6 +21,5 @@
int AF_split(char *src, char *dst, size_t blocksize, unsigned int blocknumbers, const char *hash);
int AF_merge(char *src, char *dst, size_t blocksize, unsigned int blocknumbers, const char *hash);
size_t AF_split_sectors(size_t blocksize, unsigned int blocknumbers);
#endif

View File

@@ -2,7 +2,6 @@
* 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
@@ -15,12 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <inttypes.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/utsname.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
@@ -29,67 +35,82 @@
#include "luks.h"
#include "internal.h"
#define div_round_up(a,b) ({ \
typeof(a) __a = (a); \
typeof(b) __b = (b); \
(__a - 1) / __b + 1; \
})
static inline int round_up_modulo(int x, int m) {
return div_round_up(x, m) * m;
}
static const char *cleaner_name=NULL;
static uint64_t cleaner_size = 0;
static int devfd=-1;
static int setup_mapping(const char *cipher, const char *name,
unsigned int bsize, struct volume_key *vk,
const char *device, unsigned int payloadOffset,
const char *key, size_t keyLength,
unsigned int sector, size_t srcLength,
int mode, struct crypt_device *ctx)
{
struct device *device = crypt_metadata_device(ctx);
struct crypt_dm_active_device dmd = {
.target = DM_CRYPT,
.uuid = NULL,
.size = size_round_up(srcLength, bsize) / SECTOR_SIZE,
.flags = CRYPT_ACTIVATE_PRIVATE,
.data_device = device,
.u.crypt = {
.cipher = cipher,
.vk = vk,
.offset = sector,
.iv_offset = 0,
}
};
int r;
int device_sector_size = sector_size_for_device(device);
uint64_t size;
if (mode == O_RDONLY)
dmd.flags |= CRYPT_ACTIVATE_READONLY;
r = device_block_adjust(ctx, dmd.data_device, DEV_OK,
dmd.u.crypt.offset, &dmd.size, &dmd.flags);
if (r < 0)
return r;
if (mode != O_RDONLY && dmd.flags & CRYPT_ACTIVATE_READONLY) {
log_err(ctx, _("Cannot write to device %s, permission denied.\n"),
device_path(device));
return -EACCES;
/*
* we need to round this to nearest multiple of the underlying
* device's sector size, otherwise the mapping will be refused.
*/
if(device_sector_size < 0) {
log_err(ctx, _("Unable to obtain sector size for %s"), device);
return -EINVAL;
}
cleaner_size = dmd.size;
return dm_create_device(ctx, name, "TEMP", &dmd, 0);
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);
}
static void sigint_handler(int sig __attribute__((unused)))
static void sigint_handler(int sig)
{
if(devfd >= 0)
close(devfd);
devfd = -1;
if(cleaner_name)
dm_remove_device(NULL, cleaner_name, 1, cleaner_size);
dm_remove_device(cleaner_name, 1, cleaner_size);
signal(SIGINT, SIG_DFL);
kill(getpid(), SIGINT);
}
static const char *_error_hint(char *cipherMode, size_t keyLength)
static char *_error_hint(char *cipherName, char *cipherMode, size_t keyLength)
{
const char *hint= "";
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;
}
@@ -97,9 +118,10 @@ 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,
struct volume_key *vk,
char *key, size_t keyLength,
const char *device,
unsigned int sector,
ssize_t (*func)(int, int, void *, size_t),
ssize_t (*func)(int, void *, size_t),
int mode,
struct crypt_device *ctx)
{
@@ -108,14 +130,10 @@ static int LUKS_endec_template(char *src, size_t srcLength,
char *dmCipherSpec = NULL;
const char *dmDir = dm_get_dir();
int r = -1;
int bsize = device_block_size(crypt_metadata_device(ctx));
if (bsize <= 0)
return -EINVAL;
if(dmDir == NULL) {
log_err(ctx, _("Failed to obtain device mapper directory."));
return -EINVAL;
return -1;
}
if(asprintf(&name,"temporary-cryptsetup-%d",getpid()) == -1 ||
asprintf(&fullpath,"%s/%s",dmDir,name) == -1 ||
@@ -127,13 +145,13 @@ static int LUKS_endec_template(char *src, size_t srcLength,
signal(SIGINT, sigint_handler);
cleaner_name = name;
r = setup_mapping(dmCipherSpec, name, bsize, vk, sector, srcLength, mode, ctx);
r = setup_mapping(dmCipherSpec, name, device, hdr->payloadOffset,
key, keyLength, sector, srcLength, mode, ctx);
if(r < 0) {
if (r != -EACCES && r != -ENOTSUP)
log_err(ctx, _("Failed to setup dm-crypt key mapping for device %s.\n"
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_path(crypt_metadata_device(ctx)), dmCipherSpec,
_error_hint(hdr->cipherMode, vk->keylength * 8));
device, dmCipherSpec,
_error_hint(hdr->cipherName, hdr->cipherMode, keyLength * 8));
r = -EIO;
goto out1;
}
@@ -145,7 +163,7 @@ static int LUKS_endec_template(char *src, size_t srcLength,
goto out2;
}
r = func(devfd, bsize, src, srcLength);
r = func(devfd,src,srcLength);
if(r < 0) {
log_err(ctx, _("Failed to access temporary keystore device.\n"));
r = -EIO;
@@ -157,7 +175,7 @@ static int LUKS_endec_template(char *src, size_t srcLength,
close(devfd);
devfd = -1;
out2:
dm_remove_device(ctx, cleaner_name, 1, cleaner_size);
dm_remove_device(cleaner_name, 1, cleaner_size);
out1:
signal(SIGINT, SIG_DFL);
cleaner_name = NULL;
@@ -170,20 +188,23 @@ static int LUKS_endec_template(char *src, size_t srcLength,
int LUKS_encrypt_to_storage(char *src, size_t srcLength,
struct luks_phdr *hdr,
struct volume_key *vk,
char *key, size_t keyLength,
const char *device,
unsigned int sector,
struct crypt_device *ctx)
{
return LUKS_endec_template(src, srcLength, hdr, vk, sector,
write_blockwise, O_RDWR, ctx);
return LUKS_endec_template(src,srcLength,hdr,key,keyLength, device, sector,
(ssize_t (*)(int, void *, size_t)) write_blockwise,
O_RDWR, ctx);
}
int LUKS_decrypt_from_storage(char *dst, size_t dstLength,
struct luks_phdr *hdr,
struct volume_key *vk,
char *key, size_t keyLength,
const char *device,
unsigned int sector,
struct crypt_device *ctx)
{
return LUKS_endec_template(dst, dstLength, hdr, vk, sector,
read_blockwise, O_RDONLY, ctx);
return LUKS_endec_template(dst,dstLength,hdr,key,keyLength, device,
sector, read_blockwise, O_RDONLY, ctx);
}

View File

@@ -2,7 +2,6 @@
* 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
@@ -15,11 +14,13 @@
*
* 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.
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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>
@@ -28,7 +29,6 @@
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include <uuid/uuid.h>
#include "luks.h"
@@ -36,102 +36,17 @@
#include "pbkdf.h"
#include "internal.h"
/* Get size of struct luks_phdr with all keyslots material space */
static size_t LUKS_device_sectors(size_t keyLen)
{
size_t keyslot_sectors, sector;
int i;
#define div_round_up(a,b) ({ \
typeof(a) __a = (a); \
typeof(b) __b = (b); \
(__a - 1) / __b + 1; \
})
keyslot_sectors = AF_split_sectors(keyLen, LUKS_STRIPES);
sector = LUKS_ALIGN_KEYSLOTS / SECTOR_SIZE;
for (i = 0; i < LUKS_NUMKEYS; i++) {
sector = size_round_up(sector, LUKS_ALIGN_KEYSLOTS / SECTOR_SIZE);
sector += keyslot_sectors;
}
return sector;
static inline int round_up_modulo(int x, int m) {
return div_round_up(x, m) * m;
}
int LUKS_keyslot_area(struct luks_phdr *hdr,
int keyslot,
uint64_t *offset,
uint64_t *length)
{
if(keyslot >= LUKS_NUMKEYS || keyslot < 0)
return -EINVAL;
*offset = hdr->keyblock[keyslot].keyMaterialOffset * SECTOR_SIZE;
*length = AF_split_sectors(hdr->keyBytes, LUKS_STRIPES) * SECTOR_SIZE;
return 0;
}
static int LUKS_check_device_size(struct crypt_device *ctx, size_t keyLength)
{
struct device *device = crypt_metadata_device(ctx);
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_path(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_path(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 = AF_split_sectors(phdr->keyBytes, phdr->keyblock[keyIndex].stripes);
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)
const char *dbg_slot_state(crypt_keyslot_info ki)
{
switch(ki) {
case CRYPT_SLOT_INACTIVE:
@@ -148,12 +63,12 @@ static const char *dbg_slot_state(crypt_keyslot_info ki)
int LUKS_hdr_backup(
const char *backup_file,
const char *device,
struct luks_phdr *hdr,
struct crypt_device *ctx)
{
struct device *device = crypt_metadata_device(ctx);
int r = 0, devfd = -1;
ssize_t buffer_size;
size_t buffer_size;
char *buffer = NULL;
struct stat st;
@@ -162,11 +77,11 @@ int LUKS_hdr_backup(
return -EINVAL;
}
r = LUKS_read_phdr(hdr, 1, 0, ctx);
r = LUKS_read_phdr(device, hdr, 1, ctx);
if (r)
return r;
buffer_size = LUKS_device_sectors(hdr->keyBytes) << SECTOR_SHIFT;
buffer_size = hdr->payloadOffset << SECTOR_SHIFT;
buffer = crypt_safe_alloc(buffer_size);
if (!buffer || buffer_size < LUKS_ALIGN_KEYSLOTS) {
r = -ENOMEM;
@@ -176,22 +91,21 @@ int LUKS_hdr_backup(
log_dbg("Storing backup of header (%u bytes) and keyslot area (%u bytes).",
sizeof(*hdr), buffer_size - LUKS_ALIGN_KEYSLOTS);
devfd = open(device_path(device), O_RDONLY | O_DIRECT | O_SYNC);
devfd = open(device, O_RDONLY | O_DIRECT | O_SYNC);
if(devfd == -1) {
log_err(ctx, _("Device %s is not a valid LUKS device.\n"), device_path(device));
log_err(ctx, _("Device %s is not a valid LUKS device.\n"), device);
r = -EINVAL;
goto out;
}
if(read_blockwise(devfd, device_block_size(device), buffer, buffer_size) < buffer_size) {
if(read_blockwise(devfd, buffer, buffer_size) < buffer_size) {
r = -EIO;
goto out;
}
close(devfd);
/* Wipe unused area, so backup cannot contain old signatures */
if (hdr->keyblock[0].keyMaterialOffset * SECTOR_SIZE == LUKS_ALIGN_KEYSLOTS)
memset(buffer + sizeof(*hdr), 0, LUKS_ALIGN_KEYSLOTS - sizeof(*hdr));
memset(buffer + sizeof(*hdr), 0, LUKS_ALIGN_KEYSLOTS - sizeof(*hdr));
devfd = creat(backup_file, S_IRUSR);
if(devfd == -1) {
@@ -215,12 +129,12 @@ out:
int LUKS_hdr_restore(
const char *backup_file,
const char *device,
struct luks_phdr *hdr,
struct crypt_device *ctx)
{
struct device *device = crypt_metadata_device(ctx);
int r = 0, devfd = -1, diff_uuid = 0;
ssize_t buffer_size = 0;
size_t buffer_size;
char *buffer = NULL, msg[200];
struct stat st;
struct luks_phdr hdr_file;
@@ -230,12 +144,11 @@ int LUKS_hdr_restore(
return -EINVAL;
}
r = LUKS_read_phdr_backup(backup_file, &hdr_file, 0, ctx);
if (!r)
buffer_size = LUKS_device_sectors(hdr_file.keyBytes) << SECTOR_SHIFT;
r = LUKS_read_phdr_backup(backup_file, device, &hdr_file, 0, ctx);
buffer_size = hdr_file.payloadOffset << SECTOR_SHIFT;
if (r || buffer_size < LUKS_ALIGN_KEYSLOTS) {
log_err(ctx, _("Backup file doesn't contain valid LUKS header.\n"));
log_err(ctx, _("Backup file do not contain valid LUKS header.\n"));
r = -EINVAL;
goto out;
}
@@ -260,9 +173,9 @@ int LUKS_hdr_restore(
}
close(devfd);
r = LUKS_read_phdr(hdr, 0, 0, ctx);
r = LUKS_read_phdr(device, hdr, 0, ctx);
if (r == 0) {
log_dbg("Device %s already contains LUKS header, checking UUID and offset.", device_path(device));
log_dbg("Device %s already contains LUKS header, checking UUID and offset.", device);
if(hdr->payloadOffset != hdr_file.payloadOffset ||
hdr->keyBytes != hdr_file.keyBytes) {
log_err(ctx, _("Data offset or key size differs on device and backup, restore failed.\n"));
@@ -273,7 +186,7 @@ int LUKS_hdr_restore(
diff_uuid = 1;
}
if (snprintf(msg, sizeof(msg), _("Device %s %s%s"), device_path(device),
if (snprintf(msg, sizeof(msg), _("Device %s %s%s"), device,
r ? _("does not contain LUKS header. Replacing header can destroy data on that device.") :
_("already contains LUKS header. Replacing header will destroy existing keyslots."),
diff_uuid ? _("\nWARNING: real device header has different UUID than backup!") : "") < 0) {
@@ -287,27 +200,23 @@ int LUKS_hdr_restore(
}
log_dbg("Storing backup of header (%u bytes) and keyslot area (%u bytes) to device %s.",
sizeof(*hdr), buffer_size - LUKS_ALIGN_KEYSLOTS, device_path(device));
sizeof(*hdr), buffer_size - LUKS_ALIGN_KEYSLOTS, device);
devfd = open(device_path(device), O_WRONLY | O_DIRECT | O_SYNC);
devfd = open(device, O_WRONLY | O_DIRECT | O_SYNC);
if(devfd == -1) {
if (errno == EACCES)
log_err(ctx, _("Cannot write to device %s, permission denied.\n"),
device_path(device));
else
log_err(ctx, _("Cannot open device %s.\n"), device_path(device));
log_err(ctx, _("Cannot open device %s.\n"), device);
r = -EINVAL;
goto out;
}
if (write_blockwise(devfd, device_block_size(device), buffer, buffer_size) < buffer_size) {
if(write_blockwise(devfd, buffer, buffer_size) < buffer_size) {
r = -EIO;
goto out;
}
close(devfd);
/* Be sure to reload new data */
r = LUKS_read_phdr(hdr, 1, 0, ctx);
r = LUKS_read_phdr(device, hdr, 0, ctx);
out:
if (devfd != -1)
close(devfd);
@@ -315,96 +224,9 @@ out:
return r;
}
/* This routine should do some just basic recovery for known problems. */
static int _keyslot_repair(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,
1, 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(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;
@@ -415,46 +237,28 @@ 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);
return -EINVAL;
else
set_error(_("Device %s is not a valid LUKS device."), device);
r = -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);
return -EINVAL;
}
hdr->hashSpec[LUKS_HASHSPEC_L - 1] = '\0';
if (PBKDF2_HMAC_ready(hdr->hashSpec) < 0) {
r = -EINVAL;
} else if (PBKDF2_HMAC_ready(hdr->hashSpec) < 0) {
log_err(ctx, _("Requested LUKS hash %s is not supported.\n"), hdr->hashSpec);
return -EINVAL;
}
r = -EINVAL;
} else {
hdr->payloadOffset = ntohl(hdr->payloadOffset);
hdr->keyBytes = ntohl(hdr->keyBytes);
hdr->mkDigestIterations = ntohl(hdr->mkDigestIterations);
/* 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;
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);
}
}
/* 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(hdr, ctx);
else
log_verbose(ctx, _("No known problems detected for LUKS header.\n"));
}
return r;
}
@@ -473,102 +277,86 @@ static void LUKS_fix_header_compatible(struct luks_phdr *header)
}
int LUKS_read_phdr_backup(const char *backup_file,
const char *device,
struct luks_phdr *hdr,
int require_luks_device,
struct crypt_device *ctx)
{
ssize_t hdr_size = sizeof(struct luks_phdr);
int devfd = 0, r = 0;
log_dbg("Reading LUKS header of size %d from backup file %s",
(int)hdr_size, backup_file);
sizeof(struct luks_phdr), backup_file);
devfd = open(backup_file, O_RDONLY);
if(-1 == devfd) {
log_err(ctx, _("Cannot open file %s.\n"), backup_file);
log_err(ctx, _("Cannot open file %s.\n"), device);
return -EINVAL;
}
if (read(devfd, hdr, hdr_size) < hdr_size)
if(read(devfd, hdr, sizeof(struct luks_phdr)) < sizeof(struct luks_phdr))
r = -EIO;
else {
LUKS_fix_header_compatible(hdr);
r = _check_and_convert_hdr(backup_file, hdr,
require_luks_device, 0, ctx);
r = _check_and_convert_hdr(backup_file, hdr, require_luks_device, ctx);
}
close(devfd);
return r;
}
int LUKS_read_phdr(struct luks_phdr *hdr,
int LUKS_read_phdr(const char *device,
struct luks_phdr *hdr,
int require_luks_device,
int repair,
struct crypt_device *ctx)
{
struct device *device = crypt_metadata_device(ctx);
ssize_t hdr_size = sizeof(struct luks_phdr);
int devfd = 0, r = 0;
/* LUKS header starts at offset 0, first keyslot on LUKS_ALIGN_KEYSLOTS */
assert(sizeof(struct luks_phdr) <= LUKS_ALIGN_KEYSLOTS);
/* Stripes count cannot be changed without additional code fixes yet */
assert(LUKS_STRIPES == 4000);
if (repair && !require_luks_device)
return -EINVAL;
uint64_t size;
log_dbg("Reading LUKS header of size %d from device %s",
hdr_size, device_path(device));
sizeof(struct luks_phdr), device);
devfd = open(device_path(device), O_RDONLY | O_DIRECT | O_SYNC);
if (devfd == -1) {
log_err(ctx, _("Cannot open device %s.\n"), device_path(device));
devfd = open(device,O_RDONLY | O_DIRECT | O_SYNC);
if(-1 == devfd) {
log_err(ctx, _("Cannot open device %s.\n"), device);
return -EINVAL;
}
if (read_blockwise(devfd, device_block_size(device), hdr, hdr_size) < hdr_size)
if(read_blockwise(devfd, hdr, sizeof(struct luks_phdr)) < sizeof(struct luks_phdr))
r = -EIO;
else
r = _check_and_convert_hdr(device_path(device), hdr, require_luks_device,
repair, ctx);
if (!r)
r = LUKS_check_device_size(ctx, hdr->keyBytes);
r = _check_and_convert_hdr(device, hdr, require_luks_device, ctx);
#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;
}
int LUKS_write_phdr(struct luks_phdr *hdr,
int LUKS_write_phdr(const char *device,
struct luks_phdr *hdr,
struct crypt_device *ctx)
{
struct device *device = crypt_metadata_device(ctx);
ssize_t hdr_size = sizeof(struct luks_phdr);
int devfd = 0;
unsigned int i;
struct luks_phdr convHdr;
int r;
log_dbg("Updating LUKS header of size %d on device %s",
sizeof(struct luks_phdr), device_path(device));
sizeof(struct luks_phdr), device);
r = LUKS_check_device_size(ctx, hdr->keyBytes);
if (r)
return r;
devfd = open(device_path(device), O_RDWR | O_DIRECT | O_SYNC);
devfd = open(device,O_RDWR | O_DIRECT | O_SYNC);
if(-1 == devfd) {
if (errno == EACCES)
log_err(ctx, _("Cannot write to device %s, permission denied.\n"),
device_path(device));
else
log_err(ctx, _("Cannot open device %s.\n"), device_path(device));
log_err(ctx, _("Cannot open device %s.\n"), device);
return -EINVAL;
}
memcpy(&convHdr, hdr, hdr_size);
memcpy(&convHdr, hdr, sizeof(struct luks_phdr));
memset(&convHdr._padding, 0, sizeof(convHdr._padding));
/* Convert every uint16/32_t item to network byte order */
@@ -583,17 +371,16 @@ int LUKS_write_phdr(struct luks_phdr *hdr,
convHdr.keyblock[i].stripes = htonl(hdr->keyblock[i].stripes);
}
r = write_blockwise(devfd, device_block_size(device), &convHdr, hdr_size) < hdr_size ? -EIO : 0;
r = write_blockwise(devfd, &convHdr, sizeof(struct luks_phdr)) < sizeof(struct luks_phdr) ? -EIO : 0;
if (r)
log_err(ctx, _("Error during update of LUKS header on device %s.\n"), device_path(device));
log_err(ctx, _("Error during update of LUKS header on device %s.\n"), device);
close(devfd);
/* Re-read header from disk to be sure that in-memory and on-disk data are the same. */
if (!r) {
r = LUKS_read_phdr(hdr, 1, 0, ctx);
r = LUKS_read_phdr(device, hdr, 1, ctx);
if (r)
log_err(ctx, _("Error re-reading LUKS header after update on device %s.\n"),
device_path(device));
log_err(ctx, _("Error re-reading LUKS header after update on device %s.\n"), device);
}
return r;
@@ -622,17 +409,16 @@ int LUKS_generate_phdr(struct luks_phdr *header,
unsigned int alignOffset,
uint32_t iteration_time_ms,
uint64_t *PBKDF2_per_sec,
int detached_metadata_device,
struct crypt_device *ctx)
{
unsigned int i=0;
size_t blocksPerStripeSet, currentSector;
unsigned int blocksPerStripeSet = div_round_up(vk->keylength*stripes,SECTOR_SIZE);
int r;
uuid_t partitionUuid;
char luksMagic[] = LUKS_MAGIC;
uuid_t partitionUuid;
int currentSector;
/* For separate metadata device allow zero alignment */
if (alignPayload == 0 && !detached_metadata_device)
if (alignPayload == 0)
alignPayload = DEFAULT_DISK_ALIGNMENT / SECTOR_SIZE;
if (PBKDF2_HMAC_ready(hashSpec) < 0) {
@@ -664,7 +450,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_SALT);
r = crypt_random_get(ctx, header->mkDigestSalt, LUKS_SALTSIZE, CRYPT_RND_NORMAL);
if(r < 0) {
log_err(ctx, _("Cannot create LUKS header: reading random salt failed.\n"));
return r;
@@ -688,24 +474,18 @@ int LUKS_generate_phdr(struct luks_phdr *header,
return r;
}
currentSector = LUKS_ALIGN_KEYSLOTS / SECTOR_SIZE;
blocksPerStripeSet = AF_split_sectors(vk->keylength, stripes);
currentSector = round_up_modulo(LUKS_PHDR_SIZE, LUKS_ALIGN_KEYSLOTS / SECTOR_SIZE);
for(i = 0; i < LUKS_NUMKEYS; ++i) {
header->keyblock[i].active = LUKS_KEY_DISABLED;
header->keyblock[i].keyMaterialOffset = currentSector;
header->keyblock[i].stripes = stripes;
currentSector = size_round_up(currentSector + blocksPerStripeSet,
currentSector = round_up_modulo(currentSector + blocksPerStripeSet,
LUKS_ALIGN_KEYSLOTS / SECTOR_SIZE);
}
currentSector = round_up_modulo(currentSector, alignPayload);
if (detached_metadata_device) {
/* for separate metadata device use alignPayload directly */
header->payloadOffset = alignPayload;
} else {
/* alignOffset - offset from natural device alignment provided by topology info */
currentSector = size_round_up(currentSector, alignPayload);
header->payloadOffset = currentSector + alignOffset;
}
/* alignOffset - offset from natural device alignment provided by topology info */
header->payloadOffset = currentSector + alignOffset;
uuid_unparse(partitionUuid, header->uuid);
@@ -716,6 +496,7 @@ int LUKS_generate_phdr(struct luks_phdr *header,
}
int LUKS_hdr_uuid_set(
const char *device,
struct luks_phdr *hdr,
const char *uuid,
struct crypt_device *ctx)
@@ -731,19 +512,19 @@ int LUKS_hdr_uuid_set(
uuid_unparse(partitionUuid, hdr->uuid);
return LUKS_write_phdr(hdr, ctx);
return LUKS_write_phdr(device, hdr, ctx);
}
int LUKS_set_key(unsigned int keyIndex,
int LUKS_set_key(const char *device, unsigned int keyIndex,
const char *password, size_t passwordLen,
struct luks_phdr *hdr, struct volume_key *vk,
uint32_t iteration_time_ms,
uint64_t *PBKDF2_per_sec,
struct crypt_device *ctx)
{
struct volume_key *derived_key;
char derivedKey[hdr->keyBytes];
char *AfKey = NULL;
size_t AFEKSize;
unsigned int AFEKSize;
uint64_t PBKDF2_temp;
int r;
@@ -752,8 +533,7 @@ int LUKS_set_key(unsigned int keyIndex,
return -EINVAL;
}
/* LUKS keyslot has always at least 4000 stripes accoding to specification */
if(hdr->keyblock[keyIndex].stripes < 4000) {
if(hdr->keyblock[keyIndex].stripes < LUKS_STRIPES) {
log_err(ctx, _("Key slot %d material includes too few stripes. Header manipulation?\n"),
keyIndex);
return -EINVAL;
@@ -777,27 +557,24 @@ int LUKS_set_key(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_SALT);
LUKS_SALTSIZE, CRYPT_RND_NORMAL);
if (r < 0)
goto out;
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,
derived_key->key, hdr->keyBytes);
derivedKey, 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 = AF_split_sectors(vk->keylength, hdr->keyblock[keyIndex].stripes) * SECTOR_SIZE;
AFEKSize = hdr->keyblock[keyIndex].stripes*vk->keylength;
AfKey = crypt_safe_alloc(AFEKSize);
if (!AfKey) {
r = -ENOMEM;
@@ -810,31 +587,36 @@ int LUKS_set_key(unsigned int keyIndex,
if (r < 0)
goto out;
log_dbg("Updating key slot %d [0x%04x] area.", keyIndex,
hdr->keyblock[keyIndex].keyMaterialOffset << 9);
log_dbg("Updating key slot %d [0x%04x] area on device %s.", keyIndex,
hdr->keyblock[keyIndex].keyMaterialOffset << 9, device);
/* Encryption via dm */
r = LUKS_encrypt_to_storage(AfKey,
AFEKSize,
hdr,
derived_key,
derivedKey,
hdr->keyBytes,
device,
hdr->keyblock[keyIndex].keyMaterialOffset,
ctx);
if (r < 0)
if (r < 0) {
if(!get_error())
log_err(ctx, _("Failed to write to key storage.\n"));
goto out;
}
/* Mark the key as active in phdr */
r = LUKS_keyslot_set(hdr, (int)keyIndex, 1);
if (r < 0)
goto out;
r = LUKS_write_phdr(hdr, ctx);
r = LUKS_write_phdr(device, hdr, ctx);
if (r < 0)
goto out;
r = 0;
out:
crypt_safe_free(AfKey);
crypt_free_volume_key(derived_key);
memset(derivedKey, 0, sizeof(derivedKey));
return r;
}
@@ -857,7 +639,8 @@ int LUKS_verify_volume_key(const struct luks_phdr *hdr,
}
/* Try to open a particular key slot */
static int LUKS_open_key(unsigned int keyIndex,
static int LUKS_open_key(const char *device,
unsigned int keyIndex,
const char *password,
size_t passwordLen,
struct luks_phdr *hdr,
@@ -865,7 +648,7 @@ static int LUKS_open_key(unsigned int keyIndex,
struct crypt_device *ctx)
{
crypt_keyslot_info ki = LUKS_keyslot_info(hdr, keyIndex);
struct volume_key *derived_key;
char derivedKey[hdr->keyBytes];
char *AfKey;
size_t AFEKSize;
int r;
@@ -876,22 +659,17 @@ static int LUKS_open_key(unsigned int keyIndex,
if (ki < CRYPT_SLOT_ACTIVE)
return -ENOENT;
derived_key = crypt_alloc_volume_key(hdr->keyBytes, NULL);
if (!derived_key)
return -ENOMEM;
// assert((vk->keylength % TWOFISH_BLOCKSIZE) == 0); FIXME
assert(vk->keylength == hdr->keyBytes);
AFEKSize = AF_split_sectors(vk->keylength, hdr->keyblock[keyIndex].stripes) * SECTOR_SIZE;
AFEKSize = hdr->keyblock[keyIndex].stripes*vk->keylength;
AfKey = crypt_safe_alloc(AFEKSize);
if (!AfKey) {
r = -ENOMEM;
goto out;
}
if (!AfKey)
return -ENOMEM;
r = PBKDF2_HMAC(hdr->hashSpec, password,passwordLen,
hdr->keyblock[keyIndex].passwordSalt,LUKS_SALTSIZE,
hdr->keyblock[keyIndex].passwordIterations,
derived_key->key, hdr->keyBytes);
derivedKey, hdr->keyBytes);
if (r < 0)
goto out;
@@ -899,11 +677,15 @@ static int LUKS_open_key(unsigned int keyIndex,
r = LUKS_decrypt_from_storage(AfKey,
AFEKSize,
hdr,
derived_key,
derivedKey,
hdr->keyBytes,
device,
hdr->keyblock[keyIndex].keyMaterialOffset,
ctx);
if (r < 0)
if (r < 0) {
log_err(ctx, _("Failed to read from key storage.\n"));
goto out;
}
r = AF_merge(AfKey,vk->key,vk->keylength,hdr->keyblock[keyIndex].stripes,hdr->hashSpec);
if (r < 0)
@@ -914,11 +696,12 @@ static int LUKS_open_key(unsigned int keyIndex,
log_verbose(ctx, _("Key slot %d unlocked.\n"), keyIndex);
out:
crypt_safe_free(AfKey);
crypt_free_volume_key(derived_key);
memset(derivedKey, 0, sizeof(derivedKey));
return r;
}
int LUKS_open_key_with_hdr(int keyIndex,
int LUKS_open_key_with_hdr(const char *device,
int keyIndex,
const char *password,
size_t passwordLen,
struct luks_phdr *hdr,
@@ -931,12 +714,12 @@ int LUKS_open_key_with_hdr(int keyIndex,
*vk = crypt_alloc_volume_key(hdr->keyBytes, NULL);
if (keyIndex >= 0) {
r = LUKS_open_key(keyIndex, password, passwordLen, hdr, *vk, ctx);
r = LUKS_open_key(device, keyIndex, password, passwordLen, hdr, *vk, ctx);
return (r < 0) ? r : keyIndex;
}
for(i = 0; i < LUKS_NUMKEYS; i++) {
r = LUKS_open_key(i, password, passwordLen, hdr, *vk, ctx);
r = LUKS_open_key(device, i, password, passwordLen, hdr, *vk, ctx);
if(r == 0)
return i;
@@ -950,15 +733,77 @@ int LUKS_open_key_with_hdr(int keyIndex,
return -EPERM;
}
int LUKS_del_key(unsigned int keyIndex,
/*
* 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;
char *buffer;
unsigned int i;
unsigned int bufLen = (to - from) * SECTOR_SIZE;
int r = 0;
devfd = open(device, O_RDWR | O_DIRECT | O_SYNC);
if(devfd == -1)
return -EINVAL;
buffer = (char *) malloc(bufLen);
if(!buffer) {
close(devfd);
return -ENOMEM;
}
for(i = 0; i < 39; ++i) {
if (i >= 0 && 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);
if(write_lseek_blockwise(devfd, buffer, bufLen, from * SECTOR_SIZE) < 0) {
r = -EIO;
break;
}
}
free(buffer);
close(devfd);
return r;
}
int LUKS_del_key(const char *device,
unsigned int keyIndex,
struct luks_phdr *hdr,
struct crypt_device *ctx)
{
struct device *device = crypt_metadata_device(ctx);
unsigned int startOffset, endOffset;
unsigned int startOffset, endOffset, stripesLen;
int r;
r = LUKS_read_phdr(hdr, 1, 0, ctx);
r = LUKS_read_phdr(device, hdr, 1, ctx);
if (r)
return r;
@@ -971,19 +816,12 @@ int LUKS_del_key(unsigned int keyIndex,
/* secure deletion of key material */
startOffset = hdr->keyblock[keyIndex].keyMaterialOffset;
endOffset = startOffset + AF_split_sectors(hdr->keyBytes, hdr->keyblock[keyIndex].stripes);
stripesLen = hdr->keyBytes * hdr->keyblock[keyIndex].stripes;
endOffset = startOffset + div_round_up(stripesLen, SECTOR_SIZE);
r = crypt_wipe(device, startOffset * SECTOR_SIZE,
(endOffset - startOffset) * SECTOR_SIZE,
CRYPT_WIPE_DISK, 0);
r = wipe(device, startOffset, endOffset);
if (r) {
if (r == -EACCES) {
log_err(ctx, _("Cannot write to device %s, permission denied.\n"),
device_path(device));
r = -EINVAL;
} else
log_err(ctx, _("Cannot wipe device %s.\n"),
device_path(device));
log_err(ctx, _("Cannot wipe device %s.\n"), device);
return r;
}
@@ -991,7 +829,7 @@ int LUKS_del_key(unsigned int keyIndex,
memset(&hdr->keyblock[keyIndex].passwordSalt, 0, LUKS_SALTSIZE);
hdr->keyblock[keyIndex].passwordIterations = 0;
r = LUKS_write_phdr(hdr, ctx);
r = LUKS_write_phdr(device, hdr, ctx);
return r;
}
@@ -1052,46 +890,3 @@ 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_data_device(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_block_adjust(cd, dmd.data_device, device_check,
dmd.u.crypt.offset, &dmd.size, &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(cd, name, CRYPT_LUKS1, &dmd, 0);
free(dm_cipher);
return r;
}

View File

@@ -1,23 +1,3 @@
/*
* 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
@@ -51,6 +31,8 @@
#define LUKS_MAGIC {'L','U','K','S', 0xba, 0xbe};
#define LUKS_MAGIC_L 6
#define LUKS_PHDR_SIZE (sizeof(struct luks_phdr)/SECTOR_SIZE+1)
/* Actually we need only 37, but we don't want struct autoaligning to kick in */
#define UUID_STRING_L 40
@@ -61,7 +43,6 @@
converted */
struct volume_key;
struct device_backend;
struct luks_phdr {
char magic[LUKS_MAGIC_L];
@@ -107,41 +88,46 @@ int LUKS_generate_phdr(
unsigned int alignOffset,
uint32_t iteration_time_ms,
uint64_t *PBKDF2_per_sec,
int detached_metadata_device,
struct crypt_device *ctx);
int LUKS_read_phdr(
const char *device,
struct luks_phdr *hdr,
int require_luks_device,
int repair,
struct crypt_device *ctx);
int LUKS_read_phdr_backup(
const char *backup_file,
const char *device,
struct luks_phdr *hdr,
int require_luks_device,
struct crypt_device *ctx);
int LUKS_hdr_uuid_set(
const char *device,
struct luks_phdr *hdr,
const char *uuid,
struct crypt_device *ctx);
int LUKS_hdr_backup(
const char *backup_file,
const char *device,
struct luks_phdr *hdr,
struct crypt_device *ctx);
int LUKS_hdr_restore(
const char *backup_file,
const char *device,
struct luks_phdr *hdr,
struct crypt_device *ctx);
int LUKS_write_phdr(
const char *device,
struct luks_phdr *hdr,
struct crypt_device *ctx);
int LUKS_set_key(
const char *device,
unsigned int keyIndex,
const char *password,
size_t passwordLen,
@@ -152,6 +138,7 @@ int LUKS_set_key(
struct crypt_device *ctx);
int LUKS_open_key_with_hdr(
const char *device,
int keyIndex,
const char *password,
size_t passwordLen,
@@ -160,6 +147,7 @@ int LUKS_open_key_with_hdr(
struct crypt_device *ctx);
int LUKS_del_key(
const char *device,
unsigned int keyIndex,
struct luks_phdr *hdr,
struct crypt_device *ctx);
@@ -168,28 +156,21 @@ crypt_keyslot_info LUKS_keyslot_info(struct luks_phdr *hdr, int keyslot);
int LUKS_keyslot_find_empty(struct luks_phdr *hdr);
int LUKS_keyslot_active_count(struct luks_phdr *hdr);
int LUKS_keyslot_set(struct luks_phdr *hdr, int keyslot, int enable);
int LUKS_keyslot_area(struct luks_phdr *hdr,
int keyslot,
uint64_t *offset,
uint64_t *length);
int LUKS_encrypt_to_storage(
char *src, size_t srcLength,
struct luks_phdr *hdr,
struct volume_key *vk,
char *key, size_t keyLength,
const char *device,
unsigned int sector,
struct crypt_device *ctx);
int LUKS_decrypt_from_storage(
char *dst, size_t dstLength,
struct luks_phdr *hdr,
struct volume_key *vk,
char *key, size_t keyLength,
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

View File

@@ -1,11 +1,10 @@
/*
* 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-2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-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
@@ -19,7 +18,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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
@@ -30,7 +29,6 @@
#include <string.h>
#include <sys/time.h>
#include "crypto_backend.h"
#include "pbkdf.h"
static volatile uint64_t __PBKDF2_global_j = 0;
static volatile uint64_t __PBKDF2_performance = 0;
@@ -168,6 +166,9 @@ 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;
@@ -222,7 +223,7 @@ int PBKDF2_HMAC_ready(const char *hash)
return 1;
}
static void sigvtalarm(int foo __attribute__((unused)))
static void sigvtalarm(int foo)
{
__PBKDF2_performance = __PBKDF2_global_j;
}

View File

@@ -1,28 +1,3 @@
/*
* 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

View File

@@ -27,8 +27,6 @@
# define textdomain(Domain) /* empty */
# define _(Text) (Text)
# define N_(Text) (Text)
# define ngettext(Singular, Plural, Count) \
( (Count) == 1 ? (Singular) : (Plural) )
#endif
#endif /* CRYPTSETUP_NLS_H */
#endif /* CRYPTSETUP_H */

View File

@@ -1,7 +1,7 @@
/*
* cryptsetup kernel RNG access functions
*
* Copyright (C) 2010-2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-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
@@ -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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdlib.h>
@@ -41,8 +41,7 @@ static int random_fd = -1;
#define RANDOM_DEVICE_TIMEOUT 5
/* URANDOM_DEVICE access */
static int _get_urandom(struct crypt_device *ctx __attribute__((unused)),
char *buf, size_t len)
static int _get_urandom(struct crypt_device *ctx, char *buf, size_t len)
{
int r;
size_t old_len = len;
@@ -176,17 +175,7 @@ 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) {
@@ -212,7 +201,7 @@ int crypt_random_get(struct crypt_device *ctx, char *buf, size_t len, int qualit
return status;
}
void crypt_random_exit(void)
void crypt_random_exit()
{
random_initialised = 0;
@@ -227,7 +216,7 @@ void crypt_random_exit(void)
}
}
int crypt_random_default_key_rng(void)
int crypt_random_default_key_rng()
{
if (!strcmp(DEFAULT_RNG, RANDOM_DEVICE))
return CRYPT_RNG_RANDOM;

File diff suppressed because it is too large Load Diff

View File

@@ -3,7 +3,7 @@
*
* 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.
* 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
@@ -16,21 +16,64 @@
*
* 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.
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdarg.h>
#include <errno.h>
#include <linux/fs.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/resource.h>
#include "libcryptsetup.h"
#include "internal.h"
unsigned crypt_getpagesize(void)
static char *error=NULL;
void set_error_va(const char *fmt, va_list va)
{
return (unsigned)sysconf(_SC_PAGESIZE);
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';
}
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;
}
static int get_alignment(int fd)
@@ -63,16 +106,35 @@ static void *aligned_malloc(void **base, int size, int alignment)
return ptr;
#endif
}
static int sector_size(int fd)
{
int bsize;
if (ioctl(fd,BLKSSZGET, &bsize) < 0)
return -EINVAL;
else
return bsize;
}
ssize_t write_blockwise(int fd, int bsize, void *orig_buf, size_t count)
int sector_size_for_device(const char *device)
{
int fd = open(device, O_RDONLY);
int r;
if(fd < 0)
return -EINVAL;
r = sector_size(fd);
close(fd);
return r;
}
ssize_t write_blockwise(int fd, const void *orig_buf, size_t count)
{
void *hangover_buf, *hangover_buf_base = NULL;
void *buf, *buf_base = NULL;
int r, hangover, solid, alignment;
int r, hangover, solid, bsize, alignment;
ssize_t ret = -1;
if (fd == -1 || !orig_buf || bsize <= 0)
return -1;
if ((bsize = sector_size(fd)) < 0)
return bsize;
hangover = count % bsize;
solid = count - hangover;
@@ -84,7 +146,7 @@ ssize_t write_blockwise(int fd, int bsize, void *orig_buf, size_t count)
goto out;
memcpy(buf, orig_buf, count);
} else
buf = orig_buf;
buf = (void *)orig_buf;
r = write(fd, buf, solid);
if (r < 0 || r != solid)
@@ -96,34 +158,32 @@ ssize_t write_blockwise(int fd, int bsize, void *orig_buf, size_t count)
goto out;
r = read(fd, hangover_buf, bsize);
if (r < 0 || r != bsize)
goto out;
if(r < 0 || r != bsize) goto out;
r = lseek(fd, -bsize, SEEK_CUR);
if (r < 0)
goto out;
memcpy(hangover_buf, (char*)buf + solid, hangover);
memcpy(hangover_buf, buf + solid, hangover);
r = write(fd, hangover_buf, bsize);
if (r < 0 || r != bsize)
goto out;
if(r < 0 || r != bsize) goto out;
free(hangover_buf_base);
}
ret = count;
out:
free(hangover_buf_base);
out:
if (buf != orig_buf)
free(buf_base);
return ret;
}
ssize_t read_blockwise(int fd, int bsize, void *orig_buf, size_t count) {
void *hangover_buf, *hangover_buf_base = NULL;
ssize_t read_blockwise(int fd, void *orig_buf, size_t count) {
void *hangover_buf, *hangover_buf_base;
void *buf, *buf_base = NULL;
int r, hangover, solid, alignment;
int r, hangover, solid, bsize, alignment;
ssize_t ret = -1;
if (fd == -1 || !orig_buf || bsize <= 0)
return -1;
if ((bsize = sector_size(fd)) < 0)
return bsize;
hangover = count % bsize;
solid = count - hangover;
@@ -148,11 +208,11 @@ ssize_t read_blockwise(int fd, int bsize, void *orig_buf, size_t count) {
if (r < 0 || r != bsize)
goto out;
memcpy((char *)buf + solid, hangover_buf, hangover);
memcpy(buf + solid, hangover_buf, hangover);
free(hangover_buf_base);
}
ret = count;
out:
free(hangover_buf_base);
out:
if (buf != orig_buf) {
memcpy(orig_buf, buf, count);
free(buf_base);
@@ -160,61 +220,227 @@ out:
return ret;
}
/*
/*
* Combines llseek with blockwise write. write_blockwise can already deal with short writes
* but we also need a function to deal with short writes at the start. But this information
* is implicitly included in the read/write offset, which can not be set to non-aligned
* is implicitly included in the read/write offset, which can not be set to non-aligned
* boundaries. Hence, we combine llseek with write.
*/
ssize_t write_lseek_blockwise(int fd, int bsize, char *buf, size_t count, off_t offset) {
char *frontPadBuf;
void *frontPadBuf_base = NULL;
int r, frontHang;
size_t innerCount = 0;
ssize_t ret = -1;
if (fd == -1 || !buf || bsize <= 0)
return -1;
ssize_t write_lseek_blockwise(int fd, const char *buf, size_t count, off_t offset) {
int bsize = sector_size(fd);
const char *orig_buf = buf;
char frontPadBuf[bsize];
int frontHang = offset % bsize;
int r;
int innerCount = count < bsize ? count : bsize;
frontHang = offset % bsize;
if (bsize < 0)
return bsize;
if (lseek(fd, offset - frontHang, SEEK_SET) < 0)
goto out;
lseek(fd, offset - frontHang, SEEK_SET);
if(offset % bsize) {
r = read(fd,frontPadBuf,bsize);
if(r < 0) return -1;
if (frontHang) {
frontPadBuf = aligned_malloc(&frontPadBuf_base,
bsize, get_alignment(fd));
if (!frontPadBuf)
goto out;
memcpy(frontPadBuf+frontHang, buf, innerCount);
r = read(fd, frontPadBuf, bsize);
if (r < 0 || r != bsize)
goto out;
innerCount = bsize - frontHang;
if (innerCount > count)
innerCount = count;
memcpy(frontPadBuf + frontHang, buf, innerCount);
if (lseek(fd, offset - frontHang, SEEK_SET) < 0)
goto out;
r = write(fd, frontPadBuf, bsize);
if (r < 0 || r != bsize)
goto out;
lseek(fd, offset - frontHang, SEEK_SET);
r = write(fd,frontPadBuf,bsize);
if(r < 0) return -1;
buf += innerCount;
count -= innerCount;
}
if(count <= 0) return buf - orig_buf;
ret = count ? write_blockwise(fd, bsize, buf, count) : 0;
if (ret >= 0)
ret += innerCount;
return write_blockwise(fd, buf, count) + innerCount;
}
int device_ready(struct crypt_device *cd, const char *device, int mode)
{
int devfd, r = 0;
ssize_t s;
struct stat st;
char buf[512];
if(stat(device, &st) < 0) {
log_err(cd, _("Device %s doesn't exist or access denied.\n"), device);
return -EINVAL;
}
if (!S_ISBLK(st.st_mode))
return -ENOTBLK;
log_dbg("Trying to open and read device %s.", device);
devfd = open(device, mode | O_DIRECT | O_SYNC);
if(devfd < 0) {
log_err(cd, _("Cannot open device %s for %s%s access.\n"), device,
(mode & O_EXCL) ? _("exclusive ") : "",
(mode & O_RDWR) ? _("writable") : _("read-only"));
return -EINVAL;
}
/* Try to read first sector */
s = read_blockwise(devfd, buf, sizeof(buf));
if (s < 0 || s != sizeof(buf)) {
log_verbose(cd, _("Cannot read device %s.\n"), device);
r = -EIO;
}
memset(buf, 0, sizeof(buf));
close(devfd);
return r;
}
int get_device_infos(const char *device,
int open_exclusive,
int *readonly,
uint64_t *size)
{
struct stat st;
unsigned long size_small;
int fd, r = -1;
int flags = 0;
*readonly = 0;
*size = 0;
if (stat(device, &st) < 0)
return -EINVAL;
/* never wipe header on mounted device */
if (open_exclusive && S_ISBLK(st.st_mode))
flags |= O_EXCL;
/* Try to open read-write to check whether it is a read-only device */
fd = open(device, O_RDWR | flags);
if (fd == -1 && errno == EROFS) {
*readonly = 1;
fd = open(device, O_RDONLY | flags);
}
if (fd == -1 && open_exclusive && errno == EBUSY)
return -EBUSY;
if (fd == -1)
return -EINVAL;
#ifdef BLKROGET
/* If the device can be opened read-write, i.e. readonly is still 0, then
* check whether BKROGET says that it is read-only. E.g. read-only loop
* devices may be openend read-write but are read-only according to BLKROGET
*/
if (*readonly == 0 && (r = ioctl(fd, BLKROGET, readonly)) < 0)
goto out;
#else
#error BLKROGET not available
#endif
#ifdef BLKGETSIZE64
if (ioctl(fd, BLKGETSIZE64, size) >= 0) {
*size >>= SECTOR_SHIFT;
r = 0;
goto out;
}
#endif
#ifdef BLKGETSIZE
if (ioctl(fd, BLKGETSIZE, &size_small) >= 0) {
*size = (uint64_t)size_small;
r = 0;
goto out;
}
#else
# error Need at least the BLKGETSIZE ioctl!
#endif
r = -EINVAL;
out:
free(frontPadBuf_base);
close(fd);
return r;
}
return ret;
int device_check_and_adjust(struct crypt_device *cd,
const char *device,
int open_exclusive,
uint64_t *size,
uint64_t *offset,
int *read_only)
{
int r, real_readonly;
uint64_t real_size;
if (!device)
return -ENOTBLK;
r = get_device_infos(device, open_exclusive, &real_readonly, &real_size);
if (r < 0) {
if (r == -EBUSY)
log_err(cd, _("Cannot use device %s which is in use "
"(already mapped or mounted).\n"),
device);
else
log_err(cd, _("Cannot get info about device %s.\n"),
device);
return r;
}
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;
}
if (real_readonly)
*read_only = 1;
log_dbg("Calculated device size is %" PRIu64 " sectors (%s), offset %" PRIu64 ".",
*size, *read_only ? "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 */
@@ -229,7 +455,7 @@ int crypt_memlock_inc(struct crypt_device *ctx)
if (!_memlock_count++) {
log_dbg("Locking memory.");
if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) {
log_dbg("Cannot lock memory with mlockall.");
log_err(ctx, _("WARNING!!! Possibly insecure memory. Are you root?\n"));
_memlock_count--;
return 0;
}
@@ -255,3 +481,60 @@ int crypt_memlock_dec(struct crypt_device *ctx)
}
return _memlock_count ? 1 : 0;
}
/* DEVICE TOPOLOGY */
/* block device topology ioctls, introduced in 2.6.32 */
#ifndef BLKIOMIN
#define BLKIOMIN _IO(0x12,120)
#define BLKIOOPT _IO(0x12,121)
#define BLKALIGNOFF _IO(0x12,122)
#endif
void get_topology_alignment(const char *device,
unsigned long *required_alignment, /* bytes */
unsigned long *alignment_offset, /* bytes */
unsigned long default_alignment)
{
int dev_alignment_offset = 0;
unsigned int min_io_size = 0, opt_io_size = 0;
unsigned long temp_alignment = 0;
int fd;
*required_alignment = default_alignment;
*alignment_offset = 0;
fd = open(device, O_RDONLY);
if (fd == -1)
return;
/* minimum io size */
if (ioctl(fd, BLKIOMIN, &min_io_size) == -1) {
log_dbg("Topology info for %s not supported, using default offset %lu bytes.",
device, default_alignment);
goto out;
}
/* optimal io size */
if (ioctl(fd, BLKIOOPT, &opt_io_size) == -1)
opt_io_size = min_io_size;
/* alignment offset, bogus -1 means misaligned/unknown */
if (ioctl(fd, BLKALIGNOFF, &dev_alignment_offset) == -1 || dev_alignment_offset < 0)
dev_alignment_offset = 0;
*alignment_offset = (unsigned long)dev_alignment_offset;
temp_alignment = (unsigned long)min_io_size;
if (temp_alignment < (unsigned long)opt_io_size)
temp_alignment = (unsigned long)opt_io_size;
/* If calculated alignment is multiple of default, keep default */
if (temp_alignment && (default_alignment % temp_alignment))
*required_alignment = temp_alignment;
log_dbg("Topology: IO (%u/%u), offset = %lu; Required alignment is %lu bytes.",
min_io_size, opt_io_size, *alignment_offset, *required_alignment);
out:
(void)close(fd);
}

View File

@@ -1,8 +1,8 @@
/*
* utils_crypt - cipher utilities for cryptsetup
* util_crypt - cipher utilities for cryptsetup
*
* Copyright (C) 2004-2007, Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
* 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
@@ -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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdlib.h>
@@ -23,8 +23,6 @@
#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>
@@ -60,15 +58,6 @@ 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)
@@ -92,9 +81,7 @@ void *crypt_safe_alloc(size_t size)
return NULL;
alloc->size = size;
memset(&alloc->data, 0, size);
/* coverity[leaked_storage] */
return &alloc->data;
}
@@ -105,8 +92,7 @@ void crypt_safe_free(void *data)
if (!data)
return;
alloc = (struct safe_allocation *)
((char *)data - offsetof(struct safe_allocation, data));
alloc = data - offsetof(struct safe_allocation, data);
memset(data, 0, alloc->size);
@@ -123,8 +109,7 @@ void *crypt_safe_realloc(void *data, size_t size)
if (new_data && data) {
alloc = (struct safe_allocation *)
((char *)data - offsetof(struct safe_allocation, data));
alloc = data - offsetof(struct safe_allocation, data);
if (size > alloc->size)
size = alloc->size;
@@ -248,7 +233,6 @@ 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;
}
}
@@ -263,49 +247,6 @@ out_err:
return r;
}
/*
* A simple call to lseek(3) might not be possible for some inputs (e.g.
* reading from a pipe), so this function instead reads of up to BUFSIZ bytes
* at a time until the specified number of bytes. It returns -1 on read error
* or when it reaches EOF before the requested number of bytes have been
* discarded.
*/
static int keyfile_seek(int fd, size_t bytes)
{
char tmp[BUFSIZ];
size_t next_read;
ssize_t bytes_r;
off_t r;
r = lseek(fd, bytes, SEEK_CUR);
if (r > 0)
return 0;
if (r < 0 && errno != ESPIPE)
return -1;
while (bytes > 0) {
/* figure out how much to read */
next_read = bytes > sizeof(tmp) ? sizeof(tmp) : bytes;
bytes_r = read(fd, tmp, next_read);
if (bytes_r < 0) {
if (errno == EINTR)
continue;
/* read error */
return -1;
}
if (bytes_r == 0)
/* EOF */
break;
bytes -= bytes_r;
}
return bytes == 0 ? 0 : -1;
}
/*
* Note: --key-file=- is interpreted as a read from a binary file (stdin)
* key_size_max == 0 means detect maximum according to input type (tty/file)
@@ -313,14 +254,14 @@ static int keyfile_seek(int fd, size_t bytes)
*/
int crypt_get_key(const char *prompt,
char **key, size_t *key_size,
size_t keyfile_offset, size_t keyfile_size_max,
const char *key_file, int timeout, int verify,
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, file_read_size;
size_t buflen, i;
struct stat st;
*key = NULL;
@@ -329,12 +270,12 @@ 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 (keyfile_offset) {
log_err(cd, _("Cannot use offset with terminal input.\n"));
return -EINVAL;
}
if(read_stdin && isatty(STDIN_FILENO))
return crypt_get_key_tty(prompt, key, key_size, timeout, verify, cd);
if (keyfile_size_max < 0) {
log_err(cd, _("Negative keyfile size not permitted.\n"));
return -EINVAL;
}
if (read_stdin)
@@ -364,19 +305,11 @@ 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 (file_read_size >= keyfile_size_max)
if (st.st_size >= keyfile_size_max)
buflen = keyfile_size_max;
else if (file_read_size)
buflen = file_read_size;
else
buflen = st.st_size;
}
}
@@ -386,12 +319,6 @@ int crypt_get_key(const char *prompt,
goto out_err;
}
/* Discard keyfile_offset bytes on input */
if (keyfile_offset && keyfile_seek(fd, keyfile_offset) < 0) {
log_err(cd, _("Cannot seek to requested keyfile offset.\n"));
goto out_err;
}
for(i = 0; i < keyfile_size_max; i++) {
if(i == buflen) {
buflen += 4096;
@@ -423,7 +350,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 exceeded.\n"));
log_err(cd, _("Maximum keyfile size exceeeded.\n"));
goto out_err;
}
@@ -432,6 +359,12 @@ 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;
@@ -443,94 +376,3 @@ 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;
/* Fall through */
case 'g':
case 'G': mult *= mult_base;
/* Fall through */
case 'm':
case 'M': mult *= mult_base;
/* Fall through */
case 'k':
case 'K': mult *= mult_base;
break;
default:
return -EINVAL;
}
tmp = *size * mult;
if ((tmp / *size) != mult) {
log_dbg("Device size overflow.");
return -EINVAL;
}
*size = tmp;
return 0;
}

View File

@@ -1,23 +1,3 @@
/*
* 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
@@ -34,7 +14,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_offset, size_t keyfile_size_max,
size_t keyfile_size_max,
const char *key_file,
int timeout, int verify,
struct crypt_device *cd);
@@ -43,7 +23,4 @@ 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 */

146
lib/utils_debug.c Normal file
View File

@@ -0,0 +1,146 @@
/*
* 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;
size_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);
}

View File

@@ -1,429 +0,0 @@
/*
* device backend utilities
*
* 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.
*/
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <linux/fs.h>
#include <unistd.h>
#include "internal.h"
struct device {
char *path;
char *file_path;
int loop_fd;
int init_done:1;
};
static int device_ready(const char *device)
{
int devfd, r = 0;
struct stat st;
if(stat(device, &st) < 0) {
log_err(NULL, _("Device %s doesn't exist or access denied.\n"), device);
return -EINVAL;
}
if (!S_ISBLK(st.st_mode))
return S_ISREG(st.st_mode) ? -ENOTBLK : -EINVAL;
log_dbg("Trying to open and read device %s.", device);
devfd = open(device, O_RDONLY | O_DIRECT | O_SYNC);
if(devfd < 0) {
log_err(NULL, _("Cannot open device %s.\n"), device);
return -EINVAL;
}
close(devfd);
return r;
}
int device_alloc(struct device **device, const char *path)
{
struct device *dev;
int r;
if (!path) {
*device = NULL;
return 0;
}
dev = malloc(sizeof(struct device));
if (!dev)
return -ENOMEM;
memset(dev, 0, sizeof(struct device));
dev->loop_fd = -1;
r = device_ready(path);
if (!r) {
dev->init_done = 1;
} else if (r == -ENOTBLK) {
/* alloc loop later */
} else if (r < 0) {
free(dev);
return -ENOTBLK;
}
dev->path = strdup(path);
if (!dev->path) {
free(dev);
return -ENOMEM;
}
*device = dev;
return 0;
}
void device_free(struct device *device)
{
if (!device)
return;
if (device->loop_fd != -1) {
log_dbg("Closed loop %s (%s).", device->path, device->file_path);
close(device->loop_fd);
}
free(device->file_path);
free(device->path);
free(device);
}
/* Get block device path */
const char *device_block_path(const struct device *device)
{
if (!device || !device->init_done)
return NULL;
return device->path;
}
/* Get path to device / file */
const char *device_path(const struct device *device)
{
if (!device)
return NULL;
if (device->file_path)
return device->file_path;
return device->path;
}
/* block device topology ioctls, introduced in 2.6.32 */
#ifndef BLKIOMIN
#define BLKIOMIN _IO(0x12,120)
#define BLKIOOPT _IO(0x12,121)
#define BLKALIGNOFF _IO(0x12,122)
#endif
void device_topology_alignment(struct device *device,
unsigned long *required_alignment, /* bytes */
unsigned long *alignment_offset, /* bytes */
unsigned long default_alignment)
{
int dev_alignment_offset = 0;
unsigned int min_io_size = 0, opt_io_size = 0;
unsigned long temp_alignment = 0;
int fd;
*required_alignment = default_alignment;
*alignment_offset = 0;
if (!device || !device->path) //FIXME
return;
fd = open(device->path, O_RDONLY);
if (fd == -1)
return;
/* minimum io size */
if (ioctl(fd, BLKIOMIN, &min_io_size) == -1) {
log_dbg("Topology info for %s not supported, using default offset %lu bytes.",
device->path, default_alignment);
goto out;
}
/* optimal io size */
if (ioctl(fd, BLKIOOPT, &opt_io_size) == -1)
opt_io_size = min_io_size;
/* alignment offset, bogus -1 means misaligned/unknown */
if (ioctl(fd, BLKALIGNOFF, &dev_alignment_offset) == -1 || dev_alignment_offset < 0)
dev_alignment_offset = 0;
*alignment_offset = (unsigned long)dev_alignment_offset;
temp_alignment = (unsigned long)min_io_size;
if (temp_alignment < (unsigned long)opt_io_size)
temp_alignment = (unsigned long)opt_io_size;
/* If calculated alignment is multiple of default, keep default */
if (temp_alignment && (default_alignment % temp_alignment))
*required_alignment = temp_alignment;
log_dbg("Topology: IO (%u/%u), offset = %lu; Required alignment is %lu bytes.",
min_io_size, opt_io_size, *alignment_offset, *required_alignment);
out:
(void)close(fd);
}
int device_block_size(struct device *device)
{
struct stat st;
int fd, bsize = 0, r = -EINVAL;
if (!device)
return 0;
fd = open(device->path, O_RDONLY);
if(fd < 0)
return -EINVAL;
if (fstat(fd, &st) < 0)
goto out;
if (S_ISREG(st.st_mode)) {
r = (int)crypt_getpagesize();
goto out;
}
if (ioctl(fd, BLKSSZGET, &bsize) >= 0)
r = bsize;
out:
close(fd);
return r;
}
int device_read_ahead(struct device *device, uint32_t *read_ahead)
{
int fd, r = 0;
long read_ahead_long;
if (!device)
return 0;
if ((fd = open(device->path, O_RDONLY)) < 0)
return 0;
r = ioctl(fd, BLKRAGET, &read_ahead_long) ? 0 : 1;
close(fd);
if (r)
*read_ahead = (uint32_t) read_ahead_long;
return r;
}
/* Get data size in bytes */
int device_size(struct device *device, uint64_t *size)
{
struct stat st;
int devfd, r = -EINVAL;
devfd = open(device->path, O_RDONLY);
if(devfd == -1)
return -EINVAL;
if (fstat(devfd, &st) < 0)
goto out;
if (S_ISREG(st.st_mode)) {
*size = (uint64_t)st.st_size;
r = 0;
} else if (ioctl(devfd, BLKGETSIZE64, size) >= 0)
r = 0;
out:
close(devfd);
return r;
}
static int device_info(struct device *device,
enum devcheck device_check,
int *readonly, uint64_t *size)
{
struct stat st;
int fd, r = -EINVAL, flags = 0;
*readonly = 0;
*size = 0;
if (stat(device->path, &st) < 0)
return -EINVAL;
/* never wipe header on mounted device */
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 */
fd = open(device->path, O_RDWR | flags);
if (fd == -1 && errno == EROFS) {
*readonly = 1;
fd = open(device->path, O_RDONLY | flags);
}
if (fd == -1 && device_check == DEV_EXCL && errno == EBUSY)
return -EBUSY;
if (fd == -1)
return -EINVAL;
if (S_ISREG(st.st_mode)) {
//FIXME: add readonly check
*size = (uint64_t)st.st_size;
*size >>= SECTOR_SHIFT;
} else {
/* If the device can be opened read-write, i.e. readonly is still 0, then
* check whether BKROGET says that it is read-only. E.g. read-only loop
* devices may be openend read-write but are read-only according to BLKROGET
*/
if (*readonly == 0 && (r = ioctl(fd, BLKROGET, readonly)) < 0)
goto out;
if (ioctl(fd, BLKGETSIZE64, size) >= 0) {
*size >>= SECTOR_SHIFT;
r = 0;
goto out;
}
}
r = -EINVAL;
out:
close(fd);
return r;
}
static int device_internal_prepare(struct crypt_device *cd, struct device *device)
{
char *loop_device;
int r, loop_fd, readonly = 0;
if (device->init_done)
return 0;
log_dbg("Allocating a free loop device.");
loop_device = crypt_loop_get_device();
if (!loop_device) {
if (getuid() || geteuid())
log_err(cd, _("Cannot use a loopback device, "
"running as non-root user.\n"));
else
log_err(cd, _("Cannot find a free loopback device.\n"));
return -ENOTSUP;
}
/* Keep the loop open, dettached on last close. */
loop_fd = crypt_loop_attach(loop_device, device->path, 0, 1, &readonly);
if (loop_fd == -1) {
log_err(cd, _("Attaching loopback device failed "
"(loop device with autoclear flag is required).\n"));
free(loop_device);
return -EINVAL;
}
r = device_ready(loop_device);
if (r < 0) {
free(loop_device);
return r;
}
device->loop_fd = loop_fd;
device->file_path = device->path;
device->path = loop_device;
device->init_done = 1;
return 0;
}
int device_block_adjust(struct crypt_device *cd,
struct device *device,
enum devcheck device_check,
uint64_t device_offset,
uint64_t *size,
uint32_t *flags)
{
int r, real_readonly;
uint64_t real_size;
if (!device)
return -ENOTBLK;
r = device_internal_prepare(cd, device);
if (r)
return r;
r = device_info(device, device_check, &real_readonly, &real_size);
if (r < 0) {
if (r == -EBUSY)
log_err(cd, _("Cannot use device %s which is in use "
"(already mapped or mounted).\n"),
device->path);
else
log_err(cd, _("Cannot get info about device %s.\n"),
device->path);
return r;
}
if (device_offset >= real_size) {
log_err(cd, _("Requested offset is beyond real size of device %s.\n"),
device->path);
return -EINVAL;
}
if (size && !*size) {
*size = real_size;
if (!*size) {
log_err(cd, _("Device %s has zero size.\n"), device->path);
return -ENOTBLK;
}
*size -= device_offset;
}
/* in case of size is set by parameter */
if (size && ((real_size - device_offset) < *size)) {
log_dbg("Device %s: offset = %" PRIu64 " requested size = %" PRIu64
", backing device size = %" PRIu64,
device->path, device_offset, *size, real_size);
log_err(cd, _("Device %s is too small.\n"), device->path);
return -EINVAL;
}
if (flags && real_readonly)
*flags |= CRYPT_ACTIVATE_READONLY;
if (size)
log_dbg("Calculated device size is %" PRIu64" sectors (%s), offset %" PRIu64 ".",
*size, real_readonly ? "RO" : "RW", device_offset);
return 0;
}
size_t size_round_up(size_t size, unsigned int block)
{
size_t s = (size + (block - 1)) / block;
return s * block;
}

View File

@@ -1,196 +0,0 @@
/*
* devname - search for device name
*
* 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.
*/
#include <string.h>
#include <stdio.h>
#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"
/* These are DM helpers used only by this file */
int dm_is_dm_device(int major, int minor);
int dm_is_dm_kernel_name(const char *name);
char *dm_device_path(const char *prefix, int major, int minor);
char *crypt_lookup_dev(const char *dev_id);
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)
{
struct dirent *entry;
struct stat st;
char *ptr;
char *result = NULL;
DIR *dir;
int space;
/* Ignore strange nested directories */
if (dir_level > max_level)
return NULL;
path[PATH_MAX - 1] = '\0';
ptr = path + strlen(path);
*ptr++ = '/';
*ptr = '\0';
space = PATH_MAX - (ptr - path);
dir = opendir(path);
if (!dir)
return NULL;
while((entry = readdir(dir))) {
if (entry->d_name[0] == '.' ||
!strncmp(entry->d_name, "..", 2))
continue;
if (dir_level == 0 &&
(!strcmp(entry->d_name, "shm") ||
!strcmp(entry->d_name, "fd") ||
!strcmp(entry->d_name, "char") ||
!strcmp(entry->d_name, "pts")))
continue;
strncpy(ptr, entry->d_name, space);
if (stat(path, &st) < 0)
continue;
if (S_ISDIR(st.st_mode)) {
result = __lookup_dev(path, dev, dir_level + 1, max_level);
if (result)
break;
} else if (S_ISBLK(st.st_mode)) {
/* workaround: ignore dm-X devices, these are internal kernel names */
if (dir_level == 0 && dm_is_dm_kernel_name(entry->d_name))
continue;
if (st.st_rdev == dev) {
result = strdup(path);
break;
}
}
}
closedir(dir);
return result;
}
/*
* Non-udev systemd need to scan for device here.
*/
static char *lookup_dev_old(int major, int minor)
{
dev_t dev;
char *result = NULL, buf[PATH_MAX + 1];
dev = makedev(major, minor);
strncpy(buf, "/dev", PATH_MAX);
buf[PATH_MAX] = '\0';
/* First try low level device */
if ((result = __lookup_dev(buf, dev, 0, 0)))
return result;
/* If it is dm, try DM dir */
if (dm_is_dm_device(major, minor)) {
strncpy(buf, dm_get_dir(), PATH_MAX);
if ((result = __lookup_dev(buf, dev, 0, 0)))
return result;
}
strncpy(buf, "/dev", PATH_MAX);
return __lookup_dev(buf, dev, 0, 4);
}
/*
* Returns string pointing to device in /dev according to "major:minor" dev_id
*/
char *crypt_lookup_dev(const char *dev_id)
{
int major, minor;
char link[PATH_MAX], path[PATH_MAX], *devname, *devpath = NULL;
struct stat st;
ssize_t len;
if (sscanf(dev_id, "%d:%d", &major, &minor) != 2)
return NULL;
if (snprintf(path, sizeof(path), "/sys/dev/block/%s", dev_id) < 0)
return NULL;
len = readlink(path, link, sizeof(link) - 1);
if (len < 0) {
/* Without /sys use old scan */
if (stat("/sys/dev/block", &st) < 0)
return lookup_dev_old(major, minor);
return NULL;
}
link[len] = '\0';
devname = strrchr(link, '/');
if (!devname)
return NULL;
devname++;
if (dm_is_dm_kernel_name(devname))
devpath = dm_device_path("/dev/mapper/", major, minor);
else if (snprintf(path, sizeof(path), "/dev/%s", devname) > 0)
devpath = strdup(path);
/*
* Check that path is correct.
*/
if (devpath && ((stat(devpath, &st) < 0) ||
!S_ISBLK(st.st_mode) ||
(st.st_rdev != makedev(major, minor)))) {
free(devpath);
/* Should never happen unless user mangles with dev nodes. */
return lookup_dev_old(major, minor);
}
return devpath;
}
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;
}

View File

@@ -1,101 +0,0 @@
/*
* 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
/* device-mapper library helpers */
#include <inttypes.h>
struct crypt_device;
struct volume_key;
struct crypt_params_verity;
struct device;
/* 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;
struct device *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 {
struct device *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;
};
void dm_backend_init(void);
void dm_backend_exit(void);
int dm_remove_device(struct crypt_device *cd, const char *name,
int force, uint64_t size);
int dm_status_device(struct crypt_device *cd, const char *name);
int dm_status_suspended(struct crypt_device *cd, const char *name);
int dm_status_verity_ok(struct crypt_device *cd, const char *name);
int dm_query_device(struct crypt_device *cd, const char *name,
uint32_t get_flags, struct crypt_dm_active_device *dmd);
int dm_create_device(struct crypt_device *cd, const char *name,
const char *type, struct crypt_dm_active_device *dmd,
int reload);
int dm_suspend_and_wipe_key(struct crypt_device *cd, const char *name);
int dm_resume_and_reinstate_key(struct crypt_device *cd, const char *name,
size_t key_size, const char *key);
const char *dm_get_dir(void);
#endif /* _UTILS_DM_H */

View File

@@ -1,62 +0,0 @@
/*
* 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 */

View File

@@ -1,29 +0,0 @@
/*
* 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 */

View File

@@ -1,7 +1,7 @@
/*
* loopback block device utilities
*
* Copyright (C) 2011-2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 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
@@ -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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <string.h>
@@ -29,17 +29,7 @@
#include "utils_loop.h"
#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 *crypt_loop_get_device(void)
{
char dev[20];
int i, loop_fd;
@@ -66,32 +56,6 @@ static char *crypt_loop_get_device_old(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)
{
@@ -99,7 +63,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 || errno == EACCES) && !*readonly) {
if (file_fd < 0 && errno == EROFS && !*readonly) {
*readonly = 1;
file_fd = open(file, O_RDONLY | O_EXCL);
}

View File

@@ -1,27 +1,14 @@
/*
* 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);

View File

@@ -1,196 +0,0 @@
/*
* 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, int bsize, char *buffer,
uint64_t offset, uint64_t size)
{
memset(buffer, 0, size);
return write_lseek_blockwise(fd, bsize, buffer, size, offset);
}
static ssize_t _crypt_wipe_random(int fd, int bsize, 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, bsize, 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, int bsize, 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, bsize, buffer, size, offset);
if (written < 0 || written != (ssize_t)size)
return written;
}
/* Rewrite it finally with random */
return _crypt_wipe_random(fd, bsize, buffer, offset, size);
}
static ssize_t _crypt_wipe_ssd(int fd, int bsize, char *buffer,
uint64_t offset, uint64_t size)
{
// FIXME: for now just rewrite it by random
return _crypt_wipe_random(fd, bsize, buffer, offset, size);
}
int crypt_wipe(struct device *device,
uint64_t offset,
uint64_t size,
crypt_wipe_type type,
int exclusive)
{
struct stat st;
char *buffer;
int devfd, flags, rotational, bsize;
ssize_t written;
if (!size || size % SECTOR_SIZE || (size > MAXIMUM_WIPE_BYTES)) {
log_dbg("Unsuported wipe size for device %s: %ld.",
device_path(device), (unsigned long)size);
return -EINVAL;
}
if (stat(device_path(device), &st) < 0) {
log_dbg("Device %s not found.", device_path(device));
return -EINVAL;
}
if (type == CRYPT_WIPE_DISK && S_ISBLK(st.st_mode)) {
rotational = 0;
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;
}
bsize = device_block_size(device);
if (bsize <= 0)
return -EINVAL;
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_path(device), flags);
if (devfd == -1) {
free(buffer);
return errno ? -errno : -EINVAL;
}
// FIXME: use fixed block size and loop here
switch (type) {
case CRYPT_WIPE_ZERO:
written = _crypt_wipe_zero(devfd, bsize, buffer, offset, size);
break;
case CRYPT_WIPE_DISK:
written = _crypt_wipe_disk(devfd, bsize, buffer, offset, size);
break;
case CRYPT_WIPE_SSD:
written = _crypt_wipe_ssd(devfd, bsize, buffer, offset, size);
break;
case CRYPT_WIPE_RANDOM:
written = _crypt_wipe_random(devfd, bsize, 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;
}

View File

@@ -1,16 +0,0 @@
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

View File

@@ -1,283 +0,0 @@
/*
* 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,
uint64_t sb_offset,
char **uuid_string,
struct crypt_params_verity *params)
{
const char *device = device_path(crypt_metadata_device(cd));
int bsize = device_block_size(crypt_metadata_device(cd));
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, bsize, &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,
uint64_t sb_offset,
const char *uuid_string,
struct crypt_params_verity *params)
{
const char *device = device_path(crypt_metadata_device(cd));
int bsize = device_block_size(crypt_metadata_device(cd));
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, bsize, (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 *root_hash,
size_t root_hash_size,
struct crypt_params_verity *verity_hdr,
uint32_t activation_flags)
{
struct crypt_dm_active_device dmd;
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,
root_hash, root_hash_size);
if (r < 0)
return r;
}
if (!name)
return 0;
dmd.target = DM_VERITY;
dmd.data_device = crypt_data_device(cd);
dmd.u.verity.hash_device = crypt_metadata_device(cd);
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_block_adjust(cd, dmd.u.verity.hash_device, DEV_OK,
0, NULL, NULL);
if (r)
return r;
r = device_block_adjust(cd, dmd.data_device, DEV_EXCL,
0, &dmd.size, &dmd.flags);
if (r)
return r;
r = dm_create_device(cd, 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(cd, name);
if (r < 0)
return r;
if (!r)
log_err(cd, _("Verity device detected corruption after activation.\n"));
return 0;
}

View File

@@ -1,64 +0,0 @@
/*
* 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,
uint64_t sb_offset,
char **uuid,
struct crypt_params_verity *params);
int VERITY_write_sb(struct crypt_device *cd,
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 *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 *root_hash,
size_t root_hash_size);
int VERITY_create(struct crypt_device *cd,
struct crypt_params_verity *verity_hdr,
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

View File

@@ -1,431 +0,0 @@
/*
* 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,
struct device *hash_device,
struct device *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,
device_path(data_device), data_blocks,
device_path(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) {
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(device_path(data_device), "r");
if (!data_file) {
log_err(cd, _("Cannot open device %s.\n"),
device_path(data_device)
);
r = -EIO;
goto out;
}
log_dbg("Hash device size required: %" PRIu64 " bytes.",
hash_device_size);
hash_file = fopen(device_path(hash_device), verify ? "r" : "r+");
if (!hash_file) {
log_err(cd, _("Cannot open device %s.\n"),
device_path(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(device_path(hash_device), "r");
if (!hash_file_2) {
log_err(cd, _("Cannot open device %s.\n"),
device_path(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 *root_hash,
size_t root_hash_size)
{
return VERITY_create_or_verify_hash(cd, 1,
verity_hdr->hash_type,
verity_hdr->hash_name,
crypt_metadata_device(cd),
crypt_data_device(cd),
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,
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,
crypt_metadata_device(cd),
crypt_data_device(cd),
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);
}

View File

@@ -2,7 +2,7 @@
* cryptsetup volume key implementation
*
* Copyright (C) 2004-2006, Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2010-2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-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
@@ -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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <string.h>
@@ -33,8 +33,6 @@ 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;
}

View File

@@ -1,11 +1,3 @@
man8_MANS = 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
EXTRA_DIST = cryptsetup.8

View File

@@ -1,210 +0,0 @@
.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

File diff suppressed because it is too large Load Diff

View File

@@ -1,141 +0,0 @@
.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.
The data or hash device argument can be block device or file image.
If hash device path doesn't exist, it will be created as file.
\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

View File

@@ -1,17 +0,0 @@
TARGET=luks_dict
CFLAGS=-O2 -g -Wall -D_GNU_SOURCE
LDLIBS=-lcryptsetup
CC=gcc
SOURCES=$(wildcard *.c)
OBJECTS=$(SOURCES:.c=.o)
all: $(TARGET)
$(TARGET): $(OBJECTS)
$(CC) -o $@ $^ $(LDLIBS)
clean:
rm -f *.o *~ core $(TARGET)
.PHONY: clean

View File

@@ -1,17 +0,0 @@
Simple example how to use libcryptsetup
for password search.
Run: luks_dict <device|image> <dictionary> [cpus]
<device|image> is LUKS device or image
<dictionary> is list of passphrases to try
(note trailing EOL is stripped)
cpus - number of processes to start in parallel
Format of dictionary file is simple one password per line,
if first char on line s # it is skiped as comment.
You have it run as root (device-mapper cannot
create dmcrypt devices as nrmal user. Code need
to map keyslots as temporary dmcrypt device.)

View File

@@ -1,130 +0,0 @@
/*
* Example of LUKS password dictionary search
*
* Run this as root, e.g. ./luks_dict test.img /usr/share/john/password.lst 4
*
* 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/prctl.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <libcryptsetup.h>
#define MAX_LEN 512
static void check(struct crypt_device *cd, const char *pwd_file, unsigned my_id, unsigned max_id)
{
FILE *f;
int len, r = -1;
unsigned long line = 0;
char pwd[MAX_LEN];
if (fork())
return;
/* open password file, now in separate process */
f = fopen(pwd_file, "r");
if (!f) {
printf("Cannot open %s.\n", pwd_file);
exit(EXIT_FAILURE);
}
while (fgets(pwd, MAX_LEN, f)) {
/* every process tries N-th line, skip others */
if (line++ % max_id != my_id)
continue;
len = strlen(pwd);
/* strip EOL - this is like a input from tty */
if (len && pwd[len - 1] == '\n') {
pwd[len - 1] = '\0';
len--;
}
/* lines starting "#!comment" are comments */
if (len >= 9 && !strncmp(pwd, "#!comment", 9)) {
/* printf("skipping %s\n", pwd); */
continue;
}
/* printf("%d: checking %s\n", my_id, pwd); */
r = crypt_activate_by_passphrase(cd, NULL, CRYPT_ANY_SLOT, pwd, len, 0);
if (r >= 0) {
printf("Found passphrase for slot %d: \"%s\"\n", r, pwd);
break;
}
}
fclose(f);
crypt_free(cd);
exit(r >= 0 ? 2 : EXIT_SUCCESS);
}
int main(int argc, char *argv[])
{
int i, status, procs = 4;
struct crypt_device *cd;
if (argc < 3 || argc > 4) {
printf("Use: %s <LUKS_device|file> <password file> [#processes] %d\n", argv[0], argc);
exit(EXIT_FAILURE);
}
if (argc == 4 && (sscanf(argv[3], "%i", &procs) != 1 || procs < 1)) {
printf("Wrong number of processes.\n");
exit(EXIT_FAILURE);
}
/* crypt_set_debug_level(CRYPT_DEBUG_ALL); */
/*
* Need to create temporary keyslot device-mapper devices and allocate loop if needed,
* so root is requried here.
*/
if (getuid() != 0) {
printf("You must be root to run this program.\n");
exit(EXIT_FAILURE);
}
/* signal all children if anything happens */
prctl(PR_SET_PDEATHSIG, SIGHUP);
setpriority(PRIO_PROCESS, 0, -5);
/* we are not going to modify anything, so common init is ok */
if (crypt_init(&cd, argv[1]) || crypt_load(cd, CRYPT_LUKS1, NULL)) {
printf("Cannot open %s.\n", argv[1]);
exit(EXIT_FAILURE);
}
/* run scan in separate processes, it is up to scheduler to assign CPUs inteligently */
for (i = 0; i < procs; i++)
check(cd, argv[2], i, procs);
/* wait until at least one finishes with error or status 2 (key found) */
while (wait(&status) != -1 && WIFEXITED(status)) {
if (WEXITSTATUS(status) == EXIT_SUCCESS)
continue;
/* kill rest of processes */
kill(0, SIGHUP);
/* not reached */
break;
}
exit(0);
}

View File

@@ -1,23 +0,0 @@
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.

View File

@@ -1,5 +0,0 @@
#!/bin/bash
which cryptsetup-reencrypt >/dev/null 2>&1 || exit 1
exit 0

View File

@@ -1,6 +0,0 @@
#!/bin/bash
inst cryptsetup-reencrypt
inst_hook cmdline 30 "$moddir/parse-reencrypt.sh"
inst "$moddir"/reencrypt.sh /sbin/reencrypt

View File

@@ -1,22 +0,0 @@
#!/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
}

View File

@@ -1,22 +0,0 @@
#!/bin/sh
REENC=$(getargs rd_REENCRYPT=)
REENC_DEV=$(echo $REENC | sed 's/:.*//')
REENC_SIZE=$(echo $REENC | sed -n 's/.*://p')
REENC_KEY=$(getargs rd_REENCRYPT_KEY=)
if [ -z "$REENC_KEY" ] ; then
REENC_KEY=none
fi
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_KEY $REENC_SIZE"
printf 'LABEL="reenc_end"\n'
} > /etc/udev/rules.d/69-reencryption.rules
fi

View File

@@ -1,58 +0,0 @@
#!/bin/sh
#
# $1=$device [$2=keyfile|none [$3=size]]
#
[ -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 "$3" ]; then
PARAMS="$PARAMS --device-size $3"
fi
reenc_readkey() {
local keypath="${1#*:}"
local keydev="${1%%:*}"
local mntp="/tmp/reencrypted-mount-tmp"
mkdir "$mntp"
mount -r "$keydev" "$mntp" && cat "$mntp/$keypath"
umount "$mntp"
rm -r "$mntp"
}
reenc_run() {
local cwd=$(pwd)
cd /tmp
if [ "$1" = "none" ] ; then
/bin/plymouth ask-for-password \
--prompt "LUKS password for REENCRYPTING $device" \
--command="/sbin/cryptsetup-reencrypt $PARAMS"
else
info "REENCRYPT using key $1"
reenc_readkey "$1" | /sbin/cryptsetup-reencrypt -d - $PARAMS
fi
cd $cwd
}
info "REENCRYPT $device requested"
# flock against other interactive activities
{ flock -s 9;
reenc_run $2
} 9>/.console.lock
# do not ask again
>> /tmp/reencrypted
exit 0

View File

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

View File

@@ -1,118 +0,0 @@
Purpose
=======
chk_luks_keyslots is a tool that searches the keyslot area of a
LUKS container for positions where entropy is low and hence
there is a high probability of damage from overwrites of parts
of the key-slot with data such as a RAID superblock or a partition
table.
Installation
============
1. Install the version of cryptsetup the tool came with.
2. Compile with
gcc -lm -lcryptsetup chk_luks_keyslots.c -o chk_luks_keyslots
Usage
=====
Call chk_luks_keyslots without arguments for an option summary.
Example of a good keyslot area:
-------------------------------
root> ./chk_luks_keyslots /dev/loop0
parameters (commandline and LUKS header):
sector size: 512
threshold: 0.900000
- processing keyslot 0: start: 0x001000 end: 0x020400
- processing keyslot 1: start: 0x021000 end: 0x040400
- processing keyslot 2: start: 0x041000 end: 0x060400
- processing keyslot 3: start: 0x061000 end: 0x080400
- processing keyslot 4: start: 0x081000 end: 0x0a0400
- processing keyslot 5: start: 0x0a1000 end: 0x0c0400
- processing keyslot 6: start: 0x0c1000 end: 0x0e0400
- processing keyslot 7: start: 0x0e1000 end: 0x100400
Example of a fault in slot 8 at offset 0x100200:
-----------------------------
root>./chk_luks_keyslots /dev/loop2
parameters (commandline and LUKS header):
sector size: 512
threshold: 0.900000
- processing keyslot 0: start: 0x001000 end: 0x020400
- processing keyslot 1: start: 0x021000 end: 0x040400
- processing keyslot 2: start: 0x041000 end: 0x060400
- processing keyslot 3: start: 0x061000 end: 0x080400
- processing keyslot 4: start: 0x081000 end: 0x0a0400
- processing keyslot 5: start: 0x0a1000 end: 0x0c0400
- processing keyslot 6: start: 0x0c1000 end: 0x0e0400
- processing keyslot 7: start: 0x0e1000 end: 0x100400
low entropy at: 0x100200 entropy: 0.846546
Same as last, but verbose:
--------------------------
root>./chk_luks_keyslots -v /dev/loop2
parameters (commandline and LUKS header):
sector size: 512
threshold: 0.900000
- processing keyslot 0: start: 0x001000 end: 0x020400
- processing keyslot 1: start: 0x021000 end: 0x040400
- processing keyslot 2: start: 0x041000 end: 0x060400
- processing keyslot 3: start: 0x061000 end: 0x080400
- processing keyslot 4: start: 0x081000 end: 0x0a0400
- processing keyslot 5: start: 0x0a1000 end: 0x0c0400
- processing keyslot 6: start: 0x0c1000 end: 0x0e0400
- processing keyslot 7: start: 0x0e1000 end: 0x100400
low entropy at: 0x100200 entropy: 0.846546
Binary dump:
0x100200 BD 0E C7 A8 7D EF 04 F6 AF 83 DF 74 94 FE 04 56 ....}......t...V
0x100210 3B 64 BD 68 A9 F6 CF 3C 37 CD 66 B7 17 4D 63 2B ;d.h...<7.f..Mc+
0x100220 8F 6E 74 7E 96 7A 2B 27 32 1B F0 80 37 5A 9A 41 .nt~.z+'2...7Z.A
0x100230 4A 6E CB C0 CF 39 95 45 92 90 E1 0B E6 08 EE 2A Jn...9.E.......*
0x100240 FA 66 6D 67 49 89 76 B1 41 CD 24 57 AA 65 F7 69 .fmgI.v.A.$W.e.i
0x100250 33 16 A7 C7 61 3D 43 B7 74 D6 86 83 1D 19 BF 85 3...a=C.t.......
0x100260 E4 22 3E 16 66 1C B0 1E 11 0D D4 26 37 AD A4 02 .">.f......&7...
0x100270 40 77 9A 5A B8 40 39 E3 A3 A0 96 08 4D 57 C5 0C @w.Z.@9.....MW..
0x100280 D4 74 89 45 FA 93 F7 FE A7 9D D3 99 43 77 8E 35 .t.E........Cw.5
0x100290 E0 55 90 3E 91 29 EA DB 5C 13 19 C9 83 CE D8 0C .U.>.)..\.......
0x1002a0 85 7F 96 26 60 16 A0 0B E1 F9 01 13 1E 59 83 98 ...&`........Y..
0x1002b0 06 B5 1D 6F B6 81 9D 60 58 70 15 30 29 42 32 C6 ...o...`Xp.0)B2.
0x1002c0 A7 55 64 00 65 ED 41 1C B4 C1 C7 10 E1 8E 60 B0 .Ud.e.A.......`.
0x1002d0 F0 9E 9C 40 5A 84 92 8D 21 F0 B8 2D 61 4E 21 9D ...@Z...!..-aN!.
0x1002e0 FA B8 18 D3 47 A4 4F D4 AB 73 C0 93 F3 8E 9A 95 ....G.O..s......
0x1002f0 A4 F1 6D EB 36 85 F4 F7 62 BA 26 D5 15 57 0D 0C ..m.6...b.&..W..
0x100300 C9 4E 19 F2 5B 5A F5 54 B8 F4 B5 57 72 08 1B 7A .N..[Z.T...Wr..z
0x100310 C3 66 7F 82 1E 75 92 C2 E9 97 64 5E F7 FB A9 05 .f...u....d^....
0x100320 CF 30 C8 6A D1 35 9B 9D 22 52 22 46 0E 4B DE 53 .0.j.5.."R"F.K.S
0x100330 68 C8 DA 5F C7 CA 31 D0 C9 B4 57 CF 0F 1F 4B 9C h.._..1...W...K.
0x100340 DF 0C F8 7C F2 E3 32 52 3C 0D D2 DC 5C CF F0 00 ...|..2R<...\...
0x100350 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 XXXXXXXXXXXXXXXX
0x100360 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 XXXXXXXXXXXXXXXX
0x100370 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 XXXXXXXXXXXXXXXX
0x100380 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 XXXXXXXXXXXXXXXX
0x100390 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 XXXXXXXXXXXXXXXX
0x1003a0 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 XXXXXXXXXXXXXXXX
0x1003b0 B4 81 7A F0 BE 38 7E 00 A4 61 41 06 ED 7B 40 D9 ..z..8~..aA..{@.
0x1003c0 BF 58 51 C9 CD 37 78 4D 4D B3 6E B4 7D 86 3C CB .XQ..7xMM.n.}.<.
0x1003d0 D5 39 2E FC 78 B1 3E DE C0 7F 55 25 65 71 AD 2A .9..x.>...U%eq.*
0x1003e0 1E 68 D3 3B 78 17 5F D2 08 93 50 88 D8 0A 75 4F .h.;x._...P...uO
0x1003f0 E5 AA 26 0F B4 F7 F5 88 65 2B E4 92 18 08 32 9E ..&.....e+....2.
----
Copyright (C) 2012, Arno Wagner <arno@wagner.name>
This file is free documentation; the author gives
unlimited permission to copy, distribute and modify it.

View File

@@ -1,370 +0,0 @@
/*
* LUKS keyslot entropy tester. Works only for header version 1.
*
* Functionality: Determines sample entropy (symbols: bytes) for
* each (by default) 512B sector in each used keyslot. If it
* is lower than a threshold, the sector address is printed
* as it is suspected of having non-"random" data in it, indicating
* damage by overwriting. This can obviously not find overwriting
* with random or random-like data (encrypted, compressed).
*
* Version history:
* v0.1: 09.09.2012 Initial release
* v0.2: 08.10.2012 Converted to use libcryptsetup
*
* Copyright (C) 2012, Arno Wagner <arno@wagner.name>
*
* 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 <stdio.h>
#include <unistd.h>
#include <ctype.h>
#include <math.h>
#include <fcntl.h>
#include <inttypes.h>
#include <libcryptsetup.h>
const char *help =
"Version 0.2 [8.10.2012]\n"
"\n"
" chk_luks_keyslots [options] luks-device \n"
"\n"
"This tool checks all keyslots of a LUKS device for \n"
"low entropy sections. If any are found, they are reported. \n"
"This allows to find areas damaged by things like filesystem \n"
"creation or RAID superblocks. \n"
"\n"
"Options: \n"
" -t <num> Entropy threshold. Possible values 0.0 ... 1.0 \n"
" Default: 0.90, which works well for 512B sectors.\n"
" For 512B sectors, you will get frequent misdetections\n"
" at thresholds around 0.94\n"
" Higher value: more sensitive but more false detections.\n"
" -s <num> Sector size. Must divide keyslot-size.\n"
" Default: 512 Bytes.\n"
" Values smaller than 128 are generally not very useful.\n"
" For values smaller than the default, you need to adjust\n"
" the threshold down to reduce misdetection. For values\n"
" larger than the default you need to adjust the threshold\n"
" up to retain sensitivity.\n"
" -v Print found suspicuous sectors verbosely. \n"
" -d Print decimal addresses instead of hex ones.\n"
"\n";
/* Config defaults */
static int sector_size = 512;
static double threshold = 0.90;
static int print_decimal = 0;
static int verbose = 0;
/* tools */
/* Calculates and returns sample entropy on byte level for
* The argument.
*/
static double ent_samp(unsigned char * buf, int len)
{
int freq[256]; /* stores symbol frequencies */
int i;
double e, f;
/* 0. Plausibility checks */
if (len <= 0)
return 0.0;
/* 1. count all frequencies */
for (i = 0; i < 256; i++) {
freq[i] = 0.0;
}
for (i = 0; i < len; i ++)
freq[buf[i]]++;
/* 2. calculate sample entropy */
e = 0.0;
for (i = 0; i < 256; i++) {
f = freq[i];
if (f > 0) {
f = f / (double)len;
e += f * log2(f);
}
}
if (e != 0.0)
e = -1.0 * e;
e = e / 8.0;
return e;
}
static void print_address(FILE *out, uint64_t value)
{
if (print_decimal) {
fprintf(out,"%08" PRIu64 " ", value);
} else {
fprintf(out,"%#08" PRIx64 " ", value);
}
}
/* uses default "hd" style, i.e. 16 bytes followed by ASCII */
static void hexdump_line(FILE *out, uint64_t address, unsigned char *buf) {
int i;
static char tbl[16] = "0123456789ABCDEF";
fprintf(out," ");
print_address(out, address);
fprintf(out," ");
/* hex */
for (i = 0; i < 16; i++) {
fprintf(out, "%c%c",
tbl[(unsigned char)buf[i]>> 4],
tbl[(unsigned char)buf[i] & 0x0f]);
fprintf(out," ");
if (i == 7)
fprintf(out," ");
}
fprintf(out," ");
/* ascii */
for (i = 0; i < 16; i++) {
if (isprint(buf[i])) {
fprintf(out, "%c", buf[i]);
} else {
fprintf(out, ".");
}
}
fprintf(out, "\n");
}
static void hexdump_sector(FILE *out, unsigned char *buf, uint64_t address, int len)
{
int done;
done = 0;
while (len - done >= 16) {
hexdump_line(out, address + done, buf + done);
done += 16;
}
}
static int check_keyslots(FILE *out, struct crypt_device *cd, int f_luks)
{
int i;
double ent;
off_t ofs;
uint64_t start, length, end;
crypt_keyslot_info ki;
unsigned char buffer[sector_size];
for (i = 0; i < crypt_keyslot_max(CRYPT_LUKS1) ; i++) {
fprintf(out, "- processing keyslot %d:", i);
ki = crypt_keyslot_status(cd, i);
if (ki == CRYPT_SLOT_INACTIVE) {
fprintf(out, " keyslot not in use\n");
continue;
}
if (ki == CRYPT_SLOT_INVALID) {
fprintf(out, "\nError: keyslot invalid.\n");
return EXIT_FAILURE;
}
if (crypt_keyslot_area(cd, i, &start, &length) < 0) {
fprintf(stderr,"\nError: querying keyslot area failed for slot %d\n", i);
perror(NULL);
return EXIT_FAILURE;
}
end = start + length;
fprintf(out, " start: ");
print_address(out, start);
fprintf(out, " end: ");
print_address(out, end);
fprintf(out, "\n");
/* check whether sector-size divides size */
if (length % sector_size != 0) {
fprintf(stderr,"\nError: Argument to -s does not divide keyslot size\n");
return EXIT_FAILURE;
}
for (ofs = start; (uint64_t)ofs < end; ofs += sector_size) {
if (lseek(f_luks, ofs, SEEK_SET) != ofs) {
fprintf(stderr,"\nCannot seek to keyslot area.\n");
return EXIT_FAILURE;
}
if (read(f_luks, buffer, sector_size) != sector_size) {
fprintf(stderr,"\nCannot read keyslot area.\n");
return EXIT_FAILURE;
}
ent = ent_samp(buffer, sector_size);
if (ent < threshold) {
fprintf(out, " low entropy at: ");
print_address(out, ofs);
fprintf(out, " entropy: %f\n", ent);
if (verbose) {
fprintf(out, " Binary dump:\n");
hexdump_sector(out, buffer, (uint64_t)ofs, sector_size);
fprintf(out,"\n");
}
}
}
}
return EXIT_SUCCESS;
}
/* Main */
int main(int argc, char **argv)
{
/* for option processing */
int c, r;
char *device;
/* for use of libcryptsetup */
struct crypt_device *cd;
/* Other vars */
int f_luks; /* device file for the luks device */
FILE *out;
/* temporary helper vars */
int res;
/* getopt values */
char *s, *end;
double tvalue;
int svalue;
/* global initializations */
out = stdout;
/* get commandline parameters */
while ((c = getopt (argc, argv, "t:s:vd")) != -1) {
switch (c) {
case 't':
s = optarg;
tvalue = strtod(s, &end);
if (s == end) {
fprintf(stderr, "\nError: Parsing of argument to -t failed.\n");
exit(EXIT_FAILURE);
}
if (tvalue < 0.0 || tvalue > 1.0) {
fprintf(stderr,"\nError: Argument to -t must be in 0.0 ... 1.0\n");
exit(EXIT_FAILURE);
}
threshold = tvalue;
break;
case 's':
s = optarg;
svalue = strtol(s, &end, 10);
if (s == end) {
fprintf(stderr, "\nError: Parsing of argument to -s failed.\n");
exit(EXIT_FAILURE);
}
if (svalue < 1) {
fprintf(stderr,"\nError: Argument to -s must be >= 1 \n");
exit(EXIT_FAILURE);
}
sector_size = svalue;
break;
case 'v':
verbose = 1;
break;
case 'd':
print_decimal = 1;
break;
case '?':
if (optopt == 't' || optopt == 's')
fprintf (stderr,"\nError: Option -%c requires an argument.\n",
optopt);
else if (isprint (optopt)) {
fprintf(stderr,"\nError: Unknown option `-%c'.\n", optopt);
fprintf(stderr,"\n\n%s", help);
} else {
fprintf (stderr, "\nError: Unknown option character `\\x%x'.\n",
optopt);
fprintf(stderr,"\n\n%s", help);
}
exit(EXIT_SUCCESS);
default:
exit(EXIT_FAILURE);
}
}
/* parse non-option stuff. Should be exactly one, the device. */
if (optind+1 != argc) {
fprintf(stderr,"\nError: exactly one non-option argument expected!\n");
fprintf(stderr,"\n\n%s", help);
exit(EXIT_FAILURE);
}
device = argv[optind];
/* test whether we can open and read device */
/* This is neded as we are reading the actual data
* in the keyslots dirtectly from the LUKS container.
*/
f_luks = open(device, O_RDONLY);
if (f_luks == -1) {
fprintf(stderr,"\nError: Opening of device %s failed:\n", device);
perror(NULL);
exit(EXIT_FAILURE);
}
/* now get the parameters we need via libcryptsetup */
/* Basically we need all active keyslots and their placement on disk */
/* first init. This does the following:
* - gets us a crypt_device struct with some values filled in
* Note: This does some init stuff we do not need, but that
* should not cause trouble.
*/
res = crypt_init(&cd, device);
if (res < 0) {
fprintf(stderr, "crypt_init() failed. Maybe not running as root?\n");
close(f_luks);
exit(EXIT_FAILURE);
}
/* now load LUKS header into the crypt_device
* This should also make sure a valid LUKS1 header is on disk
* and hence we should be able to skip magic and version checks.
*/
res = crypt_load(cd, CRYPT_LUKS1, NULL);
if (res < 0) {
fprintf(stderr, "crypt_load() failed. LUKS header too broken/absent?\n");
crypt_free(cd);
close(f_luks);
exit(EXIT_FAILURE);
}
fprintf(out, "\nparameters (commandline and LUKS header):\n");
fprintf(out, " sector size: %d\n", sector_size);
fprintf(out, " threshold: %0f\n\n", threshold);
r = check_keyslots(out, cd, f_luks);
crypt_free(cd);
close(f_luks);
return r;
}

View File

@@ -1,59 +0,0 @@
#!/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"

View File

@@ -1,11 +1,9 @@
cs
de
fi
fr
id
it
nl
pl
sv
uk
vi

View File

@@ -5,16 +5,10 @@ lib/utils.c
lib/crypt_plain.c
lib/utils_crypt.c
lib/utils_loop.c
lib/utils_fips.c
lib/utils_device.c
lib/utils_debug.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
src/utils_tools.c

1497
po/cs.po

File diff suppressed because it is too large Load Diff

1704
po/de.po

File diff suppressed because it is too large Load Diff

1180
po/fi.po

File diff suppressed because it is too large Load Diff

1653
po/fr.po

File diff suppressed because it is too large Load Diff

1064
po/it.po

File diff suppressed because it is too large Load Diff

1292
po/nl.po

File diff suppressed because it is too large Load Diff

1402
po/pl.po

File diff suppressed because it is too large Load Diff

1563
po/uk.po

File diff suppressed because it is too large Load Diff

1713
po/vi.po

File diff suppressed because it is too large Load Diff

View File

@@ -1,16 +0,0 @@
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

View File

@@ -1,131 +0,0 @@
#!/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)

View File

@@ -1,713 +0,0 @@
/*
* 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);
}

View File

@@ -9,25 +9,21 @@ 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 \
utils_tools.c \
cryptsetup.c \
cryptsetup.h
cryptsetup_LDADD = \
$(top_builddir)/lib/libcryptsetup.la \
@POPT_LIBS@ \
@FIPSCHECK_LIBS@
@POPT_LIBS@
cryptsetup_CFLAGS = -Wall
sbin_PROGRAMS=cryptsetup
if STATIC_TOOLS
if STATIC_CRYPTSETUP
sbin_PROGRAMS += cryptsetup.static
cryptsetup_static_SOURCES = $(cryptsetup_SOURCES)
cryptsetup_static_CFLAGS = $(cryptsetup_CFLAGS)
@@ -37,58 +33,3 @@ 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 \
utils_tools.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 \
utils_tools.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

File diff suppressed because it is too large Load Diff

View File

@@ -1,76 +1,14 @@
/*
* 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
#define _LARGEFILE64_SOURCE
#define _FILE_OFFSET_BITS 64
#include <config.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <errno.h>
#include <unistd.h>
#include <inttypes.h>
#include <limits.h>
#include <ctype.h>
#include <fcntl.h>
#include <popt.h>
#include <sys/stat.h>
#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)
#define SECTOR_SIZE 512
#define ROUND_SECTOR(x) (((x) + SECTOR_SIZE - 1) / SECTOR_SIZE)
extern int opt_debug;
extern int opt_verbose;
extern int opt_batch_mode;
/* Common tools */
void clogger(struct crypt_device *cd, int level, const char *file, int line,
const char *format, ...);
void tool_log(int level, const char *msg, void *usrptr __attribute__((unused)));
void quiet_log(int level, const char *msg, void *usrptr);
int yesDialog(const char *msg, void *usrptr __attribute__((unused)));
void show_status(int errcode);
const char *uuid_or_device(const char *spec);
void usage(poptContext popt_context, int exitcode, const char *error, const char *more);
void dbg_version_and_cmd(int argc, const char **argv);
int translate_errno(int r);
/* Log */
#define log_dbg(x...) clogger(NULL, CRYPT_LOG_DEBUG, __FILE__, __LINE__, x)
#define log_std(x...) clogger(NULL, CRYPT_LOG_NORMAL, __FILE__, __LINE__, x)
#define log_verbose(x...) clogger(NULL, CRYPT_LOG_VERBOSE, __FILE__, __LINE__, x)

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