aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-04-08 16:00:35 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-04-08 16:00:35 +0000
commit0ae9e5c7f7099ff3dba8fe2f022c8eef35e083ca (patch)
tree1e00499c0bed9db81feab51bbd69f4652a2a82ad
parentd6d41274a251064b52a9ccb8e9d9f8a9890df8bc (diff)
parentcc5e51366174ddd4580c78c9845d86e44586c034 (diff)
downloadfsverity-utils-aml_tz2_305400100.tar.gz
Change-Id: I7064b1f27db92266d43ad2ddc064b5fca192456d
-rw-r--r--.clang-format17
-rw-r--r--.gitignore12
-rw-r--r--Android.bp68
-rw-r--r--COPYING339
-rw-r--r--LICENSE360
-rw-r--r--METADATA11
-rw-r--r--MODULE_LICENSE_GPL (renamed from MODULE_LICENSE_MIT)0
-rw-r--r--Makefile261
-rw-r--r--NEWS.md43
-rw-r--r--NOTICE339
-rw-r--r--README.md114
-rw-r--r--cmd_enable.c (renamed from programs/cmd_enable.c)77
-rw-r--r--cmd_measure.c (renamed from programs/cmd_measure.c)24
-rw-r--r--cmd_sign.c635
-rw-r--r--commands.h24
-rw-r--r--common/fsverity_uapi.h91
-rw-r--r--common/win32_defs.h57
-rw-r--r--fsverity.c (renamed from programs/fsverity.c)117
-rw-r--r--fsverity_uapi.h40
-rw-r--r--hash_algs.c (renamed from lib/hash_algs.c)135
-rw-r--r--hash_algs.h68
-rw-r--r--include/libfsverity.h213
-rw-r--r--lib/compute_digest.c238
-rw-r--r--lib/enable.c53
-rw-r--r--lib/lib_private.h95
-rw-r--r--lib/libfsverity.pc.in10
-rw-r--r--lib/sign_digest.c390
-rw-r--r--lib/utils.c132
-rw-r--r--programs/cmd_digest.c129
-rw-r--r--programs/cmd_sign.c133
-rw-r--r--programs/fsverity.h58
-rw-r--r--programs/test_compute_digest.c310
-rw-r--r--programs/test_hash_algs.c45
-rw-r--r--programs/test_sign_digest.c57
-rw-r--r--programs/utils.h51
-rwxr-xr-xscripts/do-release.sh46
-rwxr-xr-xscripts/run-sparse.sh14
-rwxr-xr-xscripts/run-tests.sh187
-rw-r--r--testdata/cert.pem31
-rw-r--r--testdata/file.sigbin708 -> 0 bytes
-rw-r--r--testdata/key.pem52
-rw-r--r--util.c (renamed from programs/utils.c)52
-rw-r--r--util.h (renamed from common/common_defs.h)58
43 files changed, 2068 insertions, 3118 deletions
diff --git a/.clang-format b/.clang-format
deleted file mode 100644
index 834d0a4..0000000
--- a/.clang-format
+++ /dev/null
@@ -1,17 +0,0 @@
-# SPDX-License-Identifier: MIT
-# Copyright 2020 Google LLC
-#
-# Use of this source code is governed by an MIT-style
-# license that can be found in the LICENSE file or at
-# https://opensource.org/licenses/MIT.
-
-# Formatting settings to approximate the Linux kernel coding style.
-BasedOnStyle: LLVM
-AllowShortFunctionsOnASingleLine: false
-AllowShortIfStatementsOnASingleLine: false
-BreakBeforeBraces: Linux
-Cpp11BracedListStyle: false
-IncludeBlocks: Preserve
-IndentCaseLabels: false
-IndentWidth: 8
-UseTab: Always
diff --git a/.gitignore b/.gitignore
index 04f9a6f..95457ca 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,13 +1,5 @@
-*.a
+fsverity
*.o
-*.patch
-*.so
-*.so.*
-/.build-config
-/fsverity
-/fsverity.sig
-/run-tests.log
-/test_*
+tags
cscope.*
ncscope.*
-tags
diff --git a/Android.bp b/Android.bp
index 025de57..8b9f1e6 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,69 +1,11 @@
-package {
- default_applicable_licenses: ["external_fsverity-utils_license"],
-}
-
-// Added automatically by a large-scale-change that took the approach of
-// 'apply every license found to every target'. While this makes sure we respect
-// every license restriction, it may not be entirely correct.
-//
-// e.g. GPL in an MIT project might only apply to the contrib/ directory.
-//
-// Please consider splitting the single license below into multiple licenses,
-// taking care not to lose any license_kind information, and overriding the
-// default license using the 'licenses: [...]' property on targets as needed.
-//
-// For unused files, consider creating a 'fileGroup' with "//visibility:private"
-// to attach the license to, and including a comment whether the files may be
-// used in the current project.
-// See: http://go/android-license-faq
-license {
- name: "external_fsverity-utils_license",
- visibility: [":__subpackages__"],
- license_kinds: [
- "SPDX-license-identifier-GPL-2.0",
- "SPDX-license-identifier-MIT",
- ],
- license_text: [
- "LICENSE",
- ],
-}
-
-cc_defaults {
- name: "fsverity_default_flags",
-
- cflags: [
- "-Wall",
- "-Wno-pointer-arith",
- "-D_GNU_SOURCE",
- "-D_FILE_OFFSET_BITS=64",
- ],
-}
-
cc_binary {
name: "fsverity",
- defaults: [
- "fsverity_default_flags",
- ],
- host_supported: true,
- shared_libs: ["libfsverity"],
- srcs: [
- "programs/cmd_*.c",
- "programs/fsverity.c",
- "programs/utils.c",
- ],
-}
-
-cc_library {
- name: "libfsverity",
- defaults: [
- "fsverity_default_flags",
- ],
host_supported: true,
shared_libs: ["libcrypto"],
-
- export_include_dirs: ["include"],
-
- srcs: [
- "lib/*.c",
+ cflags: [
+ "-Wall",
+ "-Wno-pointer-arith",
+ "-D_FILE_OFFSET_BITS=64"
],
+ srcs: ["*.c"],
}
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..d159169
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/LICENSE b/LICENSE
index 3211373..d159169 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,21 +1,339 @@
-Copyright 2019 the fsverity-utils authors
-
-Permission is hereby granted, free of charge, to any person
-obtaining a copy of this software and associated documentation files
-(the "Software"), to deal in the Software without restriction,
-including without limitation the rights to use, copy, modify, merge,
-publish, distribute, sublicense, and/or sell copies of the Software,
-and to permit persons to whom the Software is furnished to do so,
-subject to the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/METADATA b/METADATA
index 6fb345f..c92888e 100644
--- a/METADATA
+++ b/METADATA
@@ -1,16 +1,15 @@
name: "fsverity-utils"
-description: "This is fsverity-utils, a set of userspace utilities for fs-verity. fs-verity is a Linux kernel feature that does transparent on-demand integrity/authenticity verification of the contents of read-only files, using a hidden Merkle tree (hash tree) associated with the file. fsverity-utils currently contains just one program, `fsverity`. The `fsverity` program allows you to set up fs-verity protected files."
+description: "This is `fsverity`, a userspace utility for fs-verity. fs-verity is a Linux kernel feature that does transparent on-demand integrity/authenticity verification of the contents of read-only files, using a Merkle tree (hash tree) hidden after the end of the file. The mechanism is similar to dm-verity, but implemented at the file level rather than at the block device level. The `fsverity` utility allows you to set up fs-verity protected files."
third_party {
url {
type: GIT
value: "https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/fsverity-utils.git"
}
- version: "v1.3"
- # would be NOTICE save for common/fsverity_uapi.h
+ version: "2151209ce1dae61c4ee7480e2c39ada1d912fcb2"
license_type: RESTRICTED
last_upgrade_date {
- year: 2021
- month: 1
- day: 19
+ year: 2019
+ month: 7
+ day: 24
}
}
diff --git a/MODULE_LICENSE_MIT b/MODULE_LICENSE_GPL
index e69de29..e69de29 100644
--- a/MODULE_LICENSE_MIT
+++ b/MODULE_LICENSE_GPL
diff --git a/Makefile b/Makefile
index 0354f62..b9c09b9 100644
--- a/Makefile
+++ b/Makefile
@@ -1,253 +1,22 @@
-# SPDX-License-Identifier: MIT
-# Copyright 2020 Google LLC
-#
-# Use of this source code is governed by an MIT-style
-# license that can be found in the LICENSE file or at
-# https://opensource.org/licenses/MIT.
+EXE := fsverity
+CFLAGS := -O2 -Wall
+CPPFLAGS := -D_FILE_OFFSET_BITS=64
+LDLIBS := -lcrypto
+DESTDIR := /usr/local
+SRC := $(wildcard *.c)
+OBJ := $(SRC:.c=.o)
+HDRS := $(wildcard *.h)
+all:$(EXE)
-# Use 'make help' to list available targets.
-#
-# Define V=1 to enable "verbose" mode, showing all executed commands.
-#
-# Define USE_SHARED_LIB=1 to link the fsverity binary to the shared library
-# libfsverity.so rather than to the static library libfsverity.a.
-#
-# Define PREFIX to override the installation prefix, like './configure --prefix'
-# in autotools-based projects (default: /usr/local)
-#
-# Define BINDIR to override where to install binaries, like './configure
-# --bindir' in autotools-based projects (default: PREFIX/bin)
-#
-# Define INCDIR to override where to install headers, like './configure
-# --includedir' in autotools-based projects (default: PREFIX/include)
-#
-# Define LIBDIR to override where to install libraries, like './configure
-# --libdir' in autotools-based projects (default: PREFIX/lib)
-#
-# Define DESTDIR to override the installation destination directory
-# (default: empty string)
-#
-# You can also specify custom CC, CFLAGS, CPPFLAGS, LDFLAGS, and/or PKGCONF.
-#
-##############################################################################
+$(EXE):$(OBJ)
-cc-option = $(shell if $(CC) $(1) -c -x c /dev/null -o /dev/null > /dev/null 2>&1; \
- then echo $(1); fi)
+$(OBJ): %.o: %.c $(HDRS)
-# Support building with MinGW for minimal Windows fsverity.exe, but not for
-# libfsverity. fsverity.exe will be statically linked.
-ifneq ($(findstring -mingw,$(shell $(CC) -dumpmachine 2>/dev/null)),)
-MINGW = 1
-endif
-
-CFLAGS ?= -O2
-
-override CFLAGS := -Wall -Wundef \
- $(call cc-option,-Wdeclaration-after-statement) \
- $(call cc-option,-Wimplicit-fallthrough) \
- $(call cc-option,-Wmissing-field-initializers) \
- $(call cc-option,-Wmissing-prototypes) \
- $(call cc-option,-Wstrict-prototypes) \
- $(call cc-option,-Wunused-parameter) \
- $(call cc-option,-Wvla) \
- $(CFLAGS)
-
-override CPPFLAGS := -Iinclude -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE $(CPPFLAGS)
-
-ifneq ($(V),1)
-QUIET_CC = @echo ' CC ' $@;
-QUIET_CCLD = @echo ' CCLD ' $@;
-QUIET_AR = @echo ' AR ' $@;
-QUIET_LN = @echo ' LN ' $@;
-QUIET_GEN = @echo ' GEN ' $@;
-endif
-USE_SHARED_LIB ?=
-PREFIX ?= /usr/local
-BINDIR ?= $(PREFIX)/bin
-INCDIR ?= $(PREFIX)/include
-LIBDIR ?= $(PREFIX)/lib
-DESTDIR ?=
-ifneq ($(MINGW),1)
-PKGCONF ?= pkg-config
-else
-PKGCONF := false
-EXEEXT := .exe
-endif
-FSVERITY := fsverity$(EXEEXT)
-
-# Rebuild if a user-specified setting that affects the build changed.
-.build-config: FORCE
- @flags=$$( \
- echo 'CC=$(CC)'; \
- echo 'CFLAGS=$(CFLAGS)'; \
- echo 'CPPFLAGS=$(CPPFLAGS)'; \
- echo 'LDFLAGS=$(LDFLAGS)'; \
- echo 'LDLIBS=$(LDLIBS)'; \
- echo 'USE_SHARED_LIB=$(USE_SHARED_LIB)'; \
- ); \
- if [ "$$flags" != "`cat $@ 2>/dev/null`" ]; then \
- [ -e $@ ] && echo "Rebuilding due to new settings"; \
- echo "$$flags" > $@; \
- fi
-
-DEFAULT_TARGETS :=
-COMMON_HEADERS := $(wildcard common/*.h)
-LDLIBS := $(shell "$(PKGCONF)" libcrypto --libs 2>/dev/null || echo -lcrypto)
-CFLAGS += $(shell "$(PKGCONF)" libcrypto --cflags 2>/dev/null || echo)
-
-# If we are dynamically linking, when running tests we need to override
-# LD_LIBRARY_PATH as no RPATH is set
-ifdef USE_SHARED_LIB
-RUN_FSVERITY = LD_LIBRARY_PATH=./ $(TEST_WRAPPER_PROG) ./$(FSVERITY)
-else
-RUN_FSVERITY = $(TEST_WRAPPER_PROG) ./$(FSVERITY)
-endif
-
-##############################################################################
-
-#### Library
-
-SOVERSION := 0
-LIB_CFLAGS := $(CFLAGS) -fvisibility=hidden
-LIB_SRC := $(wildcard lib/*.c)
-ifeq ($(MINGW),1)
-LIB_SRC := $(filter-out lib/enable.c,${LIB_SRC})
-endif
-LIB_HEADERS := $(wildcard lib/*.h) $(COMMON_HEADERS)
-STATIC_LIB_OBJ := $(LIB_SRC:.c=.o)
-SHARED_LIB_OBJ := $(LIB_SRC:.c=.shlib.o)
-
-# Compile static library object files
-$(STATIC_LIB_OBJ): %.o: %.c $(LIB_HEADERS) .build-config
- $(QUIET_CC) $(CC) -o $@ -c $(CPPFLAGS) $(LIB_CFLAGS) $<
-
-# Compile shared library object files
-$(SHARED_LIB_OBJ): %.shlib.o: %.c $(LIB_HEADERS) .build-config
- $(QUIET_CC) $(CC) -o $@ -c $(CPPFLAGS) $(LIB_CFLAGS) -fPIC $<
-
-# Create static library
-libfsverity.a:$(STATIC_LIB_OBJ)
- $(QUIET_AR) $(AR) cr $@ $+
-
-DEFAULT_TARGETS += libfsverity.a
-
-# Create shared library
-libfsverity.so.$(SOVERSION):$(SHARED_LIB_OBJ)
- $(QUIET_CCLD) $(CC) -o $@ -Wl,-soname=$@ -shared $+ \
- $(CFLAGS) $(LDFLAGS) $(LDLIBS)
-
-DEFAULT_TARGETS += libfsverity.so.$(SOVERSION)
-
-# Create the symlink libfsverity.so => libfsverity.so.$(SOVERSION)
-libfsverity.so:libfsverity.so.$(SOVERSION)
- $(QUIET_LN) ln -sf $+ $@
-
-DEFAULT_TARGETS += libfsverity.so
-
-##############################################################################
-
-#### Programs
-
-ALL_PROG_SRC := $(wildcard programs/*.c)
-ALL_PROG_OBJ := $(ALL_PROG_SRC:.c=.o)
-ALL_PROG_HEADERS := $(wildcard programs/*.h) $(COMMON_HEADERS)
-PROG_COMMON_SRC := programs/utils.c
-PROG_COMMON_OBJ := $(PROG_COMMON_SRC:.c=.o)
-FSVERITY_PROG_OBJ := $(PROG_COMMON_OBJ) \
- programs/cmd_digest.o \
- programs/cmd_sign.o \
- programs/fsverity.o
-ifneq ($(MINGW),1)
-FSVERITY_PROG_OBJ += \
- programs/cmd_enable.o \
- programs/cmd_measure.o
-endif
-TEST_PROG_SRC := $(wildcard programs/test_*.c)
-TEST_PROGRAMS := $(TEST_PROG_SRC:programs/%.c=%$(EXEEXT))
-
-# Compile program object files
-$(ALL_PROG_OBJ): %.o: %.c $(ALL_PROG_HEADERS) .build-config
- $(QUIET_CC) $(CC) -o $@ -c $(CPPFLAGS) $(CFLAGS) $<
-
-# Link the fsverity program
-ifdef USE_SHARED_LIB
-$(FSVERITY): $(FSVERITY_PROG_OBJ) libfsverity.so
- $(QUIET_CCLD) $(CC) -o $@ $(FSVERITY_PROG_OBJ) \
- $(CFLAGS) $(LDFLAGS) -L. -lfsverity
-else
-$(FSVERITY): $(FSVERITY_PROG_OBJ) libfsverity.a
- $(QUIET_CCLD) $(CC) -o $@ $+ $(CFLAGS) $(LDFLAGS) $(LDLIBS)
-endif
-
-DEFAULT_TARGETS += $(FSVERITY)
-
-# Link the test programs
-$(TEST_PROGRAMS): %$(EXEEXT): programs/%.o $(PROG_COMMON_OBJ) libfsverity.a
- $(QUIET_CCLD) $(CC) -o $@ $+ $(CFLAGS) $(LDFLAGS) $(LDLIBS)
-
-##############################################################################
-
-SPECIAL_TARGETS := all test_programs check install uninstall help clean
-
-FORCE:
-
-.PHONY: $(SPECIAL_TARGETS) FORCE
-
-.DEFAULT_GOAL = all
-
-all:$(DEFAULT_TARGETS)
-
-test_programs:$(TEST_PROGRAMS)
-
-# This just runs some quick, portable tests. Use scripts/run-tests.sh if you
-# want to run the full tests.
-check:$(FSVERITY) test_programs
- for prog in $(TEST_PROGRAMS); do \
- $(TEST_WRAPPER_PROG) ./$$prog || exit 1; \
- done
- $(RUN_FSVERITY) --help > /dev/null
- $(RUN_FSVERITY) --version > /dev/null
- $(RUN_FSVERITY) sign $(FSVERITY) fsverity.sig \
- --key=testdata/key.pem --cert=testdata/cert.pem > /dev/null
- $(RUN_FSVERITY) sign $(FSVERITY) fsverity.sig --hash=sha512 \
- --block-size=512 --salt=12345678 \
- --key=testdata/key.pem --cert=testdata/cert.pem > /dev/null
- $(RUN_FSVERITY) digest $(FSVERITY) --hash=sha512 \
- --block-size=512 --salt=12345678 > /dev/null
- rm -f fsverity.sig
- @echo "All tests passed!"
+clean:
+ rm -f $(EXE) $(OBJ)
install:all
- install -d $(DESTDIR)$(LIBDIR)/pkgconfig $(DESTDIR)$(INCDIR) $(DESTDIR)$(BINDIR)
- install -m755 $(FSVERITY) $(DESTDIR)$(BINDIR)
- install -m644 libfsverity.a $(DESTDIR)$(LIBDIR)
- install -m755 libfsverity.so.$(SOVERSION) $(DESTDIR)$(LIBDIR)
- ln -sf libfsverity.so.$(SOVERSION) $(DESTDIR)$(LIBDIR)/libfsverity.so
- install -m644 include/libfsverity.h $(DESTDIR)$(INCDIR)
- sed -e "s|@PREFIX@|$(PREFIX)|" \
- -e "s|@LIBDIR@|$(LIBDIR)|" \
- -e "s|@INCDIR@|$(INCDIR)|" \
- lib/libfsverity.pc.in \
- > $(DESTDIR)$(LIBDIR)/pkgconfig/libfsverity.pc
- chmod 644 $(DESTDIR)$(LIBDIR)/pkgconfig/libfsverity.pc
-
-uninstall:
- rm -f $(DESTDIR)$(BINDIR)/$(FSVERITY)
- rm -f $(DESTDIR)$(LIBDIR)/libfsverity.a
- rm -f $(DESTDIR)$(LIBDIR)/libfsverity.so.$(SOVERSION)
- rm -f $(DESTDIR)$(LIBDIR)/libfsverity.so
- rm -f $(DESTDIR)$(LIBDIR)/pkgconfig/libfsverity.pc
- rm -f $(DESTDIR)$(INCDIR)/libfsverity.h
+ install -Dm755 -t $(DESTDIR)/bin $(EXE)
-help:
- @echo "Available targets:"
- @echo "------------------"
- @for target in $(DEFAULT_TARGETS) $(TEST_PROGRAMS) $(SPECIAL_TARGETS); \
- do \
- echo $$target; \
- done
-
-clean:
- rm -f $(DEFAULT_TARGETS) $(TEST_PROGRAMS) \
- lib/*.o programs/*.o .build-config fsverity.sig
+.PHONY: all clean install
diff --git a/NEWS.md b/NEWS.md
deleted file mode 100644
index 8745745..0000000
--- a/NEWS.md
+++ /dev/null
@@ -1,43 +0,0 @@
-# fsverity-utils release notes
-
-## Version 1.3
-
-* Added a `fsverity digest` subcommand.
-
-* Added `libfsverity_enable()` and `libfsverity_enable_with_sig()`.
-
-* Added basic support for Windows builds of `fsverity` using MinGW.
-
-* `fsverity` now defaults to 4096-byte blocks on all platforms.
-
-* libfsverity now will use SHA-256 with 4096-byte blocks if the
- `hash_algorithm` and `block_size` fields are left 0.
-
-* `make install` now installs a pkg-config file for libfsverity.
-
-* The Makefile now uses pkg-config to get the libcrypto build flags.
-
-* Fixed `make check` with `USE_SHARED_LIB=1`.
-
-## Version 1.2
-
-* Changed license from GPL to MIT.
-
-* Fixed build error when /bin/sh is dash.
-
-## Version 1.1
-
-* Split the file digest computation and signing functionality of the
- `fsverity` program into a library `libfsverity`. See `README.md`
- and `Makefile` for more details.
-
-* Improved the Makefile.
-
-* Added some tests. They can be run using `make check`. Also added
- `scripts/run-tests.sh` which does more extensive prerelease tests.
-
-* Lots of cleanups and other small improvements.
-
-## Version 1.0
-
-* First official release of fsverity-utils.
diff --git a/NOTICE b/NOTICE
new file mode 100644
index 0000000..d159169
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/README.md b/README.md
index 2b63488..8a72088 100644
--- a/README.md
+++ b/README.md
@@ -1,31 +1,21 @@
-# fsverity-utils
+# Introduction
-## Introduction
-
-This is fsverity-utils, a set of userspace utilities for fs-verity.
-fs-verity is a Linux kernel feature that does transparent on-demand
+This is `fsverity`, a userspace utility for fs-verity. fs-verity is a
+Linux kernel feature that does transparent on-demand
integrity/authenticity verification of the contents of read-only
files, using a hidden Merkle tree (hash tree) associated with the
-file. It is similar to dm-verity, but implemented at the file level
-rather than at the block device level. See the [kernel
-documentation](https://www.kernel.org/doc/html/latest/filesystems/fsverity.html)
-for more information about fs-verity.
-
-fs-verity is supported by the ext4 and f2fs filesystems in Linux v5.4
-and later when configured with `CONFIG_FS_VERITY=y` and when the
-`verity` filesystem feature flag has been enabled. Other filesystems
-might add support for fs-verity in the future.
+file. The mechanism is similar to dm-verity, but implemented at the
+file level rather than at the block device level. The `fsverity`
+utility allows you to set up fs-verity protected files.
-fsverity-utils currently contains just one program, `fsverity`. The
-`fsverity` program allows you to set up fs-verity protected files.
-In addition, the file digest computation and signing functionality of
-`fsverity` is optionally exposed through a C library `libfsverity`.
-See `libfsverity.h` for the API of this library.
+fs-verity will initially be supported by the ext4 and f2fs
+filesystems, but it may later be supported by other filesystems too.
-## Building and installing
+# Building and installing
-fsverity-utils uses the OpenSSL library, so you first must install the
-needed development files. For example, on Debian-based systems, run:
+The `fsverity` utility uses the OpenSSL library, so you first must
+install the needed development files. For example, on Debian-based
+systems, run:
```bash
sudo apt-get install libssl-dev
@@ -33,37 +23,16 @@ needed development files. For example, on Debian-based systems, run:
OpenSSL must be version 1.0.0 or later.
-Then, to build and install fsverity-utils:
+Then, to build and install:
```bash
make
sudo make install
```
-By default, the following targets are built and installed: the program
-`fsverity`, the static library `libfsverity.a`, and the shared library
-`libfsverity.so`. You can also run `make check` to build and run the
-tests, or `make help` to display all available build targets.
-
-By default, `fsverity` is statically linked to `libfsverity`. You can
-use `make USE_SHARED_LIB=1` to use dynamic linking instead.
-
-See the `Makefile` for other supported build and installation options.
-
-### Building on Windows
-
-There is minimal support for building Windows executables using MinGW.
-```bash
- make CC=x86_64-w64-mingw32-gcc
-```
-
-`fsverity.exe` will be built, and it supports the `digest` and `sign` commands.
-
-A Windows build of OpenSSL/libcrypto needs to be available.
-
-## Examples
+# Examples
-### Basic use
+## Basic use
```bash
mkfs.ext4 -O verity /dev/vdc
@@ -72,19 +41,19 @@ A Windows build of OpenSSL/libcrypto needs to be available.
# Create a test file
head -c 1000000 /dev/urandom > file
- sha256sum file
+ md5sum file
# Enable verity on the file
fsverity enable file
- # Show the verity file digest
+ # Show the verity file measurement
fsverity measure file
# File should still be readable as usual. However, all data read
# is now transparently checked against a hidden Merkle tree, whose
- # root hash is incorporated into the verity file digest. Reads of
- # any corrupted parts of the data will fail.
- sha256sum file
+ # root hash is incorporated into the verity file measurement.
+ # Reads of any corrupted parts of the data will fail.
+ md5sum file
```
Note that in the above example, the file isn't signed. Therefore, to
@@ -92,13 +61,13 @@ get any authenticity protection (as opposed to just integrity
protection), the output of `fsverity measure` needs to be compared
against a trusted value.
-### Using builtin signatures
+## Using builtin signatures
With `CONFIG_FS_VERITY_BUILTIN_SIGNATURES=y`, the filesystem supports
-automatically verifying a signed file digest that has been included in
-the verity metadata. The signature is verified against the set of
-X.509 certificates that have been loaded into the ".fs-verity" kernel
-keyring. Here's an example:
+automatically verifying a signed file measurement that has been
+included in the verity metadata. The signature is verified against
+the set of X.509 certificates that have been loaded into the
+".fs-verity" kernel keyring. Here's an example:
```bash
# Generate a new certificate and private key:
@@ -118,15 +87,11 @@ keyring. Here's an example:
sysctl fs.verity.require_signatures=1
# Now set up fs-verity on a test file:
- sha256sum file
+ md5sum file
fsverity sign file file.sig --key=key.pem --cert=cert.pem
fsverity enable file --signature=file.sig
rm -f file.sig
- sha256sum file
-
- # The digest to be signed can also be printed separately, hex
- # encoded, in case the integrated signing cannot be used:
- fsverity digest file --compact --for-builtin-sig | tr -d '\n' | xxd -p -r | openssl smime -sign -in /dev/stdin ...
+ md5sum file
```
By default, it's not required that verity files have a signature.
@@ -138,28 +103,25 @@ Note: applications generally still need to check whether the file
they're accessing really is a verity file, since an attacker could
replace a verity file with a regular one.
-### With IMA
+## With IMA
IMA support for fs-verity is planned.
-## Notices
+# Notices
-fsverity-utils is provided under the terms of the MIT license. A copy
-of this license can be found in the file named [LICENSE](LICENSE).
+This project is provided under the terms of the GNU General Public
+License, version 2; or at your option, any later version. A copy of the
+GPLv2 can be found in the file named [COPYING](COPYING).
-Send questions and bug reports to linux-fscrypt@vger.kernel.org.
+Permission to link to OpenSSL (libcrypto) is granted.
-Signed release tarballs for fsverity-utils can be found on
-[kernel.org](https://kernel.org/pub/linux/kernel/people/ebiggers/fsverity-utils/).
+Send questions and bug reports to linux-fscrypt@vger.kernel.org.
-## Contributing
+# Submitting patches
-Send patches to linux-fscrypt@vger.kernel.org with the additional tag
-`fsverity-utils` in the subject, i.e. `[fsverity-utils PATCH]`.
-Patches should follow the Linux kernel's coding style. A
-`.clang-format` file is provided to approximate this coding style;
-consider using `git clang-format`. Additionally, like the Linux
-kernel itself, patches require the following "sign-off" procedure:
+Send patches to linux-fscrypt@vger.kernel.org. Patches should follow
+the Linux kernel's coding style. Additionally, like the Linux kernel
+itself, patches require the following "sign-off" procedure:
The sign-off is a simple line at the end of the explanation for the
patch, which certifies that you wrote it or otherwise have the right
diff --git a/programs/cmd_enable.c b/cmd_enable.c
index 14c3c17..1646299 100644
--- a/programs/cmd_enable.c
+++ b/cmd_enable.c
@@ -1,19 +1,48 @@
-// SPDX-License-Identifier: MIT
+// SPDX-License-Identifier: GPL-2.0+
/*
* The 'fsverity enable' command
*
- * Copyright 2018 Google LLC
+ * Copyright (C) 2018 Google LLC
*
- * Use of this source code is governed by an MIT-style
- * license that can be found in the LICENSE file or at
- * https://opensource.org/licenses/MIT.
+ * Written by Eric Biggers.
*/
-#include "fsverity.h"
-
#include <fcntl.h>
#include <getopt.h>
#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+
+#include "commands.h"
+#include "fsverity_uapi.h"
+#include "hash_algs.h"
+
+static bool parse_hash_alg_option(const char *arg, u32 *alg_ptr)
+{
+ char *end;
+ unsigned long n = strtoul(arg, &end, 10);
+ const struct fsverity_hash_alg *alg;
+
+ if (*alg_ptr != 0) {
+ error_msg("--hash-alg can only be specified once");
+ return false;
+ }
+
+ /* Specified by number? */
+ if (n > 0 && n < INT32_MAX && *end == '\0') {
+ *alg_ptr = n;
+ return true;
+ }
+
+ /* Specified by name? */
+ alg = find_hash_alg_by_name(arg);
+ if (alg != NULL) {
+ *alg_ptr = alg - fsverity_hash_algs;
+ return true;
+ }
+ return false;
+}
static bool read_signature(const char *filename, u8 **sig_ret,
u32 *sig_size_ret)
@@ -48,6 +77,13 @@ out:
return ok;
}
+enum {
+ OPT_HASH_ALG,
+ OPT_BLOCK_SIZE,
+ OPT_SALT,
+ OPT_SIGNATURE,
+};
+
static const struct option longopts[] = {
{"hash-alg", required_argument, NULL, OPT_HASH_ALG},
{"block-size", required_argument, NULL, OPT_BLOCK_SIZE},
@@ -60,9 +96,9 @@ static const struct option longopts[] = {
int fsverity_cmd_enable(const struct fsverity_command *cmd,
int argc, char *argv[])
{
- struct libfsverity_merkle_tree_params tree_params = { .version = 1 };
+ struct fsverity_enable_arg arg = { .version = 1 };
+ u8 *salt = NULL;
u8 *sig = NULL;
- u32 sig_size = 0;
struct filedes file;
int status;
int c;
@@ -70,18 +106,26 @@ int fsverity_cmd_enable(const struct fsverity_command *cmd,
while ((c = getopt_long(argc, argv, "", longopts, NULL)) != -1) {
switch (c) {
case OPT_HASH_ALG:
+ if (!parse_hash_alg_option(optarg, &arg.hash_algorithm))
+ goto out_usage;
+ break;
case OPT_BLOCK_SIZE:
+ if (!parse_block_size_option(optarg, &arg.block_size))
+ goto out_usage;
+ break;
case OPT_SALT:
- if (!parse_tree_param(c, optarg, &tree_params))
+ if (!parse_salt_option(optarg, &salt, &arg.salt_size))
goto out_usage;
+ arg.salt_ptr = (uintptr_t)salt;
break;
case OPT_SIGNATURE:
if (sig != NULL) {
error_msg("--signature can only be specified once");
goto out_usage;
}
- if (!read_signature(optarg, &sig, &sig_size))
+ if (!read_signature(optarg, &sig, &arg.sig_size))
goto out_err;
+ arg.sig_ptr = (uintptr_t)sig;
break;
default:
goto out_usage;
@@ -94,10 +138,15 @@ int fsverity_cmd_enable(const struct fsverity_command *cmd,
if (argc != 1)
goto out_usage;
+ if (arg.hash_algorithm == 0)
+ arg.hash_algorithm = FS_VERITY_HASH_ALG_DEFAULT;
+
+ if (arg.block_size == 0)
+ arg.block_size = get_default_block_size();
+
if (!open_file(&file, argv[0], O_RDONLY, 0))
goto out_err;
-
- if (libfsverity_enable_with_sig(file.fd, &tree_params, sig, sig_size)) {
+ if (ioctl(file.fd, FS_IOC_ENABLE_VERITY, &arg) != 0) {
error_msg_errno("FS_IOC_ENABLE_VERITY failed on '%s'",
file.name);
filedes_close(&file);
@@ -108,7 +157,7 @@ int fsverity_cmd_enable(const struct fsverity_command *cmd,
status = 0;
out:
- destroy_tree_params(&tree_params);
+ free(salt);
free(sig);
return status;
diff --git a/programs/cmd_measure.c b/cmd_measure.c
index d78969c..574e3ca 100644
--- a/programs/cmd_measure.c
+++ b/cmd_measure.c
@@ -1,26 +1,28 @@
-// SPDX-License-Identifier: MIT
+// SPDX-License-Identifier: GPL-2.0+
/*
* The 'fsverity measure' command
*
- * Copyright 2018 Google LLC
+ * Copyright (C) 2018 Google LLC
*
- * Use of this source code is governed by an MIT-style
- * license that can be found in the LICENSE file or at
- * https://opensource.org/licenses/MIT.
+ * Written by Eric Biggers.
*/
-#include "fsverity.h"
-
#include <fcntl.h>
+#include <stdlib.h>
#include <sys/ioctl.h>
-/* Display the fs-verity digest of the given verity file(s). */
+#include "commands.h"
+#include "fsverity_uapi.h"
+#include "hash_algs.h"
+
+/* Display the measurement of the given verity file(s). */
int fsverity_cmd_measure(const struct fsverity_command *cmd,
int argc, char *argv[])
{
struct fsverity_digest *d = NULL;
struct filedes file;
char digest_hex[FS_VERITY_MAX_DIGEST_SIZE * 2 + 1];
+ const struct fsverity_hash_alg *hash_alg;
char _hash_alg_name[32];
const char *hash_alg_name;
int status;
@@ -46,8 +48,10 @@ int fsverity_cmd_measure(const struct fsverity_command *cmd,
ASSERT(d->digest_size <= FS_VERITY_MAX_DIGEST_SIZE);
bin2hex(d->digest, d->digest_size, digest_hex);
- hash_alg_name = libfsverity_get_hash_name(d->digest_algorithm);
- if (!hash_alg_name) {
+ hash_alg = find_hash_alg_by_num(d->digest_algorithm);
+ if (hash_alg) {
+ hash_alg_name = hash_alg->name;
+ } else {
sprintf(_hash_alg_name, "ALG_%u", d->digest_algorithm);
hash_alg_name = _hash_alg_name;
}
diff --git a/cmd_sign.c b/cmd_sign.c
new file mode 100644
index 0000000..dcb37ce
--- /dev/null
+++ b/cmd_sign.c
@@ -0,0 +1,635 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * The 'fsverity sign' command
+ *
+ * Copyright (C) 2018 Google LLC
+ *
+ * Written by Eric Biggers.
+ */
+
+#include <fcntl.h>
+#include <getopt.h>
+#include <limits.h>
+#include <openssl/bio.h>
+#include <openssl/err.h>
+#include <openssl/pem.h>
+#include <openssl/pkcs7.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "commands.h"
+#include "fsverity_uapi.h"
+#include "hash_algs.h"
+
+/*
+ * Merkle tree properties. The file measurement is the hash of this structure
+ * excluding the signature and with the sig_size field set to 0.
+ */
+struct fsverity_descriptor {
+ __u8 version; /* must be 1 */
+ __u8 hash_algorithm; /* Merkle tree hash algorithm */
+ __u8 log_blocksize; /* log2 of size of data and tree blocks */
+ __u8 salt_size; /* size of salt in bytes; 0 if none */
+ __le32 sig_size; /* size of signature in bytes; 0 if none */
+ __le64 data_size; /* size of file the Merkle tree is built over */
+ __u8 root_hash[64]; /* Merkle tree root hash */
+ __u8 salt[32]; /* salt prepended to each hashed block */
+ __u8 __reserved[144]; /* must be 0's */
+ __u8 signature[]; /* optional PKCS#7 signature */
+};
+
+/*
+ * Format in which verity file measurements are signed. This is the same as
+ * 'struct fsverity_digest', except here some magic bytes are prepended to
+ * provide some context about what is being signed in case the same key is used
+ * for non-fsverity purposes, and here the fields have fixed endianness.
+ */
+struct fsverity_signed_digest {
+ char magic[8]; /* must be "FSVerity" */
+ __le16 digest_algorithm;
+ __le16 digest_size;
+ __u8 digest[];
+};
+
+static void __printf(1, 2) __cold
+error_msg_openssl(const char *format, ...)
+{
+ va_list va;
+
+ va_start(va, format);
+ do_error_msg(format, va, 0);
+ va_end(va);
+
+ if (ERR_peek_error() == 0)
+ return;
+
+ fprintf(stderr, "OpenSSL library errors:\n");
+ ERR_print_errors_fp(stderr);
+}
+
+/* Read a PEM PKCS#8 formatted private key */
+static EVP_PKEY *read_private_key(const char *keyfile)
+{
+ BIO *bio;
+ EVP_PKEY *pkey;
+
+ bio = BIO_new_file(keyfile, "r");
+ if (!bio) {
+ error_msg_openssl("can't open '%s' for reading", keyfile);
+ return NULL;
+ }
+
+ pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
+ if (!pkey) {
+ error_msg_openssl("Failed to parse private key file '%s'.\n"
+ " Note: it must be in PEM PKCS#8 format.",
+ keyfile);
+ }
+ BIO_free(bio);
+ return pkey;
+}
+
+/* Read a PEM X.509 formatted certificate */
+static X509 *read_certificate(const char *certfile)
+{
+ BIO *bio;
+ X509 *cert;
+
+ bio = BIO_new_file(certfile, "r");
+ if (!bio) {
+ error_msg_openssl("can't open '%s' for reading", certfile);
+ return NULL;
+ }
+ cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
+ if (!cert) {
+ error_msg_openssl("Failed to parse X.509 certificate file '%s'.\n"
+ " Note: it must be in PEM format.",
+ certfile);
+ }
+ BIO_free(bio);
+ return cert;
+}
+
+#ifdef OPENSSL_IS_BORINGSSL
+
+static bool sign_pkcs7(const void *data_to_sign, size_t data_size,
+ EVP_PKEY *pkey, X509 *cert, const EVP_MD *md,
+ u8 **sig_ret, u32 *sig_size_ret)
+{
+ CBB out, outer_seq, wrapped_seq, seq, digest_algos_set, digest_algo,
+ null, content_info, issuer_and_serial, signer_infos,
+ signer_info, sign_algo, signature;
+ EVP_MD_CTX md_ctx;
+ u8 *name_der = NULL, *sig = NULL, *pkcs7_data = NULL;
+ size_t pkcs7_data_len, sig_len;
+ int name_der_len, sig_nid;
+ bool ok = false;
+
+ EVP_MD_CTX_init(&md_ctx);
+ BIGNUM *serial = ASN1_INTEGER_to_BN(X509_get_serialNumber(cert), NULL);
+
+ if (!CBB_init(&out, 1024)) {
+ error_msg("out of memory");
+ goto out;
+ }
+
+ name_der_len = i2d_X509_NAME(X509_get_subject_name(cert), &name_der);
+ if (name_der_len < 0) {
+ error_msg_openssl("i2d_X509_NAME failed");
+ goto out;
+ }
+
+ if (!EVP_DigestSignInit(&md_ctx, NULL, md, NULL, pkey)) {
+ error_msg_openssl("EVP_DigestSignInit failed");
+ goto out;
+ }
+
+ sig_len = EVP_PKEY_size(pkey);
+ sig = xmalloc(sig_len);
+ if (!EVP_DigestSign(&md_ctx, sig, &sig_len, data_to_sign, data_size)) {
+ error_msg_openssl("EVP_DigestSign failed");
+ goto out;
+ }
+
+ sig_nid = EVP_PKEY_id(pkey);
+ /* To mirror OpenSSL behaviour, always use |NID_rsaEncryption| with RSA
+ * rather than the combined hash+pkey NID. */
+ if (sig_nid != NID_rsaEncryption) {
+ OBJ_find_sigid_by_algs(&sig_nid, EVP_MD_type(md),
+ EVP_PKEY_id(pkey));
+ }
+
+ // See https://tools.ietf.org/html/rfc2315#section-7
+ if (!CBB_add_asn1(&out, &outer_seq, CBS_ASN1_SEQUENCE) ||
+ !OBJ_nid2cbb(&outer_seq, NID_pkcs7_signed) ||
+ !CBB_add_asn1(&outer_seq, &wrapped_seq, CBS_ASN1_CONTEXT_SPECIFIC |
+ CBS_ASN1_CONSTRUCTED | 0) ||
+ // See https://tools.ietf.org/html/rfc2315#section-9.1
+ !CBB_add_asn1(&wrapped_seq, &seq, CBS_ASN1_SEQUENCE) ||
+ !CBB_add_asn1_uint64(&seq, 1 /* version */) ||
+ !CBB_add_asn1(&seq, &digest_algos_set, CBS_ASN1_SET) ||
+ !CBB_add_asn1(&digest_algos_set, &digest_algo, CBS_ASN1_SEQUENCE) ||
+ !OBJ_nid2cbb(&digest_algo, EVP_MD_type(md)) ||
+ !CBB_add_asn1(&digest_algo, &null, CBS_ASN1_NULL) ||
+ !CBB_add_asn1(&seq, &content_info, CBS_ASN1_SEQUENCE) ||
+ !OBJ_nid2cbb(&content_info, NID_pkcs7_data) ||
+ !CBB_add_asn1(&seq, &signer_infos, CBS_ASN1_SET) ||
+ !CBB_add_asn1(&signer_infos, &signer_info, CBS_ASN1_SEQUENCE) ||
+ !CBB_add_asn1_uint64(&signer_info, 1 /* version */) ||
+ !CBB_add_asn1(&signer_info, &issuer_and_serial,
+ CBS_ASN1_SEQUENCE) ||
+ !CBB_add_bytes(&issuer_and_serial, name_der, name_der_len) ||
+ !BN_marshal_asn1(&issuer_and_serial, serial) ||
+ !CBB_add_asn1(&signer_info, &digest_algo, CBS_ASN1_SEQUENCE) ||
+ !OBJ_nid2cbb(&digest_algo, EVP_MD_type(md)) ||
+ !CBB_add_asn1(&digest_algo, &null, CBS_ASN1_NULL) ||
+ !CBB_add_asn1(&signer_info, &sign_algo, CBS_ASN1_SEQUENCE) ||
+ !OBJ_nid2cbb(&sign_algo, sig_nid) ||
+ !CBB_add_asn1(&sign_algo, &null, CBS_ASN1_NULL) ||
+ !CBB_add_asn1(&signer_info, &signature, CBS_ASN1_OCTETSTRING) ||
+ !CBB_add_bytes(&signature, sig, sig_len) ||
+ !CBB_finish(&out, &pkcs7_data, &pkcs7_data_len)) {
+ error_msg_openssl("failed to construct PKCS#7 data");
+ goto out;
+ }
+
+ *sig_ret = xmemdup(pkcs7_data, pkcs7_data_len);
+ *sig_size_ret = pkcs7_data_len;
+ ok = true;
+out:
+ BN_free(serial);
+ EVP_MD_CTX_cleanup(&md_ctx);
+ CBB_cleanup(&out);
+ free(sig);
+ OPENSSL_free(name_der);
+ OPENSSL_free(pkcs7_data);
+ return ok;
+}
+
+#else /* OPENSSL_IS_BORINGSSL */
+
+static BIO *new_mem_buf(const void *buf, size_t size)
+{
+ BIO *bio;
+
+ ASSERT(size <= INT_MAX);
+ /*
+ * Prior to OpenSSL 1.1.0, BIO_new_mem_buf() took a non-const pointer,
+ * despite still marking the resulting bio as read-only. So cast away
+ * the const to avoid a compiler warning with older OpenSSL versions.
+ */
+ bio = BIO_new_mem_buf((void *)buf, size);
+ if (!bio)
+ error_msg_openssl("out of memory");
+ return bio;
+}
+
+static bool sign_pkcs7(const void *data_to_sign, size_t data_size,
+ EVP_PKEY *pkey, X509 *cert, const EVP_MD *md,
+ u8 **sig_ret, u32 *sig_size_ret)
+{
+ /*
+ * PKCS#7 signing flags:
+ *
+ * - PKCS7_BINARY signing binary data, so skip MIME translation
+ *
+ * - PKCS7_DETACHED omit the signed data (include signature only)
+ *
+ * - PKCS7_NOATTR omit extra authenticated attributes, such as
+ * SMIMECapabilities
+ *
+ * - PKCS7_NOCERTS omit the signer's certificate
+ *
+ * - PKCS7_PARTIAL PKCS7_sign() creates a handle only, then
+ * PKCS7_sign_add_signer() can add a signer later.
+ * This is necessary to change the message digest
+ * algorithm from the default of SHA-1. Requires
+ * OpenSSL 1.0.0 or later.
+ */
+ int pkcs7_flags = PKCS7_BINARY | PKCS7_DETACHED | PKCS7_NOATTR |
+ PKCS7_NOCERTS | PKCS7_PARTIAL;
+ u8 *sig;
+ u32 sig_size;
+ BIO *bio = NULL;
+ PKCS7 *p7 = NULL;
+ bool ok = false;
+
+ bio = new_mem_buf(data_to_sign, data_size);
+ if (!bio)
+ goto out;
+
+ p7 = PKCS7_sign(NULL, NULL, NULL, bio, pkcs7_flags);
+ if (!p7) {
+ error_msg_openssl("failed to initialize PKCS#7 signature object");
+ goto out;
+ }
+
+ if (!PKCS7_sign_add_signer(p7, cert, pkey, md, pkcs7_flags)) {
+ error_msg_openssl("failed to add signer to PKCS#7 signature object");
+ goto out;
+ }
+
+ if (PKCS7_final(p7, bio, pkcs7_flags) != 1) {
+ error_msg_openssl("failed to finalize PKCS#7 signature");
+ goto out;
+ }
+
+ BIO_free(bio);
+ bio = BIO_new(BIO_s_mem());
+ if (!bio) {
+ error_msg_openssl("out of memory");
+ goto out;
+ }
+
+ if (i2d_PKCS7_bio(bio, p7) != 1) {
+ error_msg_openssl("failed to DER-encode PKCS#7 signature object");
+ goto out;
+ }
+
+ sig_size = BIO_get_mem_data(bio, &sig);
+ *sig_ret = xmemdup(sig, sig_size);
+ *sig_size_ret = sig_size;
+ ok = true;
+out:
+ PKCS7_free(p7);
+ BIO_free(bio);
+ return ok;
+}
+
+#endif /* !OPENSSL_IS_BORINGSSL */
+
+/*
+ * Sign the specified @data_to_sign of length @data_size bytes using the private
+ * key in @keyfile, the certificate in @certfile, and the hash algorithm
+ * @hash_alg. Returns the DER-formatted PKCS#7 signature in @sig_ret and
+ * @sig_size_ret.
+ */
+static bool sign_data(const void *data_to_sign, size_t data_size,
+ const char *keyfile, const char *certfile,
+ const struct fsverity_hash_alg *hash_alg,
+ u8 **sig_ret, u32 *sig_size_ret)
+{
+ EVP_PKEY *pkey = NULL;
+ X509 *cert = NULL;
+ const EVP_MD *md;
+ bool ok = false;
+
+ pkey = read_private_key(keyfile);
+ if (!pkey)
+ goto out;
+
+ cert = read_certificate(certfile);
+ if (!cert)
+ goto out;
+
+ OpenSSL_add_all_digests();
+ md = EVP_get_digestbyname(hash_alg->name);
+ if (!md) {
+ fprintf(stderr,
+ "Warning: '%s' algorithm not found in OpenSSL library.\n"
+ " Falling back to SHA-256 signature.\n",
+ hash_alg->name);
+ md = EVP_sha256();
+ }
+
+ ok = sign_pkcs7(data_to_sign, data_size, pkey, cert, md,
+ sig_ret, sig_size_ret);
+out:
+ EVP_PKEY_free(pkey);
+ X509_free(cert);
+ return ok;
+}
+
+static bool write_signature(const char *filename, const u8 *sig, u32 sig_size)
+{
+ struct filedes file;
+ bool ok;
+
+ if (!open_file(&file, filename, O_WRONLY|O_CREAT|O_TRUNC, 0644))
+ return false;
+ ok = full_write(&file, sig, sig_size);
+ ok &= filedes_close(&file);
+ return ok;
+}
+
+#define FS_VERITY_MAX_LEVELS 64
+
+struct block_buffer {
+ u32 filled;
+ u8 *data;
+};
+
+/*
+ * Hash a block, writing the result to the next level's pending block buffer.
+ * Returns true if the next level's block became full, else false.
+ */
+static bool hash_one_block(struct hash_ctx *hash, struct block_buffer *cur,
+ u32 block_size, const u8 *salt, u32 salt_size)
+{
+ struct block_buffer *next = cur + 1;
+
+ /* Zero-pad the block if it's shorter than block_size. */
+ memset(&cur->data[cur->filled], 0, block_size - cur->filled);
+
+ hash_init(hash);
+ hash_update(hash, salt, salt_size);
+ hash_update(hash, cur->data, block_size);
+ hash_final(hash, &next->data[next->filled]);
+
+ next->filled += hash->alg->digest_size;
+ cur->filled = 0;
+
+ return next->filled + hash->alg->digest_size > block_size;
+}
+
+/*
+ * Compute the file's Merkle tree root hash using the given hash algorithm,
+ * block size, and salt.
+ */
+static bool compute_root_hash(struct filedes *file, u64 file_size,
+ struct hash_ctx *hash, u32 block_size,
+ const u8 *salt, u32 salt_size, u8 *root_hash)
+{
+ const u32 hashes_per_block = block_size / hash->alg->digest_size;
+ const u32 padded_salt_size = roundup(salt_size, hash->alg->block_size);
+ u8 *padded_salt = xzalloc(padded_salt_size);
+ u64 blocks;
+ int num_levels = 0;
+ int level;
+ struct block_buffer _buffers[1 + FS_VERITY_MAX_LEVELS + 1] = {};
+ struct block_buffer *buffers = &_buffers[1];
+ u64 offset;
+ bool ok = false;
+
+ if (salt_size != 0)
+ memcpy(padded_salt, salt, salt_size);
+
+ /* Compute number of levels */
+ for (blocks = DIV_ROUND_UP(file_size, block_size); blocks > 1;
+ blocks = DIV_ROUND_UP(blocks, hashes_per_block)) {
+ ASSERT(num_levels < FS_VERITY_MAX_LEVELS);
+ num_levels++;
+ }
+
+ /*
+ * Allocate the block buffers. Buffer "-1" is for data blocks.
+ * Buffers 0 <= level < num_levels are for the actual tree levels.
+ * Buffer 'num_levels' is for the root hash.
+ */
+ for (level = -1; level < num_levels; level++)
+ buffers[level].data = xmalloc(block_size);
+ buffers[num_levels].data = root_hash;
+
+ /* Hash each data block, also hashing the tree blocks as they fill up */
+ for (offset = 0; offset < file_size; offset += block_size) {
+ buffers[-1].filled = min(block_size, file_size - offset);
+
+ if (!full_read(file, buffers[-1].data, buffers[-1].filled))
+ goto out;
+
+ level = -1;
+ while (hash_one_block(hash, &buffers[level], block_size,
+ padded_salt, padded_salt_size)) {
+ level++;
+ ASSERT(level < num_levels);
+ }
+ }
+ /* Finish all nonempty pending tree blocks */
+ for (level = 0; level < num_levels; level++) {
+ if (buffers[level].filled != 0)
+ hash_one_block(hash, &buffers[level], block_size,
+ padded_salt, padded_salt_size);
+ }
+
+ /* Root hash was filled by the last call to hash_one_block() */
+ ASSERT(buffers[num_levels].filled == hash->alg->digest_size);
+ ok = true;
+out:
+ for (level = -1; level < num_levels; level++)
+ free(buffers[level].data);
+ free(padded_salt);
+ return ok;
+}
+
+/*
+ * Compute the fs-verity measurement of the given file.
+ *
+ * The fs-verity measurement is the hash of the fsverity_descriptor, which
+ * contains the Merkle tree properties including the root hash.
+ */
+static bool compute_file_measurement(const char *filename,
+ const struct fsverity_hash_alg *hash_alg,
+ u32 block_size, const u8 *salt,
+ u32 salt_size, u8 *measurement)
+{
+ struct filedes file = { .fd = -1 };
+ struct hash_ctx *hash = hash_create(hash_alg);
+ u64 file_size;
+ struct fsverity_descriptor desc;
+ bool ok = false;
+
+ if (!open_file(&file, filename, O_RDONLY, 0))
+ goto out;
+
+ if (!get_file_size(&file, &file_size))
+ goto out;
+
+ memset(&desc, 0, sizeof(desc));
+ desc.version = 1;
+ desc.hash_algorithm = hash_alg - fsverity_hash_algs;
+
+ ASSERT(is_power_of_2(block_size));
+ desc.log_blocksize = ilog2(block_size);
+
+ if (salt_size != 0) {
+ if (salt_size > sizeof(desc.salt)) {
+ error_msg("Salt too long (got %u bytes; max is %zu bytes)",
+ salt_size, sizeof(desc.salt));
+ goto out;
+ }
+ memcpy(desc.salt, salt, salt_size);
+ desc.salt_size = salt_size;
+ }
+
+ desc.data_size = cpu_to_le64(file_size);
+
+ /* Root hash of empty file is all 0's */
+ if (file_size != 0 &&
+ !compute_root_hash(&file, file_size, hash, block_size, salt,
+ salt_size, desc.root_hash))
+ goto out;
+
+ hash_full(hash, &desc, sizeof(desc), measurement);
+ ok = true;
+out:
+ filedes_close(&file);
+ hash_free(hash);
+ return ok;
+}
+
+enum {
+ OPT_HASH_ALG,
+ OPT_BLOCK_SIZE,
+ OPT_SALT,
+ OPT_KEY,
+ OPT_CERT,
+};
+
+static const struct option longopts[] = {
+ {"hash-alg", required_argument, NULL, OPT_HASH_ALG},
+ {"block-size", required_argument, NULL, OPT_BLOCK_SIZE},
+ {"salt", required_argument, NULL, OPT_SALT},
+ {"key", required_argument, NULL, OPT_KEY},
+ {"cert", required_argument, NULL, OPT_CERT},
+ {NULL, 0, NULL, 0}
+};
+
+/* Sign a file for fs-verity by computing its measurement, then signing it. */
+int fsverity_cmd_sign(const struct fsverity_command *cmd,
+ int argc, char *argv[])
+{
+ const struct fsverity_hash_alg *hash_alg = NULL;
+ u32 block_size = 0;
+ u8 *salt = NULL;
+ u32 salt_size = 0;
+ const char *keyfile = NULL;
+ const char *certfile = NULL;
+ struct fsverity_signed_digest *digest = NULL;
+ char digest_hex[FS_VERITY_MAX_DIGEST_SIZE * 2 + 1];
+ u8 *sig = NULL;
+ u32 sig_size;
+ int status;
+ int c;
+
+ while ((c = getopt_long(argc, argv, "", longopts, NULL)) != -1) {
+ switch (c) {
+ case OPT_HASH_ALG:
+ if (hash_alg != NULL) {
+ error_msg("--hash-alg can only be specified once");
+ goto out_usage;
+ }
+ hash_alg = find_hash_alg_by_name(optarg);
+ if (hash_alg == NULL)
+ goto out_usage;
+ break;
+ case OPT_BLOCK_SIZE:
+ if (!parse_block_size_option(optarg, &block_size))
+ goto out_usage;
+ break;
+ case OPT_SALT:
+ if (!parse_salt_option(optarg, &salt, &salt_size))
+ goto out_usage;
+ break;
+ case OPT_KEY:
+ if (keyfile != NULL) {
+ error_msg("--key can only be specified once");
+ goto out_usage;
+ }
+ keyfile = optarg;
+ break;
+ case OPT_CERT:
+ if (certfile != NULL) {
+ error_msg("--cert can only be specified once");
+ goto out_usage;
+ }
+ certfile = optarg;
+ break;
+ default:
+ goto out_usage;
+ }
+ }
+
+ argv += optind;
+ argc -= optind;
+
+ if (argc != 2)
+ goto out_usage;
+
+ if (hash_alg == NULL)
+ hash_alg = &fsverity_hash_algs[FS_VERITY_HASH_ALG_DEFAULT];
+
+ if (block_size == 0)
+ block_size = get_default_block_size();
+
+ if (keyfile == NULL) {
+ error_msg("Missing --key argument");
+ goto out_usage;
+ }
+ if (certfile == NULL)
+ certfile = keyfile;
+
+ digest = xzalloc(sizeof(*digest) + hash_alg->digest_size);
+ memcpy(digest->magic, "FSVerity", 8);
+ digest->digest_algorithm = cpu_to_le16(hash_alg - fsverity_hash_algs);
+ digest->digest_size = cpu_to_le16(hash_alg->digest_size);
+
+ if (!compute_file_measurement(argv[0], hash_alg, block_size,
+ salt, salt_size, digest->digest))
+ goto out_err;
+
+ if (!sign_data(digest, sizeof(*digest) + hash_alg->digest_size,
+ keyfile, certfile, hash_alg, &sig, &sig_size))
+ goto out_err;
+
+ if (!write_signature(argv[1], sig, sig_size))
+ goto out_err;
+
+ bin2hex(digest->digest, hash_alg->digest_size, digest_hex);
+ printf("Signed file '%s' (%s:%s)\n", argv[0], hash_alg->name,
+ digest_hex);
+ status = 0;
+out:
+ free(salt);
+ free(digest);
+ free(sig);
+ return status;
+
+out_err:
+ status = 1;
+ goto out;
+
+out_usage:
+ usage(cmd, stderr);
+ status = 2;
+ goto out;
+}
diff --git a/commands.h b/commands.h
new file mode 100644
index 0000000..98f9745
--- /dev/null
+++ b/commands.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+#ifndef COMMANDS_H
+#define COMMANDS_H
+
+#include <stdio.h>
+
+#include "util.h"
+
+struct fsverity_command;
+
+void usage(const struct fsverity_command *cmd, FILE *fp);
+
+int fsverity_cmd_enable(const struct fsverity_command *cmd,
+ int argc, char *argv[]);
+int fsverity_cmd_measure(const struct fsverity_command *cmd,
+ int argc, char *argv[]);
+int fsverity_cmd_sign(const struct fsverity_command *cmd,
+ int argc, char *argv[]);
+
+bool parse_block_size_option(const char *arg, u32 *size_ptr);
+u32 get_default_block_size(void);
+bool parse_salt_option(const char *arg, u8 **salt_ptr, u32 *salt_size_ptr);
+
+#endif /* COMMANDS_H */
diff --git a/common/fsverity_uapi.h b/common/fsverity_uapi.h
deleted file mode 100644
index a739c9a..0000000
--- a/common/fsverity_uapi.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-/*
- * fs-verity user API
- *
- * These ioctls can be used on filesystems that support fs-verity. See the
- * "User API" section of Documentation/filesystems/fsverity.rst.
- *
- * Copyright 2019 Google LLC
- */
-#ifndef _UAPI_LINUX_FSVERITY_H
-#define _UAPI_LINUX_FSVERITY_H
-
-#ifndef _WIN32
-#include <linux/ioctl.h>
-#include <linux/types.h>
-#endif /* !_WIN32 */
-
-#define FS_VERITY_HASH_ALG_SHA256 1
-#define FS_VERITY_HASH_ALG_SHA512 2
-
-struct fsverity_enable_arg {
- __u32 version;
- __u32 hash_algorithm;
- __u32 block_size;
- __u32 salt_size;
- __u64 salt_ptr;
- __u32 sig_size;
- __u32 __reserved1;
- __u64 sig_ptr;
- __u64 __reserved2[11];
-};
-
-struct fsverity_digest {
- __u16 digest_algorithm;
- __u16 digest_size; /* input/output */
- __u8 digest[];
-};
-
-/*
- * Struct containing a file's Merkle tree properties. The fs-verity file digest
- * is the hash of this struct. A userspace program needs this struct only if it
- * needs to compute fs-verity file digests itself, e.g. in order to sign files.
- * It isn't needed just to enable fs-verity on a file.
- *
- * Note: when computing the file digest, 'sig_size' and 'signature' must be left
- * zero and empty, respectively. These fields are present only because some
- * filesystems reuse this struct as part of their on-disk format.
- */
-struct fsverity_descriptor {
- __u8 version; /* must be 1 */
- __u8 hash_algorithm; /* Merkle tree hash algorithm */
- __u8 log_blocksize; /* log2 of size of data and tree blocks */
- __u8 salt_size; /* size of salt in bytes; 0 if none */
-#ifdef __KERNEL__
- __le32 sig_size;
-#else
- __le32 __reserved_0x04; /* must be 0 */
-#endif
- __le64 data_size; /* size of file the Merkle tree is built over */
- __u8 root_hash[64]; /* Merkle tree root hash */
- __u8 salt[32]; /* salt prepended to each hashed block */
- __u8 __reserved[144]; /* must be 0's */
-#ifdef __KERNEL__
- __u8 signature[];
-#endif
-};
-
-/*
- * Format in which fs-verity file digests are signed in built-in signatures.
- * This is the same as 'struct fsverity_digest', except here some magic bytes
- * are prepended to provide some context about what is being signed in case the
- * same key is used for non-fsverity purposes, and here the fields have fixed
- * endianness.
- *
- * This struct is specific to the built-in signature verification support, which
- * is optional. fs-verity users may also verify signatures in userspace, in
- * which case userspace is responsible for deciding on what bytes are signed.
- * This struct may still be used, but it doesn't have to be. For example,
- * userspace could instead use a string like "sha256:$digest_as_hex_string".
- */
-struct fsverity_formatted_digest {
- char magic[8]; /* must be "FSVerity" */
- __le16 digest_algorithm;
- __le16 digest_size;
- __u8 digest[];
-};
-
-#define FS_IOC_ENABLE_VERITY _IOW('f', 133, struct fsverity_enable_arg)
-#define FS_IOC_MEASURE_VERITY _IOWR('f', 134, struct fsverity_digest)
-
-#endif /* _UAPI_LINUX_FSVERITY_H */
diff --git a/common/win32_defs.h b/common/win32_defs.h
deleted file mode 100644
index 29ef9b2..0000000
--- a/common/win32_defs.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-/*
- * WIN32 compat definitions for libfsverity and the 'fsverity' program
- *
- * Copyright 2020 Microsoft
- *
- * Use of this source code is governed by an MIT-style
- * license that can be found in the LICENSE file or at
- * https://opensource.org/licenses/MIT.
- */
-#ifndef COMMON_WIN32_DEFS_H
-#define COMMON_WIN32_DEFS_H
-
-/* Some minimal definitions to allow the digest/sign commands to run under Windows */
-
-/* All file reads we do need this flag on _WIN32 */
-#ifndef O_BINARY
-# define O_BINARY 0
-#endif
-
-#ifdef _WIN32
-
-#include <stdint.h>
-#include <inttypes.h>
-
-#ifndef ENOPKG
-# define ENOPKG 65
-#endif
-
-#ifndef __cold
-# define __cold
-#endif
-
-/* For %zu in printf() */
-#ifndef __printf
-# define __printf(fmt_idx, vargs_idx) \
- __attribute__((format(gnu_printf, fmt_idx, vargs_idx)))
-#endif
-
-typedef __signed__ char __s8;
-typedef unsigned char __u8;
-typedef __signed__ short __s16;
-typedef unsigned short __u16;
-typedef __signed__ int __s32;
-typedef unsigned int __u32;
-typedef __signed__ long long __s64;
-typedef unsigned long long __u64;
-typedef __u16 __le16;
-typedef __u16 __be16;
-typedef __u32 __le32;
-typedef __u32 __be32;
-typedef __u64 __le64;
-typedef __u64 __be64;
-
-#endif /* _WIN32 */
-
-#endif /* COMMON_WIN32_DEFS_H */
diff --git a/programs/fsverity.c b/fsverity.c
index b911b2e..6fabfa4 100644
--- a/programs/fsverity.c
+++ b/fsverity.c
@@ -1,17 +1,19 @@
-// SPDX-License-Identifier: MIT
+// SPDX-License-Identifier: GPL-2.0+
/*
* fs-verity userspace tool
*
- * Copyright 2018 Google LLC
+ * Copyright (C) 2018 Google LLC
*
- * Use of this source code is governed by an MIT-style
- * license that can be found in the LICENSE file or at
- * https://opensource.org/licenses/MIT.
+ * Written by Eric Biggers.
*/
-#include "fsverity.h"
-
#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "commands.h"
+#include "hash_algs.h"
static const struct fsverity_command {
const char *name;
@@ -20,16 +22,6 @@ static const struct fsverity_command {
const char *usage_str;
} fsverity_commands[] = {
{
- .name = "digest",
- .func = fsverity_cmd_digest,
- .short_desc =
-"Compute the fs-verity digest of the given file(s), for offline signing",
- .usage_str =
-" fsverity digest FILE...\n"
-" [--hash-alg=HASH_ALG] [--block-size=BLOCK_SIZE] [--salt=SALT]\n"
-" [--compact] [--for-builtin-sig]\n"
-#ifndef _WIN32
- }, {
.name = "enable",
.func = fsverity_cmd_enable,
.short_desc = "Enable fs-verity on a file",
@@ -41,10 +33,9 @@ static const struct fsverity_command {
.name = "measure",
.func = fsverity_cmd_measure,
.short_desc =
-"Display the fs-verity digest of the given verity file(s)",
+"Display the measurement of the given verity file(s)",
.usage_str =
" fsverity measure FILE...\n"
-#endif /* !_WIN32 */
}, {
.name = "sign",
.func = fsverity_cmd_sign,
@@ -56,17 +47,6 @@ static const struct fsverity_command {
}
};
-static void show_all_hash_algs(FILE *fp)
-{
- u32 alg_num = 1;
- const char *name;
-
- fprintf(fp, "Available hash algorithms:");
- while ((name = libfsverity_get_hash_name(alg_num++)) != NULL)
- fprintf(fp, " %s", name);
- putc('\n', fp);
-}
-
static void usage_all(FILE *fp)
{
int i;
@@ -79,8 +59,10 @@ static void usage_all(FILE *fp)
" Standard options:\n"
" fsverity --help\n"
" fsverity --version\n"
-"\n", fp);
+"\n"
+"Available hash algorithms: ", fp);
show_all_hash_algs(fp);
+ fputs("\nSee `man fsverity` for more details.\n", fp);
}
static void usage_cmd(const struct fsverity_command *cmd, FILE *fp)
@@ -96,10 +78,20 @@ void usage(const struct fsverity_command *cmd, FILE *fp)
usage_all(fp);
}
+#define PACKAGE_VERSION "v0.0-alpha"
+#define PACKAGE_BUGREPORT "linux-fscrypt@vger.kernel.org"
+
static void show_version(void)
{
- printf("fsverity v%d.%d\n", FSVERITY_UTILS_MAJOR_VERSION,
- FSVERITY_UTILS_MINOR_VERSION);
+ static const char * const str =
+"fsverity " PACKAGE_VERSION "\n"
+"Copyright (C) 2018 Google LLC\n"
+"License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>.\n"
+"This is free software: you are free to change and redistribute it.\n"
+"There is NO WARRANTY, to the extent permitted by law.\n"
+"\n"
+"Report bugs to " PACKAGE_BUGREPORT ".\n";
+ fputs(str, stdout);
}
static void handle_common_options(int argc, char *argv[],
@@ -135,32 +127,7 @@ static const struct fsverity_command *find_command(const char *name)
return NULL;
}
-static bool parse_hash_alg_option(const char *arg, u32 *alg_ptr)
-{
- char *end;
- unsigned long n = strtoul(arg, &end, 10);
-
- if (*alg_ptr != 0) {
- error_msg("--hash-alg can only be specified once");
- return false;
- }
-
- /* Specified by number? */
- if (n > 0 && n < INT32_MAX && *end == '\0') {
- *alg_ptr = n;
- return true;
- }
-
- /* Specified by name? */
- *alg_ptr = libfsverity_find_hash_alg_by_name(arg);
- if (*alg_ptr)
- return true;
- error_msg("unknown hash algorithm: '%s'", arg);
- show_all_hash_algs(stderr);
- return false;
-}
-
-static bool parse_block_size_option(const char *arg, u32 *size_ptr)
+bool parse_block_size_option(const char *arg, u32 *size_ptr)
{
char *end;
unsigned long n = strtoul(arg, &end, 10);
@@ -178,8 +145,7 @@ static bool parse_block_size_option(const char *arg, u32 *size_ptr)
return true;
}
-static bool parse_salt_option(const char *arg, u8 **salt_ptr,
- u32 *salt_size_ptr)
+bool parse_salt_option(const char *arg, u8 **salt_ptr, u32 *salt_size_ptr)
{
if (*salt_ptr != NULL) {
error_msg("--salt can only be specified once");
@@ -194,34 +160,23 @@ static bool parse_salt_option(const char *arg, u8 **salt_ptr,
return true;
}
-bool parse_tree_param(int opt_char, const char *arg,
- struct libfsverity_merkle_tree_params *params)
+u32 get_default_block_size(void)
{
- switch (opt_char) {
- case OPT_HASH_ALG:
- return parse_hash_alg_option(arg, &params->hash_algorithm);
- case OPT_BLOCK_SIZE:
- return parse_block_size_option(arg, &params->block_size);
- case OPT_SALT:
- return parse_salt_option(arg, (u8 **)&params->salt,
- &params->salt_size);
- default:
- ASSERT(0);
- }
-}
+ long n = sysconf(_SC_PAGESIZE);
-void destroy_tree_params(struct libfsverity_merkle_tree_params *params)
-{
- free((u8 *)params->salt);
- memset(params, 0, sizeof(*params));
+ if (n <= 0 || n >= INT_MAX || !is_power_of_2(n)) {
+ fprintf(stderr,
+ "Warning: invalid _SC_PAGESIZE (%ld). Assuming 4K blocks.\n",
+ n);
+ return 4096;
+ }
+ return n;
}
int main(int argc, char *argv[])
{
const struct fsverity_command *cmd;
- install_libfsverity_error_handler();
-
if (argc < 2) {
error_msg("no command specified");
usage_all(stderr);
diff --git a/fsverity_uapi.h b/fsverity_uapi.h
new file mode 100644
index 0000000..da0daf6
--- /dev/null
+++ b/fsverity_uapi.h
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * fs-verity user API
+ *
+ * These ioctls can be used on filesystems that support fs-verity. See the
+ * "User API" section of Documentation/filesystems/fsverity.rst.
+ *
+ * Copyright 2019 Google LLC
+ */
+#ifndef _UAPI_LINUX_FSVERITY_H
+#define _UAPI_LINUX_FSVERITY_H
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+#define FS_VERITY_HASH_ALG_SHA256 1
+#define FS_VERITY_HASH_ALG_SHA512 2
+
+struct fsverity_enable_arg {
+ __u32 version;
+ __u32 hash_algorithm;
+ __u32 block_size;
+ __u32 salt_size;
+ __u64 salt_ptr;
+ __u32 sig_size;
+ __u32 __reserved1;
+ __u64 sig_ptr;
+ __u64 __reserved2[11];
+};
+
+struct fsverity_digest {
+ __u16 digest_algorithm;
+ __u16 digest_size; /* input/output */
+ __u8 digest[];
+};
+
+#define FS_IOC_ENABLE_VERITY _IOW('f', 133, struct fsverity_enable_arg)
+#define FS_IOC_MEASURE_VERITY _IOWR('f', 134, struct fsverity_digest)
+
+#endif /* _UAPI_LINUX_FSVERITY_H */
diff --git a/lib/hash_algs.c b/hash_algs.c
index 510ca3e..7251bf2 100644
--- a/lib/hash_algs.c
+++ b/hash_algs.c
@@ -1,20 +1,19 @@
-// SPDX-License-Identifier: MIT
+// SPDX-License-Identifier: GPL-2.0+
/*
* fs-verity hash algorithms
*
- * Copyright 2018 Google LLC
+ * Copyright (C) 2018 Google LLC
*
- * Use of this source code is governed by an MIT-style
- * license that can be found in the LICENSE file or at
- * https://opensource.org/licenses/MIT.
+ * Written by Eric Biggers.
*/
-#include "lib_private.h"
-
#include <openssl/evp.h>
#include <stdlib.h>
#include <string.h>
+#include "fsverity_uapi.h"
+#include "hash_algs.h"
+
/* ========== libcrypto (OpenSSL) wrappers ========== */
struct openssl_hash_ctx {
@@ -26,29 +25,29 @@ struct openssl_hash_ctx {
static void openssl_digest_init(struct hash_ctx *_ctx)
{
struct openssl_hash_ctx *ctx = (void *)_ctx;
- int ret;
- ret = EVP_DigestInit_ex(ctx->md_ctx, ctx->md, NULL);
- BUG_ON(ret != 1);
+ if (EVP_DigestInit_ex(ctx->md_ctx, ctx->md, NULL) != 1)
+ fatal_error("EVP_DigestInit_ex() failed for algorithm '%s'",
+ ctx->base.alg->name);
}
static void openssl_digest_update(struct hash_ctx *_ctx,
const void *data, size_t size)
{
struct openssl_hash_ctx *ctx = (void *)_ctx;
- int ret;
- ret = EVP_DigestUpdate(ctx->md_ctx, data, size);
- BUG_ON(ret != 1);
+ if (EVP_DigestUpdate(ctx->md_ctx, data, size) != 1)
+ fatal_error("EVP_DigestUpdate() failed for algorithm '%s'",
+ ctx->base.alg->name);
}
static void openssl_digest_final(struct hash_ctx *_ctx, u8 *digest)
{
struct openssl_hash_ctx *ctx = (void *)_ctx;
- int ret;
- ret = EVP_DigestFinal_ex(ctx->md_ctx, digest, NULL);
- BUG_ON(ret != 1);
+ if (EVP_DigestFinal_ex(ctx->md_ctx, digest, NULL) != 1)
+ fatal_error("EVP_DigestFinal_ex() failed for algorithm '%s'",
+ ctx->base.alg->name);
}
static void openssl_digest_ctx_free(struct hash_ctx *_ctx)
@@ -69,10 +68,7 @@ openssl_digest_ctx_create(const struct fsverity_hash_alg *alg, const EVP_MD *md)
{
struct openssl_hash_ctx *ctx;
- ctx = libfsverity_zalloc(sizeof(*ctx));
- if (!ctx)
- return NULL;
-
+ ctx = xzalloc(sizeof(*ctx));
ctx->base.alg = alg;
ctx->base.init = openssl_digest_init;
ctx->base.update = openssl_digest_update;
@@ -84,22 +80,13 @@ openssl_digest_ctx_create(const struct fsverity_hash_alg *alg, const EVP_MD *md)
* with older OpenSSL versions.
*/
ctx->md_ctx = EVP_MD_CTX_create();
- if (!ctx->md_ctx) {
- libfsverity_error_msg("failed to allocate EVP_MD_CTX");
- goto err1;
- }
+ if (!ctx->md_ctx)
+ fatal_error("out of memory");
ctx->md = md;
- if (WARN_ON(EVP_MD_size(md) != alg->digest_size))
- goto err2;
+ ASSERT(EVP_MD_size(md) == alg->digest_size);
return &ctx->base;
-
-err2:
- EVP_MD_CTX_destroy(ctx->md_ctx);
-err1:
- free(ctx);
- return NULL;
}
static struct hash_ctx *create_sha256_ctx(const struct fsverity_hash_alg *alg)
@@ -112,42 +99,9 @@ static struct hash_ctx *create_sha512_ctx(const struct fsverity_hash_alg *alg)
return openssl_digest_ctx_create(alg, EVP_sha512());
}
-/* ========== Hash utilities ========== */
-
-void libfsverity_hash_init(struct hash_ctx *ctx)
-{
- ctx->init(ctx);
-}
-
-void libfsverity_hash_update(struct hash_ctx *ctx, const void *data,
- size_t size)
-{
- ctx->update(ctx, data, size);
-}
-
-void libfsverity_hash_final(struct hash_ctx *ctx, u8 *digest)
-{
- ctx->final(ctx, digest);
-}
-
-/* ->init(), ->update(), and ->final() all in one step */
-void libfsverity_hash_full(struct hash_ctx *ctx, const void *data, size_t size,
- u8 *digest)
-{
- libfsverity_hash_init(ctx);
- libfsverity_hash_update(ctx, data, size);
- libfsverity_hash_final(ctx, digest);
-}
-
-void libfsverity_free_hash_ctx(struct hash_ctx *ctx)
-{
- if (ctx)
- ctx->free(ctx);
-}
-
/* ========== Hash algorithm definitions ========== */
-static const struct fsverity_hash_alg fsverity_hash_algs[] = {
+const struct fsverity_hash_alg fsverity_hash_algs[] = {
[FS_VERITY_HASH_ALG_SHA256] = {
.name = "sha256",
.digest_size = 32,
@@ -162,45 +116,48 @@ static const struct fsverity_hash_alg fsverity_hash_algs[] = {
},
};
-LIBEXPORT u32
-libfsverity_find_hash_alg_by_name(const char *name)
+const struct fsverity_hash_alg *find_hash_alg_by_name(const char *name)
{
int i;
- if (!name)
- return 0;
-
- for (i = 1; i < ARRAY_SIZE(fsverity_hash_algs); i++) {
+ for (i = 0; i < ARRAY_SIZE(fsverity_hash_algs); i++) {
if (fsverity_hash_algs[i].name &&
!strcmp(name, fsverity_hash_algs[i].name))
- return i;
+ return &fsverity_hash_algs[i];
}
- return 0;
+ error_msg("unknown hash algorithm: '%s'", name);
+ fputs("Available hash algorithms: ", stderr);
+ show_all_hash_algs(stderr);
+ putc('\n', stderr);
+ return NULL;
}
-const struct fsverity_hash_alg *libfsverity_find_hash_alg_by_num(u32 alg_num)
+const struct fsverity_hash_alg *find_hash_alg_by_num(unsigned int num)
{
- if (alg_num < ARRAY_SIZE(fsverity_hash_algs) &&
- fsverity_hash_algs[alg_num].name)
- return &fsverity_hash_algs[alg_num];
+ if (num < ARRAY_SIZE(fsverity_hash_algs) &&
+ fsverity_hash_algs[num].name)
+ return &fsverity_hash_algs[num];
return NULL;
}
-LIBEXPORT int
-libfsverity_get_digest_size(u32 alg_num)
+void show_all_hash_algs(FILE *fp)
{
- const struct fsverity_hash_alg *alg =
- libfsverity_find_hash_alg_by_num(alg_num);
+ int i;
+ const char *sep = "";
- return alg ? alg->digest_size : -1;
+ for (i = 0; i < ARRAY_SIZE(fsverity_hash_algs); i++) {
+ if (fsverity_hash_algs[i].name) {
+ fprintf(fp, "%s%s", sep, fsverity_hash_algs[i].name);
+ sep = ", ";
+ }
+ }
}
-LIBEXPORT const char *
-libfsverity_get_hash_name(u32 alg_num)
+/* ->init(), ->update(), and ->final() all in one step */
+void hash_full(struct hash_ctx *ctx, const void *data, size_t size, u8 *digest)
{
- const struct fsverity_hash_alg *alg =
- libfsverity_find_hash_alg_by_num(alg_num);
-
- return alg ? alg->name : NULL;
+ hash_init(ctx);
+ hash_update(ctx, data, size);
+ hash_final(ctx, digest);
}
diff --git a/hash_algs.h b/hash_algs.h
new file mode 100644
index 0000000..3e90f49
--- /dev/null
+++ b/hash_algs.h
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+#ifndef HASH_ALGS_H
+#define HASH_ALGS_H
+
+#include <stdio.h>
+
+#include "util.h"
+
+struct fsverity_hash_alg {
+ const char *name;
+ unsigned int digest_size;
+ unsigned int block_size;
+ struct hash_ctx *(*create_ctx)(const struct fsverity_hash_alg *alg);
+};
+
+extern const struct fsverity_hash_alg fsverity_hash_algs[];
+
+struct hash_ctx {
+ const struct fsverity_hash_alg *alg;
+ void (*init)(struct hash_ctx *ctx);
+ void (*update)(struct hash_ctx *ctx, const void *data, size_t size);
+ void (*final)(struct hash_ctx *ctx, u8 *out);
+ void (*free)(struct hash_ctx *ctx);
+};
+
+const struct fsverity_hash_alg *find_hash_alg_by_name(const char *name);
+const struct fsverity_hash_alg *find_hash_alg_by_num(unsigned int num);
+void show_all_hash_algs(FILE *fp);
+
+/* The hash algorithm that fsverity-utils assumes when none is specified */
+#define FS_VERITY_HASH_ALG_DEFAULT FS_VERITY_HASH_ALG_SHA256
+
+/*
+ * Largest digest size among all hash algorithms supported by fs-verity.
+ * This can be increased if needed.
+ */
+#define FS_VERITY_MAX_DIGEST_SIZE 64
+
+static inline struct hash_ctx *hash_create(const struct fsverity_hash_alg *alg)
+{
+ return alg->create_ctx(alg);
+}
+
+static inline void hash_init(struct hash_ctx *ctx)
+{
+ ctx->init(ctx);
+}
+
+static inline void hash_update(struct hash_ctx *ctx,
+ const void *data, size_t size)
+{
+ ctx->update(ctx, data, size);
+}
+
+static inline void hash_final(struct hash_ctx *ctx, u8 *digest)
+{
+ ctx->final(ctx, digest);
+}
+
+static inline void hash_free(struct hash_ctx *ctx)
+{
+ if (ctx)
+ ctx->free(ctx);
+}
+
+void hash_full(struct hash_ctx *ctx, const void *data, size_t size, u8 *digest);
+
+#endif /* HASH_ALGS_H */
diff --git a/include/libfsverity.h b/include/libfsverity.h
deleted file mode 100644
index 6c42e5e..0000000
--- a/include/libfsverity.h
+++ /dev/null
@@ -1,213 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-/*
- * libfsverity API
- *
- * Copyright 2018 Google LLC
- * Copyright (C) 2020 Facebook
- *
- * Use of this source code is governed by an MIT-style
- * license that can be found in the LICENSE file or at
- * https://opensource.org/licenses/MIT.
- */
-
-#ifndef LIBFSVERITY_H
-#define LIBFSVERITY_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <errno.h>
-#include <stddef.h>
-#include <stdint.h>
-
-#define FSVERITY_UTILS_MAJOR_VERSION 1
-#define FSVERITY_UTILS_MINOR_VERSION 3
-
-#define FS_VERITY_HASH_ALG_SHA256 1
-#define FS_VERITY_HASH_ALG_SHA512 2
-
-/**
- * struct libfsverity_merkle_tree_params - properties of a file's Merkle tree
- *
- * Zero this, then fill in at least @version and @file_size.
- */
-struct libfsverity_merkle_tree_params {
-
- /** @version: must be 1 */
- uint32_t version;
-
- /**
- * @hash_algorithm: one of FS_VERITY_HASH_ALG_*, or 0 to use the default
- * of FS_VERITY_HASH_ALG_SHA256
- */
- uint32_t hash_algorithm;
-
- /** @file_size: the file size in bytes */
- uint64_t file_size;
-
- /**
- * @block_size: the Merkle tree block size in bytes, or 0 to use the
- * default of 4096 bytes
- */
- uint32_t block_size;
-
- /** @salt_size: the salt size in bytes, or 0 if unsalted */
- uint32_t salt_size;
-
- /** @salt: pointer to the salt, or NULL if unsalted */
- const uint8_t *salt;
-
- /** @reserved1: must be 0 */
- uint64_t reserved1[8];
-
- /** @reserved2: must be 0 */
- uintptr_t reserved2[8];
-};
-
-struct libfsverity_digest {
- uint16_t digest_algorithm; /* one of FS_VERITY_HASH_ALG_* */
- uint16_t digest_size; /* digest size in bytes */
- uint8_t digest[]; /* the actual digest */
-};
-
-struct libfsverity_signature_params {
- const char *keyfile; /* path to key file (PEM format) */
- const char *certfile; /* path to certificate (PEM format) */
- uint64_t reserved1[8]; /* must be 0 */
- uintptr_t reserved2[8]; /* must be 0 */
-};
-
-/*
- * libfsverity_read_fn_t - callback that incrementally provides a file's data
- * @fd: the user-provided "file descriptor" (opaque to library)
- * @buf: buffer into which to read the next chunk of the file's data
- * @count: number of bytes to read in this chunk
- *
- * Must return 0 on success (all 'count' bytes read), or a negative errno value
- * on failure.
- */
-typedef int (*libfsverity_read_fn_t)(void *fd, void *buf, size_t count);
-
-/**
- * libfsverity_compute_digest() - Compute digest of a file
- * A fs-verity file digest is the hash of a file's fsverity_descriptor.
- * Not to be confused with a traditional file digest computed over the
- * entire file, or with the bare fsverity_descriptor::root_hash.
- * @fd: context that will be passed to @read_fn
- * @read_fn: a function that will read the data of the file
- * @params: Pointer to the Merkle tree parameters
- * @digest_ret: Pointer to pointer for computed digest.
- *
- * Returns:
- * * 0 for success, -EINVAL for invalid input arguments, -ENOMEM if libfsverity
- * failed to allocate memory, or an error returned by @read_fn.
- * * digest_ret returns a pointer to the digest on success. The digest object
- * is allocated by libfsverity and must be freed by the caller using free().
- */
-int
-libfsverity_compute_digest(void *fd, libfsverity_read_fn_t read_fn,
- const struct libfsverity_merkle_tree_params *params,
- struct libfsverity_digest **digest_ret);
-
-/**
- * libfsverity_sign_digest() - Sign previously computed digest of a file
- * This signature is used by the filesystem to validate the signed file
- * digest against a public key loaded into the .fs-verity kernel
- * keyring, when CONFIG_FS_VERITY_BUILTIN_SIGNATURES is enabled. The
- * signature is formatted as PKCS#7 stored in DER format. See
- * Documentation/filesystems/fsverity.rst in the kernel source tree for
- * further details.
- * @digest: pointer to previously computed digest
- * @sig_params: struct libfsverity_signature_params providing filenames of
- * the keyfile and certificate file. Reserved fields must be zero.
- * @sig_ret: Pointer to pointer for signed digest
- * @sig_size_ret: Pointer to size of signed return digest
- *
- * Return:
- * * 0 for success, -EINVAL for invalid input arguments or if the cryptographic
- * operations to sign the digest failed, -EBADMSG if the key and/or
- * certificate file is invalid, or another negative errno value.
- * * sig_ret returns a pointer to the signed digest on success. This object
- * is allocated by libfsverity and must be freed by the caller using free().
- * * sig_size_ret returns the size (in bytes) of the signed digest on success.
- */
-int
-libfsverity_sign_digest(const struct libfsverity_digest *digest,
- const struct libfsverity_signature_params *sig_params,
- uint8_t **sig_ret, size_t *sig_size_ret);
-
-/**
- * libfsverity_enable() - Enable fs-verity on a file
- * @fd: read-only file descriptor to the file
- * @params: pointer to the Merkle tree parameters
- *
- * This is a simple wrapper around the FS_IOC_ENABLE_VERITY ioctl.
- *
- * Return: 0 on success, -EINVAL for invalid arguments, or a negative errno
- * value from the FS_IOC_ENABLE_VERITY ioctl. See
- * Documentation/filesystems/fsverity.rst in the kernel source tree for
- * the possible error codes from FS_IOC_ENABLE_VERITY.
- */
-int
-libfsverity_enable(int fd, const struct libfsverity_merkle_tree_params *params);
-
-/**
- * libfsverity_enable_with_sig() - Enable fs-verity on a file, with a signature
- * @fd: read-only file descriptor to the file
- * @params: pointer to the Merkle tree parameters
- * @sig: pointer to the file's signature
- * @sig_size: size of the file's signature in bytes
- *
- * Like libfsverity_enable(), but allows specifying a built-in signature (i.e. a
- * singature created with libfsverity_sign_digest()) to associate with the file.
- * This is only needed if the in-kernel signature verification support is being
- * used; it is not needed if signatures are being verified in userspace.
- *
- * If @sig is NULL and @sig_size is 0, this is the same as libfsverity_enable().
- *
- * Return: See libfsverity_enable().
- */
-int
-libfsverity_enable_with_sig(int fd,
- const struct libfsverity_merkle_tree_params *params,
- const uint8_t *sig, size_t sig_size);
-
-/**
- * libfsverity_find_hash_alg_by_name() - Find hash algorithm by name
- * @name: Pointer to name of hash algorithm
- *
- * Return: The hash algorithm number, or zero if not found.
- */
-uint32_t libfsverity_find_hash_alg_by_name(const char *name);
-
-/**
- * libfsverity_get_digest_size() - Get size of digest for a given algorithm
- * @alg_num: Number of hash algorithm
- *
- * Return: size of digest in bytes, or -1 if algorithm is unknown.
- */
-int libfsverity_get_digest_size(uint32_t alg_num);
-
-/**
- * libfsverity_get_hash_name() - Get name of hash algorithm by number
- * @alg_num: Number of hash algorithm
- *
- * Return: The name of the hash algorithm, or NULL if algorithm is unknown.
- */
-const char *libfsverity_get_hash_name(uint32_t alg_num);
-
-/**
- * libfsverity_set_error_callback() - Set callback to handle error messages
- * @cb: the callback function.
- *
- * If a callback is already set, it is replaced. @cb may be NULL in order to
- * remove the existing callback.
- */
-void libfsverity_set_error_callback(void (*cb)(const char *msg));
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* LIBFSVERITY_H */
diff --git a/lib/compute_digest.c b/lib/compute_digest.c
deleted file mode 100644
index a4f649c..0000000
--- a/lib/compute_digest.c
+++ /dev/null
@@ -1,238 +0,0 @@
-// SPDX-License-Identifier: MIT
-/*
- * Implementation of libfsverity_compute_digest().
- *
- * Copyright 2018 Google LLC
- * Copyright (C) 2020 Facebook
- *
- * Use of this source code is governed by an MIT-style
- * license that can be found in the LICENSE file or at
- * https://opensource.org/licenses/MIT.
- */
-
-#include "lib_private.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-#define FS_VERITY_MAX_LEVELS 64
-
-struct block_buffer {
- u32 filled;
- u8 *data;
-};
-
-/*
- * Hash a block, writing the result to the next level's pending block buffer.
- * Returns true if the next level's block became full, else false.
- */
-static bool hash_one_block(struct hash_ctx *hash, struct block_buffer *cur,
- u32 block_size, const u8 *salt, u32 salt_size)
-{
- struct block_buffer *next = cur + 1;
-
- /* Zero-pad the block if it's shorter than block_size. */
- memset(&cur->data[cur->filled], 0, block_size - cur->filled);
-
- libfsverity_hash_init(hash);
- libfsverity_hash_update(hash, salt, salt_size);
- libfsverity_hash_update(hash, cur->data, block_size);
- libfsverity_hash_final(hash, &next->data[next->filled]);
-
- next->filled += hash->alg->digest_size;
- cur->filled = 0;
-
- return next->filled + hash->alg->digest_size > block_size;
-}
-
-/*
- * Compute the file's Merkle tree root hash using the given hash algorithm,
- * block size, and salt.
- */
-static int compute_root_hash(void *fd, libfsverity_read_fn_t read_fn,
- u64 file_size, struct hash_ctx *hash,
- u32 block_size, const u8 *salt, u32 salt_size,
- u8 *root_hash)
-{
- const u32 hashes_per_block = block_size / hash->alg->digest_size;
- const u32 padded_salt_size = roundup(salt_size, hash->alg->block_size);
- u8 *padded_salt = NULL;
- u64 blocks;
- int num_levels = 0;
- int level;
- struct block_buffer _buffers[1 + FS_VERITY_MAX_LEVELS + 1] = {};
- struct block_buffer *buffers = &_buffers[1];
- u64 offset;
- int err = 0;
-
- /* Root hash of empty file is all 0's */
- if (file_size == 0) {
- memset(root_hash, 0, hash->alg->digest_size);
- return 0;
- }
-
- if (salt_size != 0) {
- padded_salt = libfsverity_zalloc(padded_salt_size);
- if (!padded_salt)
- return -ENOMEM;
- memcpy(padded_salt, salt, salt_size);
- }
-
- /* Compute number of levels */
- for (blocks = DIV_ROUND_UP(file_size, block_size); blocks > 1;
- blocks = DIV_ROUND_UP(blocks, hashes_per_block)) {
- if (WARN_ON(num_levels >= FS_VERITY_MAX_LEVELS)) {
- err = -EINVAL;
- goto out;
- }
- num_levels++;
- }
-
- /*
- * Allocate the block buffers. Buffer "-1" is for data blocks.
- * Buffers 0 <= level < num_levels are for the actual tree levels.
- * Buffer 'num_levels' is for the root hash.
- */
- for (level = -1; level < num_levels; level++) {
- buffers[level].data = libfsverity_zalloc(block_size);
- if (!buffers[level].data) {
- err = -ENOMEM;
- goto out;
- }
- }
- buffers[num_levels].data = root_hash;
-
- /* Hash each data block, also hashing the tree blocks as they fill up */
- for (offset = 0; offset < file_size; offset += block_size) {
- buffers[-1].filled = min(block_size, file_size - offset);
-
- err = read_fn(fd, buffers[-1].data, buffers[-1].filled);
- if (err) {
- libfsverity_error_msg("error reading file");
- goto out;
- }
-
- level = -1;
- while (hash_one_block(hash, &buffers[level], block_size,
- padded_salt, padded_salt_size)) {
- level++;
- if (WARN_ON(level >= num_levels)) {
- err = -EINVAL;
- goto out;
- }
- }
- }
- /* Finish all nonempty pending tree blocks */
- for (level = 0; level < num_levels; level++) {
- if (buffers[level].filled != 0)
- hash_one_block(hash, &buffers[level], block_size,
- padded_salt, padded_salt_size);
- }
-
- /* Root hash was filled by the last call to hash_one_block() */
- if (WARN_ON(buffers[num_levels].filled != hash->alg->digest_size)) {
- err = -EINVAL;
- goto out;
- }
- err = 0;
-out:
- for (level = -1; level < num_levels; level++)
- free(buffers[level].data);
- free(padded_salt);
- return err;
-}
-
-LIBEXPORT int
-libfsverity_compute_digest(void *fd, libfsverity_read_fn_t read_fn,
- const struct libfsverity_merkle_tree_params *params,
- struct libfsverity_digest **digest_ret)
-{
- u32 alg_num;
- u32 block_size;
- const struct fsverity_hash_alg *hash_alg;
- struct hash_ctx *hash = NULL;
- struct libfsverity_digest *digest;
- struct fsverity_descriptor desc;
- int err;
-
- if (!read_fn || !params || !digest_ret) {
- libfsverity_error_msg("missing required parameters for compute_digest");
- return -EINVAL;
- }
- if (params->version != 1) {
- libfsverity_error_msg("unsupported version (%u)",
- params->version);
- return -EINVAL;
- }
-
- alg_num = params->hash_algorithm ?: FS_VERITY_HASH_ALG_DEFAULT;
- block_size = params->block_size ?: FS_VERITY_BLOCK_SIZE_DEFAULT;
-
- if (!is_power_of_2(block_size)) {
- libfsverity_error_msg("unsupported block size (%u)",
- block_size);
- return -EINVAL;
- }
- if (params->salt_size > sizeof(desc.salt)) {
- libfsverity_error_msg("unsupported salt size (%u)",
- params->salt_size);
- return -EINVAL;
- }
- if (params->salt_size && !params->salt) {
- libfsverity_error_msg("salt_size specified, but salt is NULL");
- return -EINVAL;
- }
- if (!libfsverity_mem_is_zeroed(params->reserved1,
- sizeof(params->reserved1)) ||
- !libfsverity_mem_is_zeroed(params->reserved2,
- sizeof(params->reserved2))) {
- libfsverity_error_msg("reserved bits set in merkle_tree_params");
- return -EINVAL;
- }
-
- hash_alg = libfsverity_find_hash_alg_by_num(alg_num);
- if (!hash_alg) {
- libfsverity_error_msg("unknown hash algorithm: %u", alg_num);
- return -EINVAL;
- }
-
- if (block_size < 2 * hash_alg->digest_size) {
- libfsverity_error_msg("block size (%u) too small for hash algorithm %s",
- block_size, hash_alg->name);
- return -EINVAL;
- }
-
- hash = hash_alg->create_ctx(hash_alg);
- if (!hash)
- return -ENOMEM;
-
- memset(&desc, 0, sizeof(desc));
- desc.version = 1;
- desc.hash_algorithm = alg_num;
- desc.log_blocksize = ilog2(block_size);
- desc.data_size = cpu_to_le64(params->file_size);
- if (params->salt_size != 0) {
- memcpy(desc.salt, params->salt, params->salt_size);
- desc.salt_size = params->salt_size;
- }
-
- err = compute_root_hash(fd, read_fn, params->file_size, hash,
- block_size, params->salt,
- params->salt_size, desc.root_hash);
- if (err)
- goto out;
-
- digest = libfsverity_zalloc(sizeof(*digest) + hash_alg->digest_size);
- if (!digest) {
- err = -ENOMEM;
- goto out;
- }
- digest->digest_algorithm = alg_num;
- digest->digest_size = hash_alg->digest_size;
- libfsverity_hash_full(hash, &desc, sizeof(desc), digest->digest);
- *digest_ret = digest;
- err = 0;
-out:
- libfsverity_free_hash_ctx(hash);
- return err;
-}
diff --git a/lib/enable.c b/lib/enable.c
deleted file mode 100644
index 2478077..0000000
--- a/lib/enable.c
+++ /dev/null
@@ -1,53 +0,0 @@
-// SPDX-License-Identifier: MIT
-/*
- * Implementation of libfsverity_enable() and libfsverity_enable_with_sig().
- *
- * Copyright 2020 Google LLC
- *
- * Use of this source code is governed by an MIT-style
- * license that can be found in the LICENSE file or at
- * https://opensource.org/licenses/MIT.
- */
-
-#include "lib_private.h"
-
-#include <sys/ioctl.h>
-
-LIBEXPORT int
-libfsverity_enable(int fd, const struct libfsverity_merkle_tree_params *params)
-{
- return libfsverity_enable_with_sig(fd, params, NULL, 0);
-}
-
-LIBEXPORT int
-libfsverity_enable_with_sig(int fd,
- const struct libfsverity_merkle_tree_params *params,
- const uint8_t *sig, size_t sig_size)
-{
- struct fsverity_enable_arg arg = {};
-
- if (!params) {
- libfsverity_error_msg("missing required parameters for enable");
- return -EINVAL;
- }
-
- if (params->version != 1) {
- libfsverity_error_msg("unsupported version (%u)",
- params->version);
- return -EINVAL;
- }
-
- arg.version = 1;
- arg.hash_algorithm =
- params->hash_algorithm ?: FS_VERITY_HASH_ALG_DEFAULT;
- arg.block_size =
- params->block_size ?: FS_VERITY_BLOCK_SIZE_DEFAULT;
- arg.salt_size = params->salt_size;
- arg.salt_ptr = (uintptr_t)params->salt;
- arg.sig_size = sig_size;
- arg.sig_ptr = (uintptr_t)sig;
-
- if (ioctl(fd, FS_IOC_ENABLE_VERITY, &arg) != 0)
- return -errno;
- return 0;
-}
diff --git a/lib/lib_private.h b/lib/lib_private.h
deleted file mode 100644
index 7768eea..0000000
--- a/lib/lib_private.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-/*
- * Private header for libfsverity
- *
- * Copyright 2020 Google LLC
- *
- * Use of this source code is governed by an MIT-style
- * license that can be found in the LICENSE file or at
- * https://opensource.org/licenses/MIT.
- */
-#ifndef LIB_LIB_PRIVATE_H
-#define LIB_LIB_PRIVATE_H
-
-#include "libfsverity.h"
-#include "../common/common_defs.h"
-#include "../common/fsverity_uapi.h"
-
-#include <stdarg.h>
-
-#define LIBEXPORT __attribute__((visibility("default")))
-
-/* The hash algorithm that libfsverity assumes when none is specified */
-#define FS_VERITY_HASH_ALG_DEFAULT FS_VERITY_HASH_ALG_SHA256
-
-/* The block size that libfsverity assumes when none is specified */
-#define FS_VERITY_BLOCK_SIZE_DEFAULT 4096
-
-/* hash_algs.c */
-
-struct fsverity_hash_alg {
- const char *name;
- unsigned int digest_size;
- unsigned int block_size;
- struct hash_ctx *(*create_ctx)(const struct fsverity_hash_alg *alg);
-};
-
-const struct fsverity_hash_alg *libfsverity_find_hash_alg_by_num(u32 alg_num);
-
-struct hash_ctx {
- const struct fsverity_hash_alg *alg;
- void (*init)(struct hash_ctx *ctx);
- void (*update)(struct hash_ctx *ctx, const void *data, size_t size);
- void (*final)(struct hash_ctx *ctx, u8 *out);
- void (*free)(struct hash_ctx *ctx);
-};
-
-void libfsverity_hash_init(struct hash_ctx *ctx);
-void libfsverity_hash_update(struct hash_ctx *ctx, const void *data,
- size_t size);
-void libfsverity_hash_final(struct hash_ctx *ctx, u8 *digest);
-void libfsverity_hash_full(struct hash_ctx *ctx, const void *data, size_t size,
- u8 *digest);
-void libfsverity_free_hash_ctx(struct hash_ctx *ctx);
-
-/* utils.c */
-
-void *libfsverity_zalloc(size_t size);
-void *libfsverity_memdup(const void *mem, size_t size);
-
-__cold void
-libfsverity_do_error_msg(const char *format, va_list va, int err);
-
-__printf(1, 2) __cold void
-libfsverity_error_msg(const char *format, ...);
-
-__printf(1, 2) __cold void
-libfsverity_error_msg_errno(const char *format, ...);
-
-__cold void
-libfsverity_warn_on(const char *condition, const char *file, int line);
-
-#define WARN_ON(condition) \
-({ \
- bool c = (condition); \
- \
- if (c) \
- libfsverity_warn_on(#condition, __FILE__, __LINE__); \
- c; \
-})
-
-__cold void
-libfsverity_bug_on(const char *condition, const char *file, int line);
-
-#define BUG_ON(condition) \
-({ \
- bool c = (condition); \
- \
- if (c) \
- libfsverity_bug_on(#condition, __FILE__, __LINE__); \
- c; \
-})
-
-bool libfsverity_mem_is_zeroed(const void *mem, size_t size);
-
-#endif /* LIB_LIB_PRIVATE_H */
diff --git a/lib/libfsverity.pc.in b/lib/libfsverity.pc.in
deleted file mode 100644
index be3ef44..0000000
--- a/lib/libfsverity.pc.in
+++ /dev/null
@@ -1,10 +0,0 @@
-prefix=@PREFIX@
-libdir=@LIBDIR@
-includedir=@INCDIR@
-
-Name: libfsverity
-Description: fs-verity library
-Version: 1.3
-Libs: -L${libdir} -lfsverity
-Requires.private: libcrypto
-Cflags: -I${includedir}
diff --git a/lib/sign_digest.c b/lib/sign_digest.c
deleted file mode 100644
index 9a35256..0000000
--- a/lib/sign_digest.c
+++ /dev/null
@@ -1,390 +0,0 @@
-// SPDX-License-Identifier: MIT
-/*
- * Implementation of libfsverity_sign_digest().
- *
- * Copyright 2018 Google LLC
- * Copyright (C) 2020 Facebook
- *
- * Use of this source code is governed by an MIT-style
- * license that can be found in the LICENSE file or at
- * https://opensource.org/licenses/MIT.
- */
-
-#include "lib_private.h"
-
-#include <limits.h>
-#include <openssl/bio.h>
-#include <openssl/err.h>
-#include <openssl/pem.h>
-#include <openssl/pkcs7.h>
-#include <string.h>
-
-static int print_openssl_err_cb(const char *str,
- size_t len __attribute__((unused)),
- void *u __attribute__((unused)))
-{
- libfsverity_error_msg("%s", str);
- return 1;
-}
-
-static void __printf(1, 2) __cold
-error_msg_openssl(const char *format, ...)
-{
- int saved_errno = errno;
- va_list va;
-
- va_start(va, format);
- libfsverity_do_error_msg(format, va, 0);
- va_end(va);
-
- if (ERR_peek_error() == 0)
- return;
-
- libfsverity_error_msg("OpenSSL library errors:");
- ERR_print_errors_cb(print_openssl_err_cb, NULL);
- errno = saved_errno;
-}
-
-/* Read a PEM PKCS#8 formatted private key */
-static int read_private_key(const char *keyfile, EVP_PKEY **pkey_ret)
-{
- BIO *bio;
- EVP_PKEY *pkey;
- int err;
-
- errno = 0;
- bio = BIO_new_file(keyfile, "r");
- if (!bio) {
- error_msg_openssl("can't open '%s' for reading", keyfile);
- return errno ? -errno : -EIO;
- }
-
- pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
- if (!pkey) {
- error_msg_openssl("Failed to parse private key file '%s'.\n"
- " Note: it must be in PEM PKCS#8 format.",
- keyfile);
- err = -EBADMSG;
- goto out;
- }
- *pkey_ret = pkey;
- err = 0;
-out:
- BIO_free(bio);
- return err;
-}
-
-/* Read a PEM X.509 formatted certificate */
-static int read_certificate(const char *certfile, X509 **cert_ret)
-{
- BIO *bio;
- X509 *cert;
- int err;
-
- errno = 0;
- bio = BIO_new_file(certfile, "r");
- if (!bio) {
- error_msg_openssl("can't open '%s' for reading", certfile);
- return errno ? -errno : -EIO;
- }
- cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
- if (!cert) {
- error_msg_openssl("Failed to parse X.509 certificate file '%s'.\n"
- " Note: it must be in PEM format.",
- certfile);
- err = -EBADMSG;
- goto out;
- }
- *cert_ret = cert;
- err = 0;
-out:
- BIO_free(bio);
- return err;
-}
-
-#ifdef OPENSSL_IS_BORINGSSL
-
-static int sign_pkcs7(const void *data_to_sign, size_t data_size,
- EVP_PKEY *pkey, X509 *cert, const EVP_MD *md,
- u8 **sig_ret, size_t *sig_size_ret)
-{
- BIGNUM *serial;
- CBB out, outer_seq, wrapped_seq, seq, digest_algos_set, digest_algo,
- null, content_info, issuer_and_serial, signer_infos,
- signer_info, sign_algo, signature;
- EVP_MD_CTX md_ctx;
- u8 *name_der = NULL, *sig = NULL, *pkcs7_data = NULL;
- size_t pkcs7_data_len, sig_len;
- int name_der_len, sig_nid;
- int err;
-
- EVP_MD_CTX_init(&md_ctx);
- serial = ASN1_INTEGER_to_BN(X509_get_serialNumber(cert), NULL);
-
- if (!CBB_init(&out, 1024)) {
- error_msg_openssl("out of memory");
- err = -ENOMEM;
- goto out;
- }
-
- name_der_len = i2d_X509_NAME(X509_get_subject_name(cert), &name_der);
- if (name_der_len < 0) {
- error_msg_openssl("i2d_X509_NAME failed");
- err = -EINVAL;
- goto out;
- }
-
- if (!EVP_DigestSignInit(&md_ctx, NULL, md, NULL, pkey)) {
- error_msg_openssl("EVP_DigestSignInit failed");
- err = -EINVAL;
- goto out;
- }
-
- sig_len = EVP_PKEY_size(pkey);
- sig = libfsverity_zalloc(sig_len);
- if (!sig) {
- err = -ENOMEM;
- goto out;
- }
- if (!EVP_DigestSign(&md_ctx, sig, &sig_len, data_to_sign, data_size)) {
- error_msg_openssl("EVP_DigestSign failed");
- err = -EINVAL;
- goto out;
- }
-
- sig_nid = EVP_PKEY_id(pkey);
- /* To mirror OpenSSL behaviour, always use |NID_rsaEncryption| with RSA
- * rather than the combined hash+pkey NID. */
- if (sig_nid != NID_rsaEncryption) {
- OBJ_find_sigid_by_algs(&sig_nid, EVP_MD_type(md),
- EVP_PKEY_id(pkey));
- }
-
- // See https://tools.ietf.org/html/rfc2315#section-7
- if (!CBB_add_asn1(&out, &outer_seq, CBS_ASN1_SEQUENCE) ||
- !OBJ_nid2cbb(&outer_seq, NID_pkcs7_signed) ||
- !CBB_add_asn1(&outer_seq, &wrapped_seq, CBS_ASN1_CONTEXT_SPECIFIC |
- CBS_ASN1_CONSTRUCTED | 0) ||
- // See https://tools.ietf.org/html/rfc2315#section-9.1
- !CBB_add_asn1(&wrapped_seq, &seq, CBS_ASN1_SEQUENCE) ||
- !CBB_add_asn1_uint64(&seq, 1 /* version */) ||
- !CBB_add_asn1(&seq, &digest_algos_set, CBS_ASN1_SET) ||
- !CBB_add_asn1(&digest_algos_set, &digest_algo, CBS_ASN1_SEQUENCE) ||
- !OBJ_nid2cbb(&digest_algo, EVP_MD_type(md)) ||
- !CBB_add_asn1(&digest_algo, &null, CBS_ASN1_NULL) ||
- !CBB_add_asn1(&seq, &content_info, CBS_ASN1_SEQUENCE) ||
- !OBJ_nid2cbb(&content_info, NID_pkcs7_data) ||
- !CBB_add_asn1(&seq, &signer_infos, CBS_ASN1_SET) ||
- !CBB_add_asn1(&signer_infos, &signer_info, CBS_ASN1_SEQUENCE) ||
- !CBB_add_asn1_uint64(&signer_info, 1 /* version */) ||
- !CBB_add_asn1(&signer_info, &issuer_and_serial,
- CBS_ASN1_SEQUENCE) ||
- !CBB_add_bytes(&issuer_and_serial, name_der, name_der_len) ||
- !BN_marshal_asn1(&issuer_and_serial, serial) ||
- !CBB_add_asn1(&signer_info, &digest_algo, CBS_ASN1_SEQUENCE) ||
- !OBJ_nid2cbb(&digest_algo, EVP_MD_type(md)) ||
- !CBB_add_asn1(&digest_algo, &null, CBS_ASN1_NULL) ||
- !CBB_add_asn1(&signer_info, &sign_algo, CBS_ASN1_SEQUENCE) ||
- !OBJ_nid2cbb(&sign_algo, sig_nid) ||
- !CBB_add_asn1(&sign_algo, &null, CBS_ASN1_NULL) ||
- !CBB_add_asn1(&signer_info, &signature, CBS_ASN1_OCTETSTRING) ||
- !CBB_add_bytes(&signature, sig, sig_len) ||
- !CBB_finish(&out, &pkcs7_data, &pkcs7_data_len)) {
- error_msg_openssl("failed to construct PKCS#7 data");
- err = -EINVAL;
- goto out;
- }
-
- *sig_ret = libfsverity_memdup(pkcs7_data, pkcs7_data_len);
- if (!*sig_ret) {
- err = -ENOMEM;
- goto out;
- }
- *sig_size_ret = pkcs7_data_len;
- err = 0;
-out:
- BN_free(serial);
- EVP_MD_CTX_cleanup(&md_ctx);
- CBB_cleanup(&out);
- free(sig);
- OPENSSL_free(name_der);
- OPENSSL_free(pkcs7_data);
- return err;
-}
-
-#else /* OPENSSL_IS_BORINGSSL */
-
-static BIO *new_mem_buf(const void *buf, size_t size)
-{
- BIO *bio;
-
- if (WARN_ON(size > INT_MAX))
- return NULL;
-
- /*
- * Prior to OpenSSL 1.1.0, BIO_new_mem_buf() took a non-const pointer,
- * despite still marking the resulting bio as read-only. So cast away
- * the const to avoid a compiler warning with older OpenSSL versions.
- */
- bio = BIO_new_mem_buf((void *)buf, size);
- if (!bio)
- error_msg_openssl("out of memory");
- return bio;
-}
-
-static int sign_pkcs7(const void *data_to_sign, size_t data_size,
- EVP_PKEY *pkey, X509 *cert, const EVP_MD *md,
- u8 **sig_ret, size_t *sig_size_ret)
-{
- /*
- * PKCS#7 signing flags:
- *
- * - PKCS7_BINARY signing binary data, so skip MIME translation
- *
- * - PKCS7_DETACHED omit the signed data (include signature only)
- *
- * - PKCS7_NOATTR omit extra authenticated attributes, such as
- * SMIMECapabilities
- *
- * - PKCS7_NOCERTS omit the signer's certificate
- *
- * - PKCS7_PARTIAL PKCS7_sign() creates a handle only, then
- * PKCS7_sign_add_signer() can add a signer later.
- * This is necessary to change the message digest
- * algorithm from the default of SHA-1. Requires
- * OpenSSL 1.0.0 or later.
- */
- int pkcs7_flags = PKCS7_BINARY | PKCS7_DETACHED | PKCS7_NOATTR |
- PKCS7_NOCERTS | PKCS7_PARTIAL;
- u8 *sig;
- u32 sig_size;
- BIO *bio = NULL;
- PKCS7 *p7 = NULL;
- int err;
-
- bio = new_mem_buf(data_to_sign, data_size);
- if (!bio) {
- err = -ENOMEM;
- goto out;
- }
-
- p7 = PKCS7_sign(NULL, NULL, NULL, bio, pkcs7_flags);
- if (!p7) {
- error_msg_openssl("failed to initialize PKCS#7 signature object");
- err = -EINVAL;
- goto out;
- }
-
- if (!PKCS7_sign_add_signer(p7, cert, pkey, md, pkcs7_flags)) {
- error_msg_openssl("failed to add signer to PKCS#7 signature object");
- err = -EINVAL;
- goto out;
- }
-
- if (PKCS7_final(p7, bio, pkcs7_flags) != 1) {
- error_msg_openssl("failed to finalize PKCS#7 signature");
- err = -EINVAL;
- goto out;
- }
-
- BIO_free(bio);
- bio = BIO_new(BIO_s_mem());
- if (!bio) {
- error_msg_openssl("out of memory");
- err = -ENOMEM;
- goto out;
- }
-
- if (i2d_PKCS7_bio(bio, p7) != 1) {
- error_msg_openssl("failed to DER-encode PKCS#7 signature object");
- err = -EINVAL;
- goto out;
- }
-
- sig_size = BIO_get_mem_data(bio, &sig);
- *sig_ret = libfsverity_memdup(sig, sig_size);
- if (!*sig_ret) {
- err = -ENOMEM;
- goto out;
- }
- *sig_size_ret = sig_size;
- err = 0;
-out:
- PKCS7_free(p7);
- BIO_free(bio);
- return err;
-}
-
-#endif /* !OPENSSL_IS_BORINGSSL */
-
-LIBEXPORT int
-libfsverity_sign_digest(const struct libfsverity_digest *digest,
- const struct libfsverity_signature_params *sig_params,
- u8 **sig_ret, size_t *sig_size_ret)
-{
- const struct fsverity_hash_alg *hash_alg;
- EVP_PKEY *pkey = NULL;
- X509 *cert = NULL;
- const EVP_MD *md;
- struct fsverity_formatted_digest *d = NULL;
- int err;
-
- if (!digest || !sig_params || !sig_ret || !sig_size_ret) {
- libfsverity_error_msg("missing required parameters for sign_digest");
- return -EINVAL;
- }
-
- if (!sig_params->keyfile || !sig_params->certfile) {
- libfsverity_error_msg("keyfile and certfile must be specified");
- return -EINVAL;
- }
-
- if (!libfsverity_mem_is_zeroed(sig_params->reserved1,
- sizeof(sig_params->reserved1)) ||
- !libfsverity_mem_is_zeroed(sig_params->reserved2,
- sizeof(sig_params->reserved2))) {
- libfsverity_error_msg("reserved bits set in signature_params");
- return -EINVAL;
- }
-
- hash_alg = libfsverity_find_hash_alg_by_num(digest->digest_algorithm);
- if (!hash_alg || digest->digest_size != hash_alg->digest_size) {
- libfsverity_error_msg("malformed fsverity digest");
- return -EINVAL;
- }
-
- err = read_private_key(sig_params->keyfile, &pkey);
- if (err)
- goto out;
-
- err = read_certificate(sig_params->certfile, &cert);
- if (err)
- goto out;
-
- OpenSSL_add_all_digests();
- md = EVP_get_digestbyname(hash_alg->name);
- if (!md) {
- libfsverity_error_msg("'%s' algorithm not found in OpenSSL library",
- hash_alg->name);
- err = -ENOPKG;
- goto out;
- }
-
- d = libfsverity_zalloc(sizeof(*d) + digest->digest_size);
- if (!d) {
- err = -ENOMEM;
- goto out;
- }
- memcpy(d->magic, "FSVerity", 8);
- d->digest_algorithm = cpu_to_le16(digest->digest_algorithm);
- d->digest_size = cpu_to_le16(digest->digest_size);
- memcpy(d->digest, digest->digest, digest->digest_size);
-
- err = sign_pkcs7(d, sizeof(*d) + digest->digest_size,
- pkey, cert, md, sig_ret, sig_size_ret);
- out:
- EVP_PKEY_free(pkey);
- X509_free(cert);
- free(d);
- return err;
-}
diff --git a/lib/utils.c b/lib/utils.c
deleted file mode 100644
index 036dd60..0000000
--- a/lib/utils.c
+++ /dev/null
@@ -1,132 +0,0 @@
-// SPDX-License-Identifier: MIT
-/*
- * Utility functions for libfsverity
- *
- * Copyright 2020 Google LLC
- *
- * Use of this source code is governed by an MIT-style
- * license that can be found in the LICENSE file or at
- * https://opensource.org/licenses/MIT.
- */
-
-#include "lib_private.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-static void *xmalloc(size_t size)
-{
- void *p = malloc(size);
-
- if (!p)
- libfsverity_error_msg("out of memory (tried to allocate %zu bytes)",
- size);
- return p;
-}
-
-void *libfsverity_zalloc(size_t size)
-{
- void *p = xmalloc(size);
-
- if (!p)
- return NULL;
- return memset(p, 0, size);
-}
-
-void *libfsverity_memdup(const void *mem, size_t size)
-{
- void *p = xmalloc(size);
-
- if (!p)
- return NULL;
- return memcpy(p, mem, size);
-}
-
-static void (*libfsverity_error_cb)(const char *msg);
-
-LIBEXPORT void
-libfsverity_set_error_callback(void (*cb)(const char *msg))
-{
- libfsverity_error_cb = cb;
-}
-
-#ifdef _WIN32
-static char *strerror_r(int errnum, char *buf, size_t buflen)
-{
- strerror_s(buf, buflen, errnum);
-
- return buf;
-}
-#endif
-
-void libfsverity_do_error_msg(const char *format, va_list va, int err)
-{
- int saved_errno = errno;
- char *msg = NULL;
-
- if (!libfsverity_error_cb)
- return;
-
- if (vasprintf(&msg, format, va) < 0)
- goto out;
-
- if (err) {
- char *msg2 = NULL;
- char errbuf[64];
-
- if (asprintf(&msg2, "%s: %s", msg,
- strerror_r(err, errbuf, sizeof(errbuf))) < 0)
- goto out2;
- free(msg);
- msg = msg2;
- }
- (*libfsverity_error_cb)(msg);
-out2:
- free(msg);
-out:
- errno = saved_errno;
-}
-
-void libfsverity_error_msg(const char *format, ...)
-{
- va_list va;
-
- va_start(va, format);
- libfsverity_do_error_msg(format, va, 0);
- va_end(va);
-}
-
-void libfsverity_error_msg_errno(const char *format, ...)
-{
- va_list va;
-
- va_start(va, format);
- libfsverity_do_error_msg(format, va, errno);
- va_end(va);
-}
-
-void libfsverity_warn_on(const char *condition, const char *file, int line)
-{
- fprintf(stderr, "libfsverity internal error! %s at %s:%d\n",
- condition, file, line);
-}
-
-void libfsverity_bug_on(const char *condition, const char *file, int line)
-{
- fprintf(stderr, "libfsverity internal error! %s at %s:%d\n"
- "Non-recoverable, aborting program.\n", condition, file, line);
- abort();
-}
-
-bool libfsverity_mem_is_zeroed(const void *mem, size_t size)
-{
- const u8 *p = mem;
- size_t i;
-
- for (i = 0; i < size; i++) {
- if (p[i])
- return false;
- }
- return true;
-}
diff --git a/programs/cmd_digest.c b/programs/cmd_digest.c
deleted file mode 100644
index 1a3c769..0000000
--- a/programs/cmd_digest.c
+++ /dev/null
@@ -1,129 +0,0 @@
-// SPDX-License-Identifier: MIT
-/*
- * The 'fsverity digest' command
- *
- * Copyright 2020 Microsoft
- *
- * Use of this source code is governed by an MIT-style
- * license that can be found in the LICENSE file or at
- * https://opensource.org/licenses/MIT.
- */
-
-#include "fsverity.h"
-
-#include <fcntl.h>
-#include <getopt.h>
-
-static const struct option longopts[] = {
- {"hash-alg", required_argument, NULL, OPT_HASH_ALG},
- {"block-size", required_argument, NULL, OPT_BLOCK_SIZE},
- {"salt", required_argument, NULL, OPT_SALT},
- {"compact", no_argument, NULL, OPT_COMPACT},
- {"for-builtin-sig", no_argument, NULL, OPT_FOR_BUILTIN_SIG},
- {NULL, 0, NULL, 0}
-};
-
-/*
- * Compute the fs-verity digest of the given file(s), for offline signing.
- */
-int fsverity_cmd_digest(const struct fsverity_command *cmd,
- int argc, char *argv[])
-{
- struct filedes file = { .fd = -1 };
- struct libfsverity_merkle_tree_params tree_params = { .version = 1 };
- bool compact = false, for_builtin_sig = false;
- int status;
- int c;
-
- while ((c = getopt_long(argc, argv, "", longopts, NULL)) != -1) {
- switch (c) {
- case OPT_HASH_ALG:
- case OPT_BLOCK_SIZE:
- case OPT_SALT:
- if (!parse_tree_param(c, optarg, &tree_params))
- goto out_usage;
- break;
- case OPT_COMPACT:
- compact = true;
- break;
- case OPT_FOR_BUILTIN_SIG:
- for_builtin_sig = true;
- break;
- default:
- goto out_usage;
- }
- }
-
- argv += optind;
- argc -= optind;
-
- if (argc < 1)
- goto out_usage;
-
- for (int i = 0; i < argc; i++) {
- struct fsverity_formatted_digest *d = NULL;
- struct libfsverity_digest *digest = NULL;
- char digest_hex[FS_VERITY_MAX_DIGEST_SIZE * 2 +
- sizeof(*d) * 2 + 1];
-
- if (!open_file(&file, argv[i], O_RDONLY, 0))
- goto out_err;
-
- if (!get_file_size(&file, &tree_params.file_size))
- goto out_err;
-
- if (libfsverity_compute_digest(&file, read_callback,
- &tree_params, &digest) != 0) {
- error_msg("failed to compute digest");
- goto out_err;
- }
-
- ASSERT(digest->digest_size <= FS_VERITY_MAX_DIGEST_SIZE);
-
- if (for_builtin_sig) {
- /*
- * Format the digest for use with the built-in signature
- * support.
- */
- d = xzalloc(sizeof(*d) + digest->digest_size);
- memcpy(d->magic, "FSVerity", 8);
- d->digest_algorithm =
- cpu_to_le16(digest->digest_algorithm);
- d->digest_size = cpu_to_le16(digest->digest_size);
- memcpy(d->digest, digest->digest, digest->digest_size);
-
- bin2hex((const u8 *)d, sizeof(*d) + digest->digest_size,
- digest_hex);
- } else {
- bin2hex(digest->digest, digest->digest_size,
- digest_hex);
- }
-
- if (compact)
- printf("%s\n", digest_hex);
- else if (for_builtin_sig)
- printf("%s %s\n", digest_hex, argv[i]);
- else
- printf("%s:%s %s\n",
- libfsverity_get_hash_name(digest->digest_algorithm),
- digest_hex, argv[i]);
-
- filedes_close(&file);
- free(digest);
- free(d);
- }
- status = 0;
-out:
- destroy_tree_params(&tree_params);
- return status;
-
-out_err:
- filedes_close(&file);
- status = 1;
- goto out;
-
-out_usage:
- usage(cmd, stderr);
- status = 2;
- goto out;
-}
diff --git a/programs/cmd_sign.c b/programs/cmd_sign.c
deleted file mode 100644
index 47ba6a2..0000000
--- a/programs/cmd_sign.c
+++ /dev/null
@@ -1,133 +0,0 @@
-// SPDX-License-Identifier: MIT
-/*
- * The 'fsverity sign' command
- *
- * Copyright 2018 Google LLC
- *
- * Use of this source code is governed by an MIT-style
- * license that can be found in the LICENSE file or at
- * https://opensource.org/licenses/MIT.
- */
-
-#include "fsverity.h"
-
-#include <fcntl.h>
-#include <getopt.h>
-
-static bool write_signature(const char *filename, const u8 *sig, u32 sig_size)
-{
- struct filedes file;
- bool ok;
-
- if (!open_file(&file, filename, O_WRONLY|O_CREAT|O_TRUNC, 0644))
- return false;
- ok = full_write(&file, sig, sig_size);
- ok &= filedes_close(&file);
- return ok;
-}
-
-static const struct option longopts[] = {
- {"hash-alg", required_argument, NULL, OPT_HASH_ALG},
- {"block-size", required_argument, NULL, OPT_BLOCK_SIZE},
- {"salt", required_argument, NULL, OPT_SALT},
- {"key", required_argument, NULL, OPT_KEY},
- {"cert", required_argument, NULL, OPT_CERT},
- {NULL, 0, NULL, 0}
-};
-
-/* Sign a file for fs-verity by computing its digest, then signing it. */
-int fsverity_cmd_sign(const struct fsverity_command *cmd,
- int argc, char *argv[])
-{
- struct filedes file = { .fd = -1 };
- struct libfsverity_merkle_tree_params tree_params = { .version = 1 };
- struct libfsverity_signature_params sig_params = {};
- struct libfsverity_digest *digest = NULL;
- char digest_hex[FS_VERITY_MAX_DIGEST_SIZE * 2 + 1];
- u8 *sig = NULL;
- size_t sig_size;
- int status;
- int c;
-
- while ((c = getopt_long(argc, argv, "", longopts, NULL)) != -1) {
- switch (c) {
- case OPT_HASH_ALG:
- case OPT_BLOCK_SIZE:
- case OPT_SALT:
- if (!parse_tree_param(c, optarg, &tree_params))
- goto out_usage;
- break;
- case OPT_KEY:
- if (sig_params.keyfile != NULL) {
- error_msg("--key can only be specified once");
- goto out_usage;
- }
- sig_params.keyfile = optarg;
- break;
- case OPT_CERT:
- if (sig_params.certfile != NULL) {
- error_msg("--cert can only be specified once");
- goto out_usage;
- }
- sig_params.certfile = optarg;
- break;
- default:
- goto out_usage;
- }
- }
-
- argv += optind;
- argc -= optind;
-
- if (argc != 2)
- goto out_usage;
-
- if (sig_params.keyfile == NULL) {
- error_msg("Missing --key argument");
- goto out_usage;
- }
- if (sig_params.certfile == NULL)
- sig_params.certfile = sig_params.keyfile;
-
- if (!open_file(&file, argv[0], O_RDONLY, 0))
- goto out_err;
-
- if (!get_file_size(&file, &tree_params.file_size))
- goto out_err;
-
- if (libfsverity_compute_digest(&file, read_callback,
- &tree_params, &digest) != 0) {
- error_msg("failed to compute digest");
- goto out_err;
- }
-
- if (libfsverity_sign_digest(digest, &sig_params,
- &sig, &sig_size) != 0) {
- error_msg("failed to sign digest");
- goto out_err;
- }
-
- if (!write_signature(argv[1], sig, sig_size))
- goto out_err;
-
- ASSERT(digest->digest_size <= FS_VERITY_MAX_DIGEST_SIZE);
- bin2hex(digest->digest, digest->digest_size, digest_hex);
- printf("Signed file '%s' (%s:%s)\n", argv[0],
- libfsverity_get_hash_name(digest->digest_algorithm), digest_hex);
- status = 0;
-out:
- filedes_close(&file);
- destroy_tree_params(&tree_params);
- free(digest);
- free(sig);
- return status;
-
-out_err:
- status = 1;
- goto out;
-
-out_usage:
- usage(cmd, stderr);
- status = 2;
- goto out;
-}
diff --git a/programs/fsverity.h b/programs/fsverity.h
deleted file mode 100644
index 45c4fe1..0000000
--- a/programs/fsverity.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-/*
- * Private header for the 'fsverity' program
- *
- * Copyright 2018 Google LLC
- *
- * Use of this source code is governed by an MIT-style
- * license that can be found in the LICENSE file or at
- * https://opensource.org/licenses/MIT.
- */
-#ifndef PROGRAMS_FSVERITY_H
-#define PROGRAMS_FSVERITY_H
-
-#include "utils.h"
-#include "../common/fsverity_uapi.h"
-
-/*
- * Largest digest size among all hash algorithms supported by fs-verity.
- * This can be increased if needed.
- */
-#define FS_VERITY_MAX_DIGEST_SIZE 64
-
-enum {
- OPT_BLOCK_SIZE,
- OPT_CERT,
- OPT_COMPACT,
- OPT_FOR_BUILTIN_SIG,
- OPT_HASH_ALG,
- OPT_KEY,
- OPT_SALT,
- OPT_SIGNATURE,
-};
-
-struct fsverity_command;
-
-/* cmd_digest.c */
-int fsverity_cmd_digest(const struct fsverity_command *cmd,
- int argc, char *argv[]);
-
-/* cmd_enable.c */
-int fsverity_cmd_enable(const struct fsverity_command *cmd,
- int argc, char *argv[]);
-
-/* cmd_measure.c */
-int fsverity_cmd_measure(const struct fsverity_command *cmd,
- int argc, char *argv[]);
-
-/* cmd_sign.c */
-int fsverity_cmd_sign(const struct fsverity_command *cmd,
- int argc, char *argv[]);
-
-/* fsverity.c */
-void usage(const struct fsverity_command *cmd, FILE *fp);
-bool parse_tree_param(int opt_char, const char *arg,
- struct libfsverity_merkle_tree_params *params);
-void destroy_tree_params(struct libfsverity_merkle_tree_params *params);
-
-#endif /* PROGRAMS_FSVERITY_H */
diff --git a/programs/test_compute_digest.c b/programs/test_compute_digest.c
deleted file mode 100644
index e7f2645..0000000
--- a/programs/test_compute_digest.c
+++ /dev/null
@@ -1,310 +0,0 @@
-// SPDX-License-Identifier: MIT
-/*
- * Test libfsverity_compute_digest().
- *
- * Copyright 2020 Google LLC
- *
- * Use of this source code is governed by an MIT-style
- * license that can be found in the LICENSE file or at
- * https://opensource.org/licenses/MIT.
- */
-
-#include "utils.h"
-
-#include <ctype.h>
-#include <inttypes.h>
-
-struct mem_file {
- u8 *data;
- size_t size;
- size_t offset;
-};
-
-static int read_fn(void *fd, void *buf, size_t count)
-{
- struct mem_file *f = fd;
-
- ASSERT(count <= f->size - f->offset);
- memcpy(buf, &f->data[f->offset], count);
- f->offset += count;
- return 0;
-}
-
-static int error_read_fn(void *fd __attribute__((unused)),
- void *buf __attribute__((unused)),
- size_t count __attribute__((unused)))
-{
- return -EIO;
-}
-
-static const struct test_case {
- u32 hash_algorithm;
- u32 block_size;
- const char *salt;
- u64 file_size;
- const char *digest;
-} test_cases[] = {
- { /* large file */
- .hash_algorithm = FS_VERITY_HASH_ALG_SHA256,
- .file_size = 1000000,
- .block_size = 4096,
- .digest = "\x48\xdf\x0c\x46\x23\x29\xcd\x87"
- "\x96\x61\xbd\x05\xb3\x9a\xa8\x1b"
- "\x05\xcc\x16\xaf\xd2\x7a\x71\x96"
- "\xa5\x59\xda\x83\x53\x1d\x39\xd9",
- }, { /* small file */
- .hash_algorithm = FS_VERITY_HASH_ALG_SHA256,
- .file_size = 100000,
- .block_size = 4096,
- .digest = "\xf2\x09\x6a\x36\xc5\xcd\xca\x4f"
- "\xa3\x3e\xe8\x85\x28\x33\x15\x0b"
- "\xb3\x24\x99\x2e\x54\x17\xa9\xd5"
- "\x71\xf1\xbf\xff\xf7\x3b\x9e\xfc",
- }, { /* single-block file */
- .hash_algorithm = FS_VERITY_HASH_ALG_SHA256,
- .file_size = 4096,
- .block_size = 4096,
- .digest = "\x6a\xc3\x99\x79\x01\x6e\x3d\xdf"
- "\x3d\x39\xff\xf6\xcb\x98\x4f\x7c"
- "\x11\x8a\xcd\xf1\x85\x29\x19\xf5"
- "\xc1\x00\xc4\xb1\x42\xc1\x81\x8e",
- }, { /* tiny file */
- .hash_algorithm = FS_VERITY_HASH_ALG_SHA256,
- .file_size = 1,
- .block_size = 4096,
- .digest = "\xb8\x03\x42\x95\x03\xd9\x59\x15"
- "\x82\x9b\x29\xfd\xbc\x8b\xba\xd1"
- "\x42\xf3\xab\xfd\x11\xb1\xca\xdf"
- "\x55\x26\x58\x2e\x68\x5c\x05\x51",
- }, { /* empty file */
- .hash_algorithm = FS_VERITY_HASH_ALG_SHA256,
- .file_size = 0,
- .block_size = 4096,
- .digest = "\x3d\x24\x8c\xa5\x42\xa2\x4f\xc6"
- "\x2d\x1c\x43\xb9\x16\xea\xe5\x01"
- "\x68\x78\xe2\x53\x3c\x88\x23\x84"
- "\x80\xb2\x61\x28\xa1\xf1\xaf\x95",
- }, { /* salt */
- .hash_algorithm = FS_VERITY_HASH_ALG_SHA256,
- .file_size = 1000000,
- .block_size = 4096,
- .salt = "abcd",
- .digest = "\x91\x79\x00\xb0\xd2\x99\x45\x4a"
- "\xa3\x04\xd5\xde\xbc\x6f\x39\xe4"
- "\xaf\x7b\x5a\xbe\x33\xbd\xbc\x56"
- "\x8d\x5d\x8f\x1e\x5c\x4d\x86\x52",
- }, { /* max length salt (32 bytes) */
- .hash_algorithm = FS_VERITY_HASH_ALG_SHA256,
- .file_size = 1000000,
- .block_size = 4096,
- .salt = "0123456789:;<=>?@ABCDEFGHIJKLMNO",
- .digest = "\xbc\x2d\x70\x32\x4c\x04\x8c\x22"
- "\x0a\x2c\xb1\x90\x83\x21\x40\x86"
- "\x3e\xb2\x68\xe6\x80\x42\x79\x39"
- "\xe5\xd4\x67\xbe\xa5\xec\x5a\xd9",
- }, { /* 1K block size */
- .hash_algorithm = FS_VERITY_HASH_ALG_SHA256,
- .file_size = 1000000,
- .block_size = 1024,
- .digest = "\xe9\xdf\x92\x7c\x14\xfc\xb9\x61"
- "\xd5\xf5\x1c\x66\x6d\x8a\xe4\xc1"
- "\x4f\xe4\xff\x98\xa3\x74\xc7\x33"
- "\xe8\x98\xd0\x0c\x9e\x74\xa8\xe3",
- }, { /* 512-byte block size */
- .hash_algorithm = FS_VERITY_HASH_ALG_SHA256,
- .file_size = 1000000,
- .block_size = 512,
- .digest = "\x03\x93\xee\x3d\xfd\x4a\x28\x96"
- "\x6e\x2a\xf4\xe0\x7c\xfa\x5b\x03"
- "\x2c\x30\xda\x5b\xb8\xe8\xef\x63"
- "\xb9\xa5\x5b\xf9\x63\x26\x23\x34",
- }, { /* 64K block size */
- .hash_algorithm = FS_VERITY_HASH_ALG_SHA256,
- .file_size = 1000000,
- .block_size = 65536,
- .digest = "\xf3\xb6\x41\x8f\x26\xd4\xd0\xe7"
- "\x47\x28\x19\x3b\xae\x76\xf1\x5c"
- "\xb4\xbb\x2c\xe9\x77\x74\x48\xd7"
- "\x6b\xd8\x13\x8b\x69\xec\x61\xc2",
- }, { /* SHA-512 */
- .hash_algorithm = FS_VERITY_HASH_ALG_SHA512,
- .file_size = 1000000,
- .block_size = 4096,
- .salt = "abcd",
- .digest = "\x84\x25\xc6\xd0\xc9\x4f\x84\xed"
- "\x90\x4c\x12\x93\x68\x45\xfb\xb7"
- "\xaf\x99\x53\x75\x37\x89\x71\x2d"
- "\xcc\x3b\xe1\x42\xdb\x3d\x4b\x6b"
- "\x47\xa3\x99\xad\x52\xaa\x60\x92"
- "\x56\xce\x29\xa9\x60\xbf\x4b\xb0"
- "\xe5\x95\xec\x38\x6c\xa5\x8c\x06"
- "\x51\x9d\x54\x6d\xc5\xb1\x97\xbb",
- }, { /* default hash algorithm (SHA-256) and block size (4096) */
- .file_size = 100000,
- .digest = "\xf2\x09\x6a\x36\xc5\xcd\xca\x4f"
- "\xa3\x3e\xe8\x85\x28\x33\x15\x0b"
- "\xb3\x24\x99\x2e\x54\x17\xa9\xd5"
- "\x71\xf1\xbf\xff\xf7\x3b\x9e\xfc",
- },
-};
-
-static void fix_digest_and_print(const struct test_case *t,
- const struct libfsverity_digest *d)
-{
- char alg_name[32] = {};
- size_t i;
-
- strncpy(alg_name, libfsverity_get_hash_name(t->hash_algorithm),
- sizeof(alg_name) - 1);
- for (i = 0; i < sizeof(alg_name) - 1; i++)
- alg_name[i] = toupper((u8)alg_name[i]);
-
- printf("\t}, {\n"
- "\t\t.hash_algorithm = FS_VERITY_HASH_ALG_%s,\n"
- "\t\t.file_size = %" PRIu64 ",\n"
- "\t\t.block_size = %u,\n",
- alg_name, t->file_size, t->block_size);
- if (t->salt != NULL)
- printf("\t\t.salt = \"%s\",\n", t->salt);
- for (i = 0; i < d->digest_size; i++) {
- if (i == 0)
- printf("\t\t.digest = \"");
- else if (i % 8 == 0)
- printf("\t\t\t \"");
- printf("\\x%02x", d->digest[i]);
- if (i + 1 == d->digest_size)
- printf("\",\n");
- else if (i % 8 == 7)
- printf("\"\n");
- }
-}
-
-static void test_invalid_params(void)
-{
- struct mem_file f = { .data = (u8 *)"abcd", .size = 4 };
- struct libfsverity_merkle_tree_params good_params = {
- .version = 1,
- .hash_algorithm = FS_VERITY_HASH_ALG_SHA256,
- .file_size = 4,
- .block_size = 4096,
- };
- struct libfsverity_merkle_tree_params params;
- struct libfsverity_digest *d = NULL;
-
- libfsverity_set_error_callback(NULL);
-
- ASSERT(libfsverity_compute_digest(&f, read_fn, &good_params, &d) == 0);
- f.offset = 0;
- free(d);
- d = NULL;
-
- /* missing required arguments */
- ASSERT(libfsverity_compute_digest(&f, NULL, &good_params, &d) == -EINVAL);
- ASSERT(libfsverity_compute_digest(&f, read_fn, NULL, &d) == -EINVAL);
- ASSERT(libfsverity_compute_digest(&f, read_fn, &good_params, NULL) == -EINVAL);
-
- /* bad version */
- params = good_params;
- params.version = 0;
- ASSERT(libfsverity_compute_digest(&f, read_fn, &params, &d) == -EINVAL);
- params.version = 1000;
- ASSERT(libfsverity_compute_digest(&f, read_fn, &params, &d) == -EINVAL);
-
- /* bad hash_algorithm */
- params = good_params;
- params.hash_algorithm = 1000;
- ASSERT(libfsverity_compute_digest(&f, read_fn, &params, &d) == -EINVAL);
-
- /* bad block_size */
- params = good_params;
- params.block_size = 1;
- ASSERT(libfsverity_compute_digest(&f, read_fn, &params, &d) == -EINVAL);
- params.block_size = 4097;
- ASSERT(libfsverity_compute_digest(&f, read_fn, &params, &d) == -EINVAL);
-
- /* bad salt_size */
- params = good_params;
- params.salt_size = 1000;
- ASSERT(libfsverity_compute_digest(&f, read_fn, &params, &d) == -EINVAL);
- params.salt = (u8 *)"";
- ASSERT(libfsverity_compute_digest(&f, read_fn, &params, &d) == -EINVAL);
-
- /* bad reserved fields */
- params = good_params;
- params.reserved1[0] = 1;
- ASSERT(libfsverity_compute_digest(&f, read_fn, &params, &d) == -EINVAL);
- params = good_params;
- params.reserved1[ARRAY_SIZE(params.reserved1) - 1] = 1;
- ASSERT(libfsverity_compute_digest(&f, read_fn, &params, &d) == -EINVAL);
- params = good_params;
- params.reserved2[0] = 1;
- ASSERT(libfsverity_compute_digest(&f, read_fn, &params, &d) == -EINVAL);
- params = good_params;
- params.reserved2[ARRAY_SIZE(params.reserved2) - 1] = 1;
- ASSERT(libfsverity_compute_digest(&f, read_fn, &params, &d) == -EINVAL);
-
- /* error reading file */
- ASSERT(libfsverity_compute_digest(&f, error_read_fn, &good_params, &d) == -EIO);
-
- ASSERT(d == NULL);
-}
-
-int main(int argc, char *argv[])
-{
- const bool update = (argc == 2 && !strcmp(argv[1], "--update"));
- size_t i;
- struct mem_file f = {};
- struct libfsverity_merkle_tree_params params;
- struct libfsverity_digest *d;
- int err;
-
- install_libfsverity_error_handler();
-
- for (i = 0; i < ARRAY_SIZE(test_cases); i++)
- f.size = max(f.size, test_cases[i].file_size);
-
- f.data = xmalloc(f.size);
- for (i = 0; i < f.size; i++)
- f.data[i] = (i % 11) + (i % 439) + (i % 1103);
-
- for (i = 0; i < ARRAY_SIZE(test_cases); i++) {
- u32 expected_alg = test_cases[i].hash_algorithm ?:
- FS_VERITY_HASH_ALG_SHA256;
-
- memset(&params, 0, sizeof(params));
- params.version = 1;
- params.hash_algorithm = test_cases[i].hash_algorithm;
- params.file_size = test_cases[i].file_size;
- params.block_size = test_cases[i].block_size;
- if (test_cases[i].salt) {
- params.salt = (const u8 *)test_cases[i].salt;
- params.salt_size = strlen(test_cases[i].salt);
- }
-
- f.size = test_cases[i].file_size;
- f.offset = 0;
-
- err = libfsverity_compute_digest(&f, read_fn, &params, &d);
- ASSERT(err == 0);
-
- ASSERT(d->digest_algorithm == expected_alg);
- ASSERT(d->digest_size ==
- libfsverity_get_digest_size(expected_alg));
- if (update)
- fix_digest_and_print(&test_cases[i], d);
- else
- ASSERT(!memcmp(d->digest, test_cases[i].digest,
- d->digest_size));
- free(d);
- d = NULL;
- }
- free(f.data);
- if (update) {
- printf("\t}\n");
- return 1;
- }
-
- test_invalid_params();
- printf("test_compute_digest passed\n");
- return 0;
-}
diff --git a/programs/test_hash_algs.c b/programs/test_hash_algs.c
deleted file mode 100644
index ede9f05..0000000
--- a/programs/test_hash_algs.c
+++ /dev/null
@@ -1,45 +0,0 @@
-// SPDX-License-Identifier: MIT
-/*
- * Test the hash algorithm-related libfsverity APIs.
- *
- * Copyright 2020 Google LLC
- *
- * Use of this source code is governed by an MIT-style
- * license that can be found in the LICENSE file or at
- * https://opensource.org/licenses/MIT.
- */
-
-#include "utils.h"
-
-#define SHA256_DIGEST_SIZE 32
-#define SHA512_DIGEST_SIZE 64
-
-int main(void)
-{
- install_libfsverity_error_handler();
-
- ASSERT(libfsverity_get_digest_size(0) == -1);
- ASSERT(libfsverity_get_hash_name(0) == NULL);
- ASSERT(libfsverity_find_hash_alg_by_name("bad") == 0);
- ASSERT(libfsverity_find_hash_alg_by_name(NULL) == 0);
-
- ASSERT(libfsverity_get_digest_size(100) == -1);
- ASSERT(libfsverity_get_hash_name(100) == NULL);
-
- ASSERT(libfsverity_get_digest_size(FS_VERITY_HASH_ALG_SHA256) ==
- SHA256_DIGEST_SIZE);
- ASSERT(!strcmp("sha256",
- libfsverity_get_hash_name(FS_VERITY_HASH_ALG_SHA256)));
- ASSERT(libfsverity_find_hash_alg_by_name("sha256") ==
- FS_VERITY_HASH_ALG_SHA256);
-
- ASSERT(libfsverity_get_digest_size(FS_VERITY_HASH_ALG_SHA512) ==
- SHA512_DIGEST_SIZE);
- ASSERT(!strcmp("sha512",
- libfsverity_get_hash_name(FS_VERITY_HASH_ALG_SHA512)));
- ASSERT(libfsverity_find_hash_alg_by_name("sha512") ==
- FS_VERITY_HASH_ALG_SHA512);
-
- printf("test_hash_algs passed\n");
- return 0;
-}
diff --git a/programs/test_sign_digest.c b/programs/test_sign_digest.c
deleted file mode 100644
index 412c6cb..0000000
--- a/programs/test_sign_digest.c
+++ /dev/null
@@ -1,57 +0,0 @@
-// SPDX-License-Identifier: MIT
-/*
- * Test libfsverity_sign_digest().
- *
- * Copyright 2020 Google LLC
- *
- * Use of this source code is governed by an MIT-style
- * license that can be found in the LICENSE file or at
- * https://opensource.org/licenses/MIT.
- */
-
-#include "utils.h"
-
-#include <fcntl.h>
-
-#define SHA256_DIGEST_SIZE 32
-
-int main(void)
-{
- struct libfsverity_digest *d = xzalloc(sizeof(*d) + SHA256_DIGEST_SIZE);
- const struct libfsverity_signature_params params = {
- .keyfile = "testdata/key.pem",
- .certfile = "testdata/cert.pem",
- };
- u8 *sig;
- size_t sig_size;
- struct filedes file;
- u8 *expected_sig;
- u64 expected_sig_size;
- int err;
-
- install_libfsverity_error_handler();
-
- d->digest_algorithm = FS_VERITY_HASH_ALG_SHA256;
- d->digest_size = SHA256_DIGEST_SIZE;
- memcpy(d->digest,
- "\x91\x79\x00\xb0\xd2\x99\x45\x4a\xa3\x04\xd5\xde\xbc\x6f\x39"
- "\xe4\xaf\x7b\x5a\xbe\x33\xbd\xbc\x56\x8d\x5d\x8f\x1e\x5c\x4d"
- "\x86\x52", SHA256_DIGEST_SIZE);
-
- err = libfsverity_sign_digest(d, &params, &sig, &sig_size);
- ASSERT(err == 0);
-
- ASSERT(open_file(&file, "testdata/file.sig", O_RDONLY, 0));
- ASSERT(get_file_size(&file, &expected_sig_size));
- ASSERT(sig_size == expected_sig_size);
- expected_sig = xmalloc(sig_size);
- ASSERT(full_read(&file, expected_sig, sig_size));
- ASSERT(!memcmp(sig, expected_sig, sig_size));
-
- free(d);
- free(sig);
- free(expected_sig);
- filedes_close(&file);
- printf("test_sign_digest passed\n");
- return 0;
-}
diff --git a/programs/utils.h b/programs/utils.h
deleted file mode 100644
index ab5005f..0000000
--- a/programs/utils.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-/*
- * Utility functions for programs
- *
- * Copyright 2018 Google LLC
- *
- * Use of this source code is governed by an MIT-style
- * license that can be found in the LICENSE file or at
- * https://opensource.org/licenses/MIT.
- */
-#ifndef PROGRAMS_UTILS_H
-#define PROGRAMS_UTILS_H
-
-#include "libfsverity.h"
-#include "../common/common_defs.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-void *xmalloc(size_t size);
-void *xzalloc(size_t size);
-void *xmemdup(const void *mem, size_t size);
-char *xstrdup(const char *s);
-
-__printf(1, 2) __cold void error_msg(const char *format, ...);
-__printf(1, 2) __cold void error_msg_errno(const char *format, ...);
-__printf(1, 2) __cold __noreturn void fatal_error(const char *format, ...);
-__cold __noreturn void assertion_failed(const char *expr,
- const char *file, int line);
-
-#define ASSERT(e) ({ if (!(e)) assertion_failed(#e, __FILE__, __LINE__); })
-
-void install_libfsverity_error_handler(void);
-
-struct filedes {
- int fd;
- char *name; /* filename, for logging or error messages */
-};
-
-bool open_file(struct filedes *file, const char *filename, int flags, int mode);
-bool get_file_size(struct filedes *file, u64 *size_ret);
-bool full_read(struct filedes *file, void *buf, size_t count);
-bool full_write(struct filedes *file, const void *buf, size_t count);
-bool filedes_close(struct filedes *file);
-int read_callback(void *file, void *buf, size_t count);
-
-bool hex2bin(const char *hex, u8 *bin, size_t bin_len);
-void bin2hex(const u8 *bin, size_t bin_len, char *hex);
-
-#endif /* PROGRAMS_UTILS_H */
diff --git a/scripts/do-release.sh b/scripts/do-release.sh
deleted file mode 100755
index 352fcf1..0000000
--- a/scripts/do-release.sh
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/bin/bash
-# SPDX-License-Identifier: MIT
-# Copyright 2020 Google LLC
-#
-# Use of this source code is governed by an MIT-style
-# license that can be found in the LICENSE file or at
-# https://opensource.org/licenses/MIT.
-
-set -e -u -o pipefail
-cd "$(dirname "$0")/.."
-
-if [ $# != 1 ]; then
- echo "Usage: $0 VERS" 1>&2
- echo " e.g. $0 1.0" 1>&2
- exit 2
-fi
-
-VERS=$1
-PKG=fsverity-utils-$VERS
-
-git checkout -f
-git clean -fdx
-./scripts/run-tests.sh
-git clean -fdx
-
-major=$(echo "$VERS" | cut -d. -f1)
-minor=$(echo "$VERS" | cut -d. -f2)
-sed -E -i -e "/FSVERITY_UTILS_MAJOR_VERSION/s/[0-9]+/$major/" \
- -e "/FSVERITY_UTILS_MINOR_VERSION/s/[0-9]+/$minor/" \
- include/libfsverity.h
-sed -E -i "/Version:/s/[0-9]+\.[0-9]+/$VERS/" \
- lib/libfsverity.pc.in
-git commit -a --signoff --message="v$VERS"
-git tag --sign "v$VERS" --message="$PKG"
-
-git archive "v$VERS" --prefix="$PKG/" > "$PKG.tar"
-tar xf "$PKG.tar"
-( cd "$PKG" && make check )
-rm -r "$PKG"
-
-gpg --detach-sign --armor "$PKG.tar"
-DESTDIR=/pub/linux/kernel/people/ebiggers/fsverity-utils/v$VERS
-kup mkdir "$DESTDIR"
-kup put "$PKG.tar" "$PKG.tar.asc" "$DESTDIR/$PKG.tar.gz"
-git push
-git push --tags
diff --git a/scripts/run-sparse.sh b/scripts/run-sparse.sh
deleted file mode 100755
index f75b837..0000000
--- a/scripts/run-sparse.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/bin/bash
-# SPDX-License-Identifier: MIT
-# Copyright 2020 Google LLC
-#
-# Use of this source code is governed by an MIT-style
-# license that can be found in the LICENSE file or at
-# https://opensource.org/licenses/MIT.
-
-set -e -u -o pipefail
-
-find . -name '*.c' | while read -r file; do
- sparse "$file" -gcc-base-dir "$(gcc --print-file-name=)" \
- -Iinclude -D_FILE_OFFSET_BITS=64 -Wbitwise -D_GNU_SOURCE
-done
diff --git a/scripts/run-tests.sh b/scripts/run-tests.sh
deleted file mode 100755
index 530fe34..0000000
--- a/scripts/run-tests.sh
+++ /dev/null
@@ -1,187 +0,0 @@
-#!/bin/bash
-# SPDX-License-Identifier: MIT
-# Copyright 2020 Google LLC
-#
-# Use of this source code is governed by an MIT-style
-# license that can be found in the LICENSE file or at
-# https://opensource.org/licenses/MIT.
-#
-#
-# Test script for fsverity-utils. Runs 'make check' in lots of configurations,
-# runs static analysis, and does a few other tests.
-#
-# Note: for more test coverage, in addition to running this script, also build
-# fsverity-utils into a kvm-xfstests test appliance and run
-# 'kvm-xfstests -c ext4,f2fs -g verity'
-
-set -e -u -o pipefail
-cd "$(dirname "$0")/.."
-
-log() {
- echo "[$(date)] $*" 1>&2
-}
-
-fail() {
- echo "FAIL: $*" 1>&2
- exit 1
-}
-
-TMPDIR=$(mktemp -d -t libfsverity_test.XXXXXXXXX)
-trap 'rm -r "$TMPDIR"' EXIT
-
-# Both stdout and stderr go to log file.
-# Only stderr goes to terminal.
-echo "Starting fsverity-utils tests. See run-tests.log for full output."
-rm -f run-tests.log
-exec >> run-tests.log
-exec 2> >(tee -ia run-tests.log 1>&2)
-
-MAKE="make -j$(getconf _NPROCESSORS_ONLN)"
-
-log "Build and test with statically linking"
-$MAKE CFLAGS="-Werror"
-if ldd fsverity | grep libfsverity.so; then
- fail "fsverity binary should be statically linked to libfsverity by default"
-fi
-./fsverity --version
-
-log "Check that all global symbols are prefixed with \"libfsverity_\""
-if nm libfsverity.a | grep ' T ' | grep -v " libfsverity_"; then
- fail "Some global symbols are not prefixed with \"libfsverity_\""
-fi
-
-log "Build and test with dynamic linking"
-$MAKE CFLAGS="-Werror" USE_SHARED_LIB=1 check
-if ! ldd fsverity | grep libfsverity.so; then
- fail "fsverity binary should be dynamically linked to libfsverity when USE_SHARED_LIB=1"
-fi
-
-log "Check that all exported symbols are prefixed with \"libfsverity_\""
-if nm libfsverity.so | grep ' T ' | grep -v " libfsverity_"; then
- fail "Some exported symbols are not prefixed with \"libfsverity_\""
-fi
-
-log "Test using libfsverity from C++ program"
-cat > "$TMPDIR/test.cc" <<EOF
-#include <libfsverity.h>
-#include <iostream>
-int main()
-{
- std::cout << libfsverity_get_digest_size(FS_VERITY_HASH_ALG_SHA256) << std::endl;
-}
-EOF
-c++ -Wall -Werror "$TMPDIR/test.cc" -Iinclude -L. -lfsverity -o "$TMPDIR/test"
-[ "$(LD_LIBRARY_PATH=. "$TMPDIR/test")" = "32" ]
-rm "${TMPDIR:?}"/*
-
-log "Check that build doesn't produce untracked files"
-$MAKE CFLAGS="-Werror" all test_programs
-if git status --short | grep -q '^??'; then
- git status
- fail "Build produced untracked files (check 'git status'). Missing gitignore entry?"
-fi
-
-log "Test that 'make uninstall' uninstalls all files"
-make DESTDIR="$TMPDIR" install
-if [ "$(find "$TMPDIR" -type f -o -type l | wc -l)" = 0 ]; then
- fail "'make install' didn't install any files"
-fi
-make DESTDIR="$TMPDIR" uninstall
-if [ "$(find "$TMPDIR" -type f -o -type l | wc -l)" != 0 ]; then
- fail "'make uninstall' didn't uninstall all files"
-fi
-rm -r "${TMPDIR:?}"/*
-
-log "Build, install, and uninstall with dash"
-make clean SHELL=/bin/dash
-make DESTDIR="$TMPDIR" SHELL=/bin/dash install
-make DESTDIR="$TMPDIR" SHELL=/bin/dash uninstall
-
-log "Check that all files have license and copyright info"
-list="$TMPDIR/filelist"
-filter_license_info() {
- # files to exclude from license and copyright info checks
- grep -E -v '(\.gitignore|LICENSE|NEWS|README|testdata|fsverity_uapi\.h|libfsverity\.pc\.in)'
-}
-git grep -L 'SPDX-License-Identifier: MIT' \
- | filter_license_info > "$list" || true
-if [ -s "$list" ]; then
- fail "The following files are missing an appropriate SPDX license identifier: $(<"$list")"
-fi
-# For now some people still prefer a free-form license statement, not just SPDX.
-git grep -L 'Use of this source code is governed by an MIT-style' \
- | filter_license_info > "$list" || true
-if [ -s "$list" ]; then
- fail "The following files are missing an appropriate license statement: $(<"$list")"
-fi
-git grep -L '\<Copyright\>' | filter_license_info > "$list" || true
-if [ -s "$list" ]; then
- fail "The following files are missing a copyright statement: $(<"$list")"
-fi
-rm "$list"
-
-log "Build and test with gcc (-O2)"
-$MAKE CC=gcc CFLAGS="-O2 -Werror" check
-
-log "Build and test with gcc (-O3)"
-$MAKE CC=gcc CFLAGS="-O3 -Werror" check
-
-log "Build and test with gcc (32-bit)"
-$MAKE CC=gcc CFLAGS="-O2 -Werror -m32" check
-
-log "Build and test with clang (-O2)"
-$MAKE CC=clang CFLAGS="-O2 -Werror" check
-
-log "Build and test with clang (-O3)"
-$MAKE CC=clang CFLAGS="-O3 -Werror" check
-
-log "Build and test with clang + UBSAN"
-$MAKE CC=clang \
- CFLAGS="-O2 -Werror -fsanitize=undefined -fno-sanitize-recover=undefined" \
- check
-
-log "Build and test with clang + ASAN"
-$MAKE CC=clang \
- CFLAGS="-O2 -Werror -fsanitize=address -fno-sanitize-recover=address" \
- check
-
-log "Build and test with clang + unsigned integer overflow sanitizer"
-$MAKE CC=clang \
- CFLAGS="-O2 -Werror -fsanitize=unsigned-integer-overflow -fno-sanitize-recover=unsigned-integer-overflow" \
- check
-
-log "Build and test with clang + CFI"
-$MAKE CC=clang CFLAGS="-O2 -Werror -fsanitize=cfi -flto -fvisibility=hidden" \
- check
-
-log "Build and test with valgrind"
-$MAKE TEST_WRAPPER_PROG="valgrind --quiet --error-exitcode=100 --leak-check=full --errors-for-leak-kinds=all" \
- CFLAGS="-O2 -Werror" check
-
-log "Build and test using BoringSSL instead of OpenSSL"
-BSSL=$HOME/src/boringssl
-$MAKE CFLAGS="-O2 -Werror" LDFLAGS="-L$BSSL/build/crypto" \
- CPPFLAGS="-I$BSSL/include" LDLIBS="-lcrypto -lpthread" check
-
-log "Build and test using -funsigned-char"
-$MAKE CFLAGS="-O2 -Werror -funsigned-char" check
-
-log "Build and test using -fsigned-char"
-$MAKE CFLAGS="-O2 -Werror -fsigned-char" check
-
-log "Cross-compile for Windows (32-bit)"
-$MAKE CC=i686-w64-mingw32-gcc CFLAGS="-O2 -Werror"
-
-log "Cross-compile for Windows (64-bit)"
-$MAKE CC=x86_64-w64-mingw32-gcc CFLAGS="-O2 -Werror"
-
-log "Run sparse"
-./scripts/run-sparse.sh
-
-log "Run clang static analyzer"
-scan-build --status-bugs make CFLAGS="-O2 -Werror" all test_programs
-
-log "Run shellcheck"
-shellcheck scripts/*.sh 1>&2
-
-log "All tests passed!"
diff --git a/testdata/cert.pem b/testdata/cert.pem
deleted file mode 100644
index c63b965..0000000
--- a/testdata/cert.pem
+++ /dev/null
@@ -1,31 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIFazCCA1OgAwIBAgIUYaRYcyZGDIv9fIxx/RoJwQu23+owDQYJKoZIhvcNAQEL
-BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
-GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMDA1MTUwMjUyMzFaFw0yMDA2
-MTQwMjUyMzFaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw
-HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggIiMA0GCSqGSIb3DQEB
-AQUAA4ICDwAwggIKAoICAQC5lXk9otBz/VM/tbvBBK6sK//HE+q3ctY4+fPVv3Ob
-D1YNYuWRD59U+7K8fVUfZlXyjgxt3n4VPzkLgRSr/w5YUTa5NEOVJIltKT4ugswL
-5oY8eRVSuIr1O+vTbu+EpUk3DhTaFkalVzwspwipBeiVTDO9kh0NAueRk2HyLJte
-IoPyfzSCKxg9sED6/WtLFqrhDb5+1qeGoMNGM66ueWXKX0QjomMEODGXC04ypIY3
-sTwB+sYhZUe3YRpY0HyaVNh/6cxCxSiKr2jkC5UL+ry+46EJerNZbKmeqqyqmhXh
-P2cHv8MO91zdH1xbXUUenLcdpK/0oq+/sTAVV1/qPvnAofpN8tdZdrH65JD753jt
-s+lH/f0iGuKAb9ZpLOTM2d3wjY13OcHElj0zu2Usw9PXQpTK/DYlbcapOI4NTVyU
-NpK3yP4i5dPnkHoxpjLWz75Eq6gP9ZXohGq3YG0LxtvELWfaFmpzEUTlD59hJJOZ
-ELGxAXzsxLbelX/EmpX+GIqnFBpdMIuPO4HEfJwD5IcdeHqGl2iH9LIqsY5DcGj4
-hnqYplIYYk5mWgbhkexRbJIGNdn8WyXlraVp2MoSr3p7xJbmo0qYRRtt3kQShzDG
-0FrZX7wqxemc/g/hr+g2xqMQj0nYLehDeodqxA2n9grDUr4AdgQyxXDMUkGZdrg3
-cwIDAQABo1MwUTAdBgNVHQ4EFgQUxpaj6YjgLFyh9UVM71hf18cb/hkwHwYDVR0j
-BBgwFoAUxpaj6YjgLFyh9UVM71hf18cb/hkwDwYDVR0TAQH/BAUwAwEB/zANBgkq
-hkiG9w0BAQsFAAOCAgEAQnXMCgI+eSjK+l3nrpE+TRrXZhHeB0aT3gilVtBqFM95
-GxkLzOgJnW4SU+BCKTiGjwhCEXQiFj6UNDrI7vaNzmurI370uqmC9/pwKn4/L27V
-ToqLHk5d8kmvjSJyfgY/9H73srzHjNcqLG3uy+JP3/fIzaUzy7x9OUJtzdH19zic
-b61kCbqe6TJrlpL0Y50FY91QTzupsIS9IsAAeYXrJiEwpkXv/O9c51swtGZmQhVD
-TDn4B2aKOHecR+gKZQbPcuwTCbNLDRRPT4q0IM9yKjUxIM8vkAaxlrW3O7fgqUV0
-GU3/i0zZugq2XEludF3VelrqMUhSMqaREAtRUe3ufipwEsovDa43Hr9P6bINAfU3
-92Kv6adgeKZc4DmuEg6sFje/ET85teioHtwmjviJu6vnkbZg7x+IU01Y6YHboz/z
-hTAjz9g6owgdsbTG9nptvgJllY83zBtnAGOqhJLNVZ+TC3pbbKht/7sT+s+WP2+K
-81oZ3gmxIr6myMVyR5CCt+FNJ1hFxYNBJDao35iiZLxDe2s5nMJKHYezUY60ujqT
-Ljv3Ku4uAk5PgXltZnWGz152ntjopA0gbnlU4f+SgnmPoBFcvn36BcUQWQbTDqmh
-h+Y0OaXR3x/27M/qkPBov4IAfoCkWeF7i02wxwtdTLiSF7OjTDkQXtZemUzN5+w=
------END CERTIFICATE-----
diff --git a/testdata/file.sig b/testdata/file.sig
deleted file mode 100644
index 1ba61f8..0000000
--- a/testdata/file.sig
+++ /dev/null
Binary files differ
diff --git a/testdata/key.pem b/testdata/key.pem
deleted file mode 100644
index e76db4c..0000000
--- a/testdata/key.pem
+++ /dev/null
@@ -1,52 +0,0 @@
------BEGIN PRIVATE KEY-----
-MIIJQQIBADANBgkqhkiG9w0BAQEFAASCCSswggknAgEAAoICAQC5lXk9otBz/VM/
-tbvBBK6sK//HE+q3ctY4+fPVv3ObD1YNYuWRD59U+7K8fVUfZlXyjgxt3n4VPzkL
-gRSr/w5YUTa5NEOVJIltKT4ugswL5oY8eRVSuIr1O+vTbu+EpUk3DhTaFkalVzws
-pwipBeiVTDO9kh0NAueRk2HyLJteIoPyfzSCKxg9sED6/WtLFqrhDb5+1qeGoMNG
-M66ueWXKX0QjomMEODGXC04ypIY3sTwB+sYhZUe3YRpY0HyaVNh/6cxCxSiKr2jk
-C5UL+ry+46EJerNZbKmeqqyqmhXhP2cHv8MO91zdH1xbXUUenLcdpK/0oq+/sTAV
-V1/qPvnAofpN8tdZdrH65JD753jts+lH/f0iGuKAb9ZpLOTM2d3wjY13OcHElj0z
-u2Usw9PXQpTK/DYlbcapOI4NTVyUNpK3yP4i5dPnkHoxpjLWz75Eq6gP9ZXohGq3
-YG0LxtvELWfaFmpzEUTlD59hJJOZELGxAXzsxLbelX/EmpX+GIqnFBpdMIuPO4HE
-fJwD5IcdeHqGl2iH9LIqsY5DcGj4hnqYplIYYk5mWgbhkexRbJIGNdn8WyXlraVp
-2MoSr3p7xJbmo0qYRRtt3kQShzDG0FrZX7wqxemc/g/hr+g2xqMQj0nYLehDeodq
-xA2n9grDUr4AdgQyxXDMUkGZdrg3cwIDAQABAoICACla0aWWfnUaYk60JJ6ieHoN
-Y/XszkUK5gnUSS28d/p5tGdPPnDQ1mSNogq2sx1IJKbkWIizJ818RS33GbAqKfws
-PNGQf+7gMW+N3TloFCgiuo8HPGUukmiLbcWz1tPsMSB/ls3yYNO/WL1qi1d+5ZE/
-Zdg8kxSvLQMXoJ/iqMyVTGnhRsYq7D/y4sgLaLlW18VG1shU9QffEyS1p5thmfk6
-uWhna0EpdIOAFXDbkL0gVYrrYvNWKmEG1mQsMVgCyCvY4ZePb7VX2TvYCOKegSjY
-eK4wFX8746Bj0A5EP9Pt2Pu1E7ZmEN+FeYMyiZCEw5lrdXpCNn+08E4RJmKAng6Z
-LXu7FeBwOffsEcYDk1IPtT4JAkpEO0ennjyY2X+bWu6faaSGqoTDRm0igL/2qeDK
-xJCCOTPDePSDKkVFaimBncQlz4SSVS7WhqqofFMBIPBtZ6oe0c+0ZeKoaH2ZX7jU
-q2DTsRbUKeRerjOlAg5WxQoLxTmLl4t7aHjm4HVafEZHqja5szyNLy13qJZyo7+x
-R8kDRkVdui7XKdC9ajCMAsVcen4NyrvNqQHSoocgqmSuD3d5S/eZnE0cSGGX3Nae
-pb0bAFthQdPq2qfZDDL/cRpe+0FAsOtXG66yEcQjZdsdNerU+pSi/sgArJkNj/U1
-Dqd0LCPOOFiLa/f9LO6hAoIBAQD2HHn2Ghl7W1j4t806i6tfDNocgUCaO+2wjaOY
-cNrg0WiJP24oaRmXew1Le0q5NhX8wHgGZAvVOh0rkcX+sUBoSURzWFK5cavxIGmL
-XqW5wHFS9ahS3mQ3I0zEbueYPyFKEg2a2aFqqq8g3XRqgZtc4kfg4GUbIoltey4z
-uQlp3tIpbRjD9w2cYF9bU9xEgdp7PU5TDmYDiRetSd0HxwD2osj40sWsEbV9UN+4
-xIh6mUwn1ZcJmt7NzuHwyXGs63EhSQoxQwS/vAt0pIKwAlyn06//GBFZGhpnpjCT
-flN9vQPaqJZA93kugsBEt3fX+oGbFTVHgEYsyMTEzH2by6c1AoIBAQDBCmg0ziga
-2WZJE0YARf/gek3MKZNG6qjahuRynpGdtgqa6cSgnRzntDCEkLhU6KZ5+SYJNp0x
-9EBkO7o8YOGWfGUtnccqdbSCt14959Vqn+kcrKnadjFiSVOAGc1728YUjd3jYGS8
-ZXkGe3xXhmXiB1mv8ekKrGY2mmx7mBiZ40gNGJNg1gboenffMeP5l7JjaO7ew5QY
-A3swJkBHNIyGCdntlmrlw1vxT7bmDQoHVLKdQ+VFJFvUVyY40nVkeH1/9WB215Lu
-hzDTzn5Q+Z19pjEouohsJDY6k2FbOyaT0c/KI1NDlNZmUpWcoqf7IIusg1eCCGCH
-nXafifGxv7EHAoIBAAehemaXCJM6kdekW0ila/rWeyzHFSmzEfuXaKshVKgD1inr
-PY8jMxfvSMo+WGLFuojLru0DzRofYygmrOzosgaJvwWUh3wYeixPxPX9SUYpIVph
-I4buPk03Wvn8NlISIwYY6TMT7F1STXvHYgSrYBXRLklaq8fbmkc6uoQACLqvnfSK
-3Wm2D0X59vrt7rZxEEUh8XvBxof1iDZnQ+Mp2G3NPk34uwhKxEXObCFedpzWg/X4
-OWai1qWq9HZyyIOECU3u5dIBMfR/8Br9vs+WQykw9xQBuwf4NzlffcIU+KG9apEt
-CPuasLcwdqWqypx3t+0HC0/cOlDJKNCxRnO+LMECggEABzLoJ+/4NugclGUPmzsB
-C9IDzLVQNLjTizK0mkGnlIYRZy2Ik6TISyvBE3CCL0htzOapsHZE7nP5YsOHcnD6
-eK4y57yWjNLO5IEKFqzqnItSGiumOetmdA/f+Ur9Cr1raaDQwYX6u7vdA4zfWjQ8
-4Gz9vz36PtenCCpCGWnWoQaEzVg5Rsc0gr7ucXhe1BQAJwzmu4/3md2nXmhOxVkE
-VItRgTa2zdK3PwyF+ZZK5XMXJh4+EpIEiqqlVkEi95g2terkqgnoBNUt0PhGZaap
-ZOIpuycZp07CZvTQEKLoEWMlqJggpsiKJk62HZ1DPm48RzausL63Otd4cQKn7MUF
-SQKCAQAHbuzSCvI1YUnFiXtfNLIXdfTV1UJ+y9Mmb3/Lz/wvfbGiAC+TrJ4sdA7R
-k4riwnrv3F3kMop1gxQk1iWSt6qPg2tvw6ZoBcnzE6qJ2/xSdIXgrpV4kCrxAVYz
-vYt9KMWp17mgk4BYbnYU/1U1hZVowlhyx+lzsZtaRRnySvxeEcCO+eR6jTKAXWfH
-rVlbGuuBcTQ/Sz+Jw7mIM3gcI+fE9FyRznSjgVnsXqIsV9bntqkEUFb8VfunR2g5
-6eMoP8XSQdTcEvtKNJ2hrr9fkRABE4L/EeaMT4XOcYyNN9nPka+uj2nRoB9Vsb25
-x55d2r87sh6ScDvl57EIav09Y6W/
------END PRIVATE KEY-----
diff --git a/programs/utils.c b/util.c
index ce19b57..2218f2e 100644
--- a/programs/utils.c
+++ b/util.c
@@ -1,23 +1,24 @@
-// SPDX-License-Identifier: MIT
+// SPDX-License-Identifier: GPL-2.0+
/*
* Utility functions for the 'fsverity' program
*
- * Copyright 2018 Google LLC
+ * Copyright (C) 2018 Google LLC
*
- * Use of this source code is governed by an MIT-style
- * license that can be found in the LICENSE file or at
- * https://opensource.org/licenses/MIT.
+ * Written by Eric Biggers.
*/
-#include "utils.h"
-
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
+#include "util.h"
+
/* ========== Memory allocation ========== */
void *xmalloc(size_t size)
@@ -46,7 +47,7 @@ char *xstrdup(const char *s)
/* ========== Error messages and assertions ========== */
-static void do_error_msg(const char *format, va_list va, int err)
+void do_error_msg(const char *format, va_list va, int err)
{
fputs("ERROR: ", stderr);
vfprintf(stderr, format, va);
@@ -88,21 +89,11 @@ __noreturn void assertion_failed(const char *expr, const char *file, int line)
fatal_error("Assertion failed: %s at %s:%d", expr, file, line);
}
-static void print_libfsverity_error(const char *msg)
-{
- error_msg("%s", msg);
-}
-
-void install_libfsverity_error_handler(void)
-{
- libfsverity_set_error_callback(print_libfsverity_error);
-}
-
/* ========== File utilities ========== */
bool open_file(struct filedes *file, const char *filename, int flags, int mode)
{
- file->fd = open(filename, flags | O_BINARY, mode);
+ file->fd = open(filename, flags, mode);
if (file->fd < 0) {
error_msg_errno("can't open '%s' for %s", filename,
(flags & O_ACCMODE) == O_RDONLY ? "reading" :
@@ -175,14 +166,6 @@ bool filedes_close(struct filedes *file)
return res == 0;
}
-int read_callback(void *file, void *buf, size_t count)
-{
- errno = 0;
- if (!full_read(file, buf, count))
- return errno ? -errno : -EIO;
- return 0;
-}
-
/* ========== String utilities ========== */
static int hex2bin_char(char c)
@@ -198,18 +181,16 @@ static int hex2bin_char(char c)
bool hex2bin(const char *hex, u8 *bin, size_t bin_len)
{
- size_t i;
-
if (strlen(hex) != 2 * bin_len)
return false;
- for (i = 0; i < bin_len; i++) {
+ while (bin_len--) {
int hi = hex2bin_char(*hex++);
int lo = hex2bin_char(*hex++);
if (hi < 0 || lo < 0)
return false;
- bin[i] = (hi << 4) | lo;
+ *bin++ = (hi << 4) | lo;
}
return true;
}
@@ -225,11 +206,10 @@ static char bin2hex_char(u8 nibble)
void bin2hex(const u8 *bin, size_t bin_len, char *hex)
{
- size_t i;
-
- for (i = 0; i < bin_len; i++) {
- *hex++ = bin2hex_char(bin[i] >> 4);
- *hex++ = bin2hex_char(bin[i] & 0xf);
+ while (bin_len--) {
+ *hex++ = bin2hex_char(*bin >> 4);
+ *hex++ = bin2hex_char(*bin & 0xf);
+ bin++;
}
*hex = '\0';
}
diff --git a/common/common_defs.h b/util.h
index 3ae5561..dfa10f2 100644
--- a/common/common_defs.h
+++ b/util.h
@@ -1,21 +1,16 @@
-/* SPDX-License-Identifier: MIT */
+/* SPDX-License-Identifier: GPL-2.0+ */
/*
- * Common definitions for libfsverity and the 'fsverity' program
+ * Utility functions and macros for the 'fsverity' program
*
- * Copyright 2018 Google LLC
- *
- * Use of this source code is governed by an MIT-style
- * license that can be found in the LICENSE file or at
- * https://opensource.org/licenses/MIT.
+ * Copyright (C) 2018 Google LLC
*/
-#ifndef COMMON_COMMON_DEFS_H
-#define COMMON_COMMON_DEFS_H
+#ifndef UTIL_H
+#define UTIL_H
+#include <inttypes.h>
+#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
-#include <stdint.h>
-
-#include "win32_defs.h"
typedef uint8_t u8;
typedef uint16_t u16;
@@ -48,7 +43,6 @@ typedef uint64_t u64;
__typeof__(b) _b = (b); \
_a < _b ? _a : _b; \
})
-
#define max(a, b) ({ \
__typeof__(a) _a = (a); \
__typeof__(b) _b = (b); \
@@ -92,4 +86,40 @@ static inline int ilog2(unsigned long n)
# define le64_to_cpu(v) (__builtin_bswap64((__force u64)(v)))
#endif
-#endif /* COMMON_COMMON_DEFS_H */
+/* ========== Memory allocation ========== */
+
+void *xmalloc(size_t size);
+void *xzalloc(size_t size);
+void *xmemdup(const void *mem, size_t size);
+char *xstrdup(const char *s);
+
+/* ========== Error messages and assertions ========== */
+
+__cold void do_error_msg(const char *format, va_list va, int err);
+__printf(1, 2) __cold void error_msg(const char *format, ...);
+__printf(1, 2) __cold void error_msg_errno(const char *format, ...);
+__printf(1, 2) __cold __noreturn void fatal_error(const char *format, ...);
+__cold __noreturn void assertion_failed(const char *expr,
+ const char *file, int line);
+
+#define ASSERT(e) ({ if (!(e)) assertion_failed(#e, __FILE__, __LINE__); })
+
+/* ========== File utilities ========== */
+
+struct filedes {
+ int fd;
+ char *name; /* filename, for logging or error messages */
+};
+
+bool open_file(struct filedes *file, const char *filename, int flags, int mode);
+bool get_file_size(struct filedes *file, u64 *size_ret);
+bool full_read(struct filedes *file, void *buf, size_t count);
+bool full_write(struct filedes *file, const void *buf, size_t count);
+bool filedes_close(struct filedes *file);
+
+/* ========== String utilities ========== */
+
+bool hex2bin(const char *hex, u8 *bin, size_t bin_len);
+void bin2hex(const u8 *bin, size_t bin_len, char *hex);
+
+#endif /* UTIL_H */