1
0
mirror of https://git.code.sf.net/p/linux-ima/ima-evm-utils synced 2025-07-03 22:23:16 +02:00

20 Commits
v1.4 ... v0.1.1

Author SHA1 Message Date
510061c2b8 Added RPM and TAR building rules
Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
2012-04-05 15:24:01 +03:00
7b0cbf5e53 evm-utils renamed to ima-evm-utils
Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
2012-04-05 14:54:28 +03:00
776183a642 added command options description
Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
2012-04-05 14:32:28 +03:00
c3d090abba removed unused parameter
Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
2012-04-05 13:48:39 +03:00
bb79f7aaf2 import functions combined
Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
2012-04-05 13:48:08 +03:00
a3c7609b80 updated error handling
Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
2012-04-05 12:23:45 +03:00
d70816cbf1 read list of existing extended attributes
getxattr() might return runtime value which does not really exist
on file system. It happens for SMACK LSM. Reading the list of existing
attributes allows to prevent such to happen.

Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
2012-04-04 16:48:38 +03:00
c6c8cccb83 added HMAC API error handling
Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
2012-04-04 16:48:16 +03:00
94de24e5ad version 0.1.0 2012-04-02 15:52:30 +03:00
3f2f98aef8 remove unused parameter
Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
2012-03-15 11:52:36 +02:00
ae47101134 Changed time_t timestamp type to uint32_t
time_t is actually long and is different on 32 and 64 bit architectures.
Format of the signatures should not depend on the architecture and should
be the same. Changed timestamp to uint32_t like in GPG.

Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
2012-02-02 10:12:34 +02:00
d98e4a9bed Added missing CFLAGS
Added missing CFLAGS

Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
2012-02-01 15:24:07 +02:00
179664d7e9 Added signature write to .sig file
To enable module signature verification working on file systems
without extended attributes, or to be able to copy modules by methods,
which does not support extended attribute copying, it is necessary
to store signature in the file. This patch provides command line parameter
for storing signature in .sig file.

Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
2012-02-01 15:24:02 +02:00
c440d2d95f Change set_xattr to xattr.
set_xattr changed to xattr.

Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
2012-02-01 11:10:15 +02:00
fed7fb6933 Changed to conform Linux kernel coding style
Changed to conform Linux kernel coding style, except 80 characters
line length limit.

Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
2012-02-01 11:04:36 +02:00
78494ab370 added password parameter for using encrypted keys
Added password parameter for using encrypted keys.

Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
2012-02-01 10:35:43 +02:00
192f897b8e added openssl initialization and error reporting
Added openssl initialization and error reporting.

Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
2012-02-01 10:35:38 +02:00
0799e24820 minor fixes
- error message
- command info

Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
2012-01-30 13:23:28 +02:00
c94a0b9262 Merge branch 'master' of ssh://linux-ima.git.sourceforge.net/gitroot/linux-ima/evm-utils 2011-12-02 14:39:56 +02:00
e2da6956c4 evmctl - IMA/EVM control tool
evmctl provides signing support for IMA/EVM.
Functionality includes signing of file content (IMA), file metadata (EVM),
importing public keys into kernel keyring.

Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
2011-10-14 16:53:34 +03:00
67 changed files with 956 additions and 7923 deletions

View File

@ -1,137 +0,0 @@
# Copyright (c) 2021 Petr Vorel <pvorel@suse.cz>
name: "distros"
on: [push, pull_request]
jobs:
job:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
# 32bit build
- container: "debian:stable"
env:
CC: gcc
ARCH: i386
TSS: tpm2-tss
VARIANT: i386
COMPILE_SSL: openssl-3.0.0-beta1
# cross compilation builds
- container: "debian:stable"
env:
ARCH: ppc64el
CC: powerpc64le-linux-gnu-gcc
TSS: ibmtss
VARIANT: cross-compile
- container: "debian:stable"
env:
ARCH: arm64
CC: aarch64-linux-gnu-gcc
TSS: tpm2-tss
VARIANT: cross-compile
- container: "debian:stable"
env:
ARCH: s390x
CC: s390x-linux-gnu-gcc
TSS: ibmtss
VARIANT: cross-compile
# musl (native)
- container: "alpine:latest"
env:
CC: gcc
TSS: tpm2-tss
# glibc (gcc/clang)
- container: "opensuse/tumbleweed"
env:
CC: clang
TSS: ibmtss
COMPILE_SSL: openssl-3.0.0-beta1
- container: "opensuse/leap"
env:
CC: gcc
TSS: tpm2-tss
- container: "ubuntu:groovy"
env:
CC: gcc
TSS: ibmtss
COMPILE_SSL: openssl-3.0.0-beta1
- container: "ubuntu:xenial"
env:
CC: clang
TSS: tpm2-tss
- container: "fedora:latest"
env:
CC: clang
TSS: ibmtss
- container: "centos:7"
env:
CC: gcc
TSS: tpm2-tss
- container: "centos:latest"
env:
CC: gcc
TSS: tpm2-tss
- container: "debian:testing"
env:
CC: clang
TSS: tpm2-tss
- container: "debian:stable"
env:
CC: clang
TSS: ibmtss
- container: "alt:sisyphus"
env:
CC: gcc
TSS: libtpm2-tss-devel
container:
image: ${{ matrix.container }}
env: ${{ matrix.env }}
options: --security-opt seccomp=unconfined
steps:
- name: Show OS
run: cat /etc/os-release
- name: Git checkout
uses: actions/checkout@v1
- name: Install additional packages
run: |
INSTALL=${{ matrix.container }}
INSTALL="${INSTALL%%:*}"
INSTALL="${INSTALL%%/*}"
if [ "$VARIANT" ]; then ARCH="$ARCH" ./ci/$INSTALL.$VARIANT.sh; fi
ARCH="$ARCH" CC="$CC" TSS="$TSS" ./ci/$INSTALL.sh
if [ "$COMPILE_SSL" ]; then COMPILE_SSL="$COMPILE_SSL" ./tests/install-openssl3.sh; fi
- name: Build swtpm
run: |
if [ ! "$VARIANT" ]; then
which tpm_server || which swtpm || \
if which tssstartup; then
./tests/install-swtpm.sh;
fi
fi
- name: Compiler version
run: $CC --version
- name: Compile
run: CC="$CC" VARIANT="$VARIANT" ./build.sh

6
.gitignore vendored
View File

@ -2,8 +2,6 @@
*~ *~
# Generated by autotools # Generated by autotools
.libs
m4
.deps .deps
aclocal.m4 aclocal.m4
autom4te.cache autom4te.cache
@ -21,13 +19,10 @@ missing
compile compile
libtool libtool
ltmain.sh ltmain.sh
test-driver
# Compiled executables # Compiled executables
*.o *.o
*.a *.a
*.lo
*.la
src/evmctl src/evmctl
tests/openclose tests/openclose
config.h config.h
@ -45,7 +40,6 @@ cscope.*
ncscope.* ncscope.*
# Generated documentation # Generated documentation
*.1
*.8 *.8
*.5 *.5
manpage.links manpage.links

View File

@ -1,98 +0,0 @@
# Copyright (c) 2017-2021 Petr Vorel <pvorel@suse.cz>
dist: bionic
language: C
services:
- docker
matrix:
include:
# 32 bit build
- os: linux
env: DISTRO=debian:stable VARIANT=i386 ARCH=i386 TSS=tpm2-tss COMPILE_SSL=openssl-3.0.0-beta1
compiler: gcc
# cross compilation builds
- os: linux
env: DISTRO=debian:stable VARIANT=cross-compile ARCH=ppc64el TSS=ibmtss
compiler: powerpc64le-linux-gnu-gcc
- os: linux
env: DISTRO=debian:stable VARIANT=cross-compile ARCH=arm64 TSS=tpm2-tss
compiler: aarch64-linux-gnu-gcc
- os: linux
env: DISTRO=debian:stable VARIANT=cross-compile ARCH=s390x TSS=ibmtss
compiler: s390x-linux-gnu-gcc
# musl
- os: linux
env: DISTRO=alpine:latest TSS=tpm2-tss CONTAINER=podman CONTAINER_ARGS="--runtime=/usr/bin/crun --network=host"
compiler: gcc
# glibc (gcc/clang)
- os: linux
env: DISTRO=opensuse/tumbleweed TSS=ibmtss CONTAINER=podman CONTAINER_ARGS="--runtime=/usr/bin/crun --network=host" COMPILE_SSL=openssl-3.0.0-beta1
compiler: clang
- os: linux
env: DISTRO=opensuse/leap TSS=tpm2-tss
compiler: gcc
- os: linux
env: DISTRO=ubuntu:groovy TSS=ibmtss COMPILE_SSL=openssl-3.0.0-beta1
compiler: gcc
- os: linux
env: DISTRO=ubuntu:xenial TSS=tpm2-tss
compiler: clang
- os: linux
env: DISTRO=fedora:latest TSS=ibmtss CONTAINER=podman CONTAINER_ARGS="--runtime=/usr/bin/crun --network=host"
compiler: clang
- os: linux
env: DISTRO=centos:7 TSS=tpm2-tss
compiler: gcc
- os: linux
env: DISTRO=centos:latest TSS=tpm2-tss
compiler: clang
- os: linux
env: DISTRO=debian:testing TSS=tpm2-tss
compiler: clang
- os: linux
env: DISTRO=debian:stable TSS=ibmtss
compiler: gcc
- os: linux
env: REPO="docker.io/library/" DISTRO=${REPO}alt:sisyphus TSS=libtpm2-tss-devel CONTAINER=podman CONTAINER_ARGS="--runtime=/usr/bin/crun --network=host"
compiler: gcc
before_install:
# Tumbleweed requires podman due docker incompatible with glibc 2.33
# (faccessat2) and crun (for clone3).
- CONTAINER="${CONTAINER:-docker}"
- >
if [ "$CONTAINER" = "podman" ]; then
# podman
. /etc/os-release
sudo sh -c "echo 'deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_${VERSION_ID}/ /' > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list"
wget -nv https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable/xUbuntu_${VERSION_ID}/Release.key -O- | sudo apt-key add -
sudo apt update
sudo apt -y install podman slirp4netns crun
fi
- $CONTAINER info
- DIR="/usr/src/ima-evm-utils"
- printf "FROM $DISTRO\nRUN mkdir -p $DIR\nWORKDIR $DIR\nCOPY . $DIR\n" > Dockerfile
- cat Dockerfile
- $CONTAINER build $CONTAINER_ARGS -t ima-evm-utils .
script:
- INSTALL="${DISTRO#${REPO}}"
- INSTALL="${INSTALL%%:*}"
- INSTALL="${INSTALL%%/*}"
- $CONTAINER run $CONTAINER_ARGS -t ima-evm-utils /bin/sh -c "if [ \"$VARIANT\" ]; then ARCH=\"$ARCH\" ./ci/$INSTALL.$VARIANT.sh; fi && ARCH=\"$ARCH\" CC=\"$CC\" TSS=\"$TSS\" ./ci/$INSTALL.sh && if [ "$COMPILE_SSL" ]; then COMPILE_SSL="$COMPILE_SSL" ./tests/install-openssl3.sh; fi && if [ ! \"$VARIANT\" ]; then which tpm_server || which swtpm || if which tssstartup; then ./tests/install-swtpm.sh; fi; fi && CC=\"$CC\" VARIANT=\"$VARIANT\" ./build.sh"

View File

@ -1,6 +1,2 @@
Dmitry Kasatkin <d.kasatkin@samsung.com> Dmitry Kasatkin <dmitry.kasatkin@intel.com>
CONTRIBUTORS:
Vivek Goyal <vgoyal@redhat.com>
Mimi Zohar <zohar@linux.vnet.ibm.com>

339
COPYING
View File

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

10
ChangeLog Normal file
View File

@ -0,0 +1,10 @@
2012-04-02 Dmitry Kasatkin <dmitry.kasatkin@intel.com>
version 0.1.0
* Fully functional version for lastest 3.x kernels
2011-08-24 Dmitry Kasatkin <dmitry.kasatkin@intel.com>
version 0.1
* Initial public version.

42
INSTALL
View File

@ -1,41 +1,18 @@
Installation Instructions Installation Instructions
************************* *************************
Copyright (C) 1994-1996, 1999-2002, 2004-2013 Free Software Foundation, Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
Inc. 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
Copying and distribution of this file, with or without modification, Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. This file is offered as-is, notice and this notice are preserved. This file is offered as-is,
without warranty of any kind. without warranty of any kind.
Prerequisites
=============
This project has the following prerequisites:
(Ubuntu package names)
libkeyutils-dev
libtasn1-dev
libgmp-dev
libnspr4-dev
libnss3-dev
These software TPMs are supported:
https://sourceforge.net/projects/ibmswtpm2/
https://github.com/stefanberger/swtpm
swtpm depends upon
https://github.com/stefanberger/libtpms
Supported TSSes include these. Both are included in some distros.
IBM TSS https://sourceforge.net/projects/ibmtpm20tss/
Intel TSS
Basic Installation Basic Installation
================== ==================
Briefly, the shell commands `autoreconf -i; ./configure; make; make install' should Briefly, the shell commands `./configure; make; make install' should
configure, build, and install this package. The following configure, build, and install this package. The following
more-detailed instructions are generic; see the `README' file for more-detailed instructions are generic; see the `README' file for
instructions specific to this package. Some packages provide this instructions specific to this package. Some packages provide this
@ -74,7 +51,7 @@ of `autoconf'.
The simplest way to compile this package is: The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type 1. `cd' to the directory containing the package's source code and type
`autoreconf -i' and then `./configure' to configure the package for your system. `./configure' to configure the package for your system.
Running `configure' might take a while. While running, it prints Running `configure' might take a while. While running, it prints
some messages telling which features it is checking for. some messages telling which features it is checking for.
@ -249,11 +226,6 @@ order to use an ANSI C compiler:
and if that doesn't work, install pre-built binaries of GCC for HP-UX. and if that doesn't work, install pre-built binaries of GCC for HP-UX.
HP-UX `make' updates targets which have the same time stamps as
their prerequisites, which makes it generally unusable when shipped
generated files such as `configure' are involved. Use GNU `make'
instead.
On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
parse its `<wchar.h>' header file. The option `-nodtk' can be used as parse its `<wchar.h>' header file. The option `-nodtk' can be used as
a workaround. If GNU CC is not installed, it is therefore recommended a workaround. If GNU CC is not installed, it is therefore recommended
@ -332,10 +304,9 @@ causes the specified `gcc' to be used as the C compiler (unless it is
overridden in the site shell script). overridden in the site shell script).
Unfortunately, this technique does not work for `CONFIG_SHELL' due to Unfortunately, this technique does not work for `CONFIG_SHELL' due to
an Autoconf limitation. Until the limitation is lifted, you can use an Autoconf bug. Until the bug is fixed you can use this workaround:
this workaround:
CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
`configure' Invocation `configure' Invocation
====================== ======================
@ -391,3 +362,4 @@ operates.
`configure' also accepts some other, not widely useful, options. Run `configure' also accepts some other, not widely useful, options. Run
`configure --help' for more details. `configure --help' for more details.

View File

@ -1,12 +1,6 @@
SUBDIRS = src tests SUBDIRS = src tests
if MANPAGE_DOCBOOK_XSL
dist_man_MANS = evmctl.1
endif
doc_DATA = examples/ima-genkey-self.sh examples/ima-genkey.sh examples/ima-gen-local-ca.sh #EXTRA_DIST = LEGAL acinclude.m4 include
EXTRA_DIST = autogen.sh $(doc_DATA)
CLEANFILES = *.html *.xsl
ACLOCAL_AMFLAGS = -I m4 ACLOCAL_AMFLAGS = -I m4
@ -17,7 +11,8 @@ pkgname = $(PACKAGE_NAME)-$(PACKAGE_VERSION)
tarname = $(pkgname).tar.gz tarname = $(pkgname).tar.gz
$(tarname): $(tarname):
git archive --format=tar --prefix=$(pkgname)/ v$(PACKAGE_VERSION) $(FILES) | gzip >$@ git tag -f v$(PACKAGE_VERSION)
git archive --format=tar --prefix=$(pkgname)/ v$(PACKAGE_VERSION) $(FILES) | gzip >$@;
tar: $(tarname) tar: $(tarname)
@ -25,19 +20,4 @@ rpm: $(tarname)
cp $(tarname) $(SRCS)/ cp $(tarname) $(SRCS)/
rpmbuild -ba --nodeps $(SPEC) rpmbuild -ba --nodeps $(SPEC)
if MANPAGE_DOCBOOK_XSL
evmctl.1.html: README
@asciidoc -o $@ $<
evmctl.1:
asciidoc -d manpage -b docbook -o evmctl.1.xsl README
xsltproc --nonet -o $@ $(MANPAGE_DOCBOOK_XSL) evmctl.1.xsl
rm -f evmctl.1.xsl
rmman:
rm -f evmctl.1
doc: evmctl.1.html rmman evmctl.1
endif
.PHONY: $(tarname) .PHONY: $(tarname)

222
NEWS
View File

@ -1,222 +0,0 @@
2021-10-22 Mimi Zohar <zohar@linux.ibm.com>
version 1.4:
* Elliptic curve support and tests
* PKCS11 support and tests
* Ability to manually specify the keyid included in the IMA xattr
* Improve IMA measurement list per TPM bank verification
* Linking with IBM TSS
* Set default hash algorithm in package configuration
* (Minimal) support and test EVM portable signatures
* CI testing:
* Refresh and include new distros
* Podman support
* GitHub Actions
* Limit "sudo" usage
* Misc bug fixes and code cleanup
* Fix static analysis bug reports, memory leaks
* Remove experimental code that was never upstreamed in the kernel
* Use unsigned variable, remove unused variables, etc
2020-10-28 Mimi Zohar <zohar@linux.ibm.com>
version 1.3.2:
* Bugfixes: importing keys
* NEW: Docker based travis distro testing
* Travis bugfixes, code cleanup, software version update,
and script removal
* Initial travis testing
2020-08-11 Mimi Zohar <zohar@linux.ibm.com>
version 1.3.1:
* "--pcrs" support for per crypto algorithm
* Drop/rename "ima_measurement" options
* Moved this summary from "Changelog" to "NEWS", removing
requirement for GNU empty files
* Distro build fixes
2020-07-21 Mimi Zohar <zohar@linux.ibm.com>
version 1.3 new features:
* NEW ima-evm-utils regression test infrastructure with two initial
tests:
- ima_hash.test: calculate/verify different crypto hash algorithms
- sign_verify.test: EVM and IMA sign/verify signature tests
* TPM 2.0 support
- Calculate the new per TPM 2.0 bank template data digest
- Support original padding the SHA1 template data digest
- Compare ALL the re-calculated TPM 2.0 bank PCRs against the
TPM 2.0 bank PCR values
- Calculate the per TPM bank "boot_aggregate" values, including
PCRs 8 & 9 in calculation
- Support reading the per TPM 2.0 Bank PCRs using Intel's TSS
- boot_aggregate.test: compare the calculated "boot_aggregate"
values with the "boot_aggregate" value included in the IMA
measurement.
* TPM 1.2 support
- Additionally support reading the TPM 1.2 PCRs from a supplied file
("--pcrs" option)
* Based on original IMA LTP and standalone version support
- Calculate the TPM 1.2 "boot_aggregate" based on the exported
TPM 1.2 BIOS event log.
- In addition to verifying the IMA measurement list against the
the TPM PCRs, verify the IMA template data digest against the
template data. (Based on LTP "--verify" option.)
- Ignore file measurement violations while verifying the IMA
measurment list. (Based on LTP "--validate" option.)
- Verify the file data signature included in the measurement list
based on the file hash also included in the measurement list
(--verify-sig)
- Support original "ima" template (mixed templates not supported)
* Support "sm3" crypto name
Bug fixes and code cleanup:
* Don't exit with -1 on failure, exit with 125
* On signature verification failure, include pathname.
* Provide minimal hash_info.h file in case one doesn't exist, needed
by the ima-evm-utils regression tests.
* On systems with TPM 1.2, skip "boot_aggregate.test" using sample logs
* Fix hash_algo type comparison mismatch
* Simplify/clean up code
* Address compiler complaints and failures
* Fix memory allocations and leaks
* Sanity check provided input files are regular files
* Revert making "tsspcrread" a compile build time decision.
* Limit additional messages based on log level (-v)
2019-07-30 Mimi Zohar <zohar@linux.ibm.com>
version 1.2.1 Bug fixes:
* When verifying multiple file signatures, return correct status
* Don't automatically use keys from x509 certs if user supplied "--rsa"
* Fix verifying DIGSIG_VERSION_1 signatures
* autoconf, openssl fixes
2019-07-24 Mimi Zohar <zohar@linux.ibm.com>
version 1.2 new features:
* Generate EVM signatures based on the specified hash algorithm
* include "security.apparmor" in EVM signature
* Add support for writing & verifying "user.xxxx" xattrs for testing
* Support Strebog/Gost hash functions
* Add OpenSSL engine support
* Use of EVP_PKEY OpenSSL API to generate/verify v2 signatures
* Support verifying multiple signatures at once
* Support new template "buf" field and warn about other unknown fields
* Improve OpenSSL error reporting
* Support reading TPM 2.0 PCRs using tsspcrread
Bug fixes and code cleanup:
* Update manpage stylesheet detection
* Fix xattr.h include file
* On error when reading TPM PCRs, don't log gargabe
* Properly return keyid string to calc_keyid_v1/v2 callers, caused by
limiting keyid output to verbose mode
* Fix hash buffer overflow caused by EVM support for larger hashes,
defined MAX_DIGEST_SIZE and MAX_SIGNATURE_SIZE, and added "asserts".
* Linked with libcrypto instead of OpenSSL
* Updated Autotools, replacing INCLUDES with AM_CPPFLAGS
* Include new "hash-info.gen" in tar
* Log the hash algorithm, not just the hash value
* Fixed memory leaks in: EV_MD_CTX, init_public_keys
* Fixed other warnings/bugs discovered by clang, coverity
* Remove indirect calls in verify_hash() to improve code readability
* Don't fallback to using sha1
* Namespace some too generic object names
* Make functions/arrays static if possible
2018-01-28 Mimi Zohar <zohar@us.ibm.com>
version 1.1
* Support the new openssl 1.1 api
* Support for validating multiple pcrs
* Verify the measurement list signature based on the list digest
* Verify the "ima-sig" measurement list using multiple keys
* Fixed parsing the measurement template data field length
* Portable & immutable EVM signatures (new format)
* Multiple fixes that have been lingering in the next branch. Some
are for experimental features that are not yet supported in the
kernel.
2014-07-30 Dmitry Kasatkin <dmitry.kasatkin@huawei.com>
version 1.0
* Recursive hashing
* Immutable EVM signatures (experimental)
* Command 'ima_clear' to remove xattrs
* Support for passing password to the library
* Support for asking password safely from the user
2014-09-23 Dmitry Kasatkin <d.kasatkin@samsung.com>
version 0.9
* Updated README
* man page generated and added to the package
* Use additional SMACK xattrs for EVM signature generation
* Signing functions moved to libimaevm for external use (RPM)
* Fixed setting of correct hash header
2014-05-05 Dmitry Kasatkin <d.kasatkin@samsung.com>
version 0.8
* Symbilic names for keyrings
* Hash list signing
* License text fix for using OpenSSL
* Help output fix
2014-02-17 Dmitry Kasatkin <d.kasatkin@samsung.com>
version 0.7
* Fix symbolic links related bugs
* Provide recursive fixing
* Provide recursive signing
* Move IMA verification to the library (first for LTP use)
* Support for target architecture data size
* Remove obsolete module signing code
* Code cleanup
2013-08-28 Dmitry Kasatkin <d.kasatkin@samsung.com>
version 0.6
* support for asymmetric crypto keys and new signature format (v2)
* fixes to set correct hash algo for digital signature v1
* uuid support for EVM
* signature verification support
* test scripts removed
* README updates
2012-05-18 Dmitry Kasatkin <dmitry.kasatkin@intel.com>
version 0.3
* llistxattr returns 0 if there are no xattrs and it is valid
* Added entry type to directory hash calculation
* inline block variable renamed
* Remove forced tag creation
* Use libexec for programs and scripts
* Some files updated
* Do not search for algorithm as it is known
* Refactored to remove redundant hash initialization code
* Added hash calculation for special files
2012-04-05 Dmitry Kasatkin <dmitry.kasatkin@intel.com>
version 0.2
* added RPM & TAR building makefile rules
* renamed evm-utils to ima-evm-utils
* added command options description
* updated error handling
* refactored redundant code
2012-04-02 Dmitry Kasatkin <dmitry.kasatkin@intel.com>
version 0.1.0
* Fully functional version for lastest 3.x kernels
2011-08-24 Dmitry Kasatkin <dmitry.kasatkin@intel.com>
version 0.1
* Initial public version.

457
README
View File

@ -1,457 +1,52 @@
EVMCTL(1)
=========
NAME 1. Generate private key
----
evmctl - IMA/EVM signing utility
SYNOPSIS
--------
evmctl [options] <command> [OPTIONS]
DESCRIPTION
-----------
The evmctl utility can be used for producing and verifying digital signatures,
which are used by Linux kernel integrity subsystem (IMA/EVM). It can be also
used to import keys into the kernel keyring.
COMMANDS
--------
--version
help <command>
import [--rsa] pubkey keyring
sign [-r] [--imahash | --imasig ] [--portable] [--key key] [--pass password] file
verify file
ima_boot_aggregate [--pcrs hash-algorithm,file] [TPM 1.2 BIOS event log]
ima_sign [--sigfile] [--key key] [--pass password] file
ima_verify file
ima_hash file
ima_measurement [--ignore-violations] [--verify-sig [--key "key1, key2, ..."]] [--pcrs [hash-algorithm,]file [--pcrs hash-algorithm,file] ...] file
ima_fix [-t fdsxm] path
sign_hash [--key key] [--pass password]
hmac [--imahash | --imasig ] file
OPTIONS
-------
-a, --hashalgo sha1, sha224, sha256, sha384, sha512
-s, --imasig make IMA signature
-d, --imahash make IMA hash
-f, --sigfile store IMA signature in .sig file instead of xattr
--xattr-user store xattrs in user namespace (for testing purposes)
--rsa use RSA key type and signing scheme v1
-k, --key path to signing key (default: /etc/keys/{privkey,pubkey}_evm.pem)
or a pkcs11 URI
--keyid n overwrite signature keyid with a 32-bit value in hex (for signing)
--keyid-from-cert file
read keyid value from SKID of a x509 cert file
-o, --portable generate portable EVM signatures
-p, --pass password for encrypted signing key
-r, --recursive recurse into directories (sign)
-t, --type file types to fix 'fxm' (f: file)
x - skip fixing if both ima and evm xattrs exist (use with caution)
m - stay on the same filesystem (like 'find -xdev')
-n print result to stdout instead of setting xattr
-u, --uuid use custom FS UUID for EVM (unspecified: from FS, empty: do not use)
--smack use extra SMACK xattrs for EVM
--m32 force EVM hmac/signature for 32 bit target system
--m64 force EVM hmac/signature for 64 bit target system
--engine e preload OpenSSL engine e (such as: gost)
--pcrs file containing TPM pcrs, one per hash-algorithm/bank
--ignore-violations ignore ToMToU measurement violations
--verify-sig verify the file signature based on the file hash, both
stored in the template data.
-v increase verbosity level
-h, --help display this help and exit
Environment variables:
EVMCTL_KEY_PASSWORD : Private key password to use; do not use --pass option
INTRODUCTION
------------
Linux kernel integrity subsystem is comprised of a number of different components
including the Integrity Measurement Architecture (IMA), Extended Verification Module
(EVM), IMA-appraisal extension, digital signature verification extension and audit
measurement log support.
The evmctl utility is used for producing and verifying digital signatures, which
are used by the Linux kernel integrity subsystem. It is also used for importing keys
into the kernel keyring.
Linux integrity subsystem allows to use IMA and EVM signatures. EVM signature
protects file metadata, such as file attributes and extended attributes. IMA
signature protects file content.
For more detailed information about integrity subsystem it is recommended to follow
resources in RESOURCES section.
EVM HMAC and signature metadata
-------------------------------
EVM protects file metadata by including following attributes into HMAC and signature
calculation: inode number, inode generation, UID, GID, file mode, security.selinux,
security.SMACK64, security.ima, security.capability.
EVM HMAC and signature in may also include additional file and file system attributes.
Currently supported additional attributes are filesystem UUID and extra SMACK
extended attributes.
Kernel configuration option CONFIG_EVM_ATTR_FSUUID controls whether to include
filesystem UUID into HMAC and enabled by default. Therefore evmctl also includes
fsuuid by default. Providing '--uuid' option without parameter allows to disable
usage of fs uuid. Providing '--uuid=UUID' option with parameter allows to use
custom UUID. Providing the '--portable' option will disable usage of the fs uuid
and also the inode number and generation.
Kernel configuration option CONFIG_EVM_EXTRA_SMACK_XATTRS controls whether to
include additional SMACK extended attributes into HMAC. They are following:
security.SMACK64EXEC, security.SMACK64TRANSMUTE and security.SMACK64MMAP.
evmctl '--smack' options enables that.
Key and signature formats
-------------------------
Linux integrity subsystem supports two type of signature and respectively two
key formats.
First key format (v1) is pure RSA key encoded in PEM a format and uses own signature
format. It is now non-default format and requires to provide evmctl '--rsa' option
for signing and importing the key.
Second key format uses X509 DER encoded public key certificates and uses asymmetric key support
in the kernel (since kernel 3.9). CONFIG_INTEGRITY_ASYMMETRIC_KEYS must be enabled (default).
For v2 signatures x509 certificate (containing the public key) could be appended to the
private key (they both are in PEM format) to automatically extract keyid from its Subject
Key Identifier (SKID).
Integrity keyrings
----------------
Integrity subsystem uses dedicated IMA/EVM keyrings to search for signature verification
keys - '_ima' and '_evm' respectively.
Since 3.13 IMA allows to declare IMA keyring as trusted. It allows only to load keys,
signed by a key from the system keyring (.system). It means self-signed keys are not
allowed. This is a default behavior unless CONFIG_IMA_TRUSTED_KEYRING is undefined.
IMA trusted keyring is has different name '.ima'. Trusted keyring requires X509
public key certificates. Old version RSA public keys are not compatible with trusted
keyring.
Generate EVM encrypted keys
---------------------------
EVM encrypted key is used for EVM HMAC calculation:
# create and save the key kernel master key (user type)
# LMK is used to encrypt encrypted keys
keyctl add user kmk "`dd if=/dev/urandom bs=1 count=32 2>/dev/null`" @u
keyctl pipe `keyctl search @u user kmk` > /etc/keys/kmk
# create the EVM encrypted key
keyctl add encrypted evm-key "new user:kmk 64" @u
keyctl pipe `keyctl search @u encrypted evm-key` >/etc/keys/evm-key
Generate EVM trusted keys (TPM based)
-------------------------------------
Trusted EVM keys are keys which a generate with the help of TPM.
They are not related to integrity trusted keys.
# create and save the key kernel master key (user type)
keyctl add trusted kmk "new 32" @u
keyctl pipe `keyctl search @u trusted kmk` >kmk
# create the EVM trusted key
keyctl add encrypted evm-key "new trusted:kmk 32" @u
keyctl pipe `keyctl search @u encrypted evm-key` >evm-key
Generate signing and verification keys
--------------------------------------
Generate private key in plain text format:
# plain key
openssl genrsa -out privkey_evm.pem 1024 openssl genrsa -out privkey_evm.pem 1024
Generate encrypted private key: # encrypted key
openssl genrsa -des3 -out privkey_evm.pem 1024 openssl genrsa -des3 -out privkey_evm.pem 1024
Make encrypted private key from unencrypted: # set password for the key
openssl rsa -in /etc/keys/privkey_evm.pem -out privkey_evm_enc.pem -des3 openssl rsa -in /etc/keys/privkey_evm.pem -out privkey_evm_enc.pem -des3
or
openssl pkcs8 -topk8 -in /etc/keys/privkey_evm.pem -out privkey_evm_enc.pem
Generate self-signed X509 public key certificate and private key for using kernel 2. Generate public key
asymmetric keys support:
openssl req -new -nodes -utf8 -sha1 -days 36500 -batch \
-x509 -config x509_evm.genkey \
-outform DER -out x509_evm.der -keyout privkey_evm.pem
Configuration file x509_evm.genkey:
# Begining of the file
[ req ]
default_bits = 1024
distinguished_name = req_distinguished_name
prompt = no
string_mask = utf8only
x509_extensions = myexts
[ req_distinguished_name ]
O = Magrathea
CN = Glacier signing key
emailAddress = slartibartfast@magrathea.h2g2
[ myexts ]
basicConstraints=critical,CA:FALSE
keyUsage=digitalSignature
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid
# EOF
Generate public key for using RSA key format:
openssl rsa -pubout -in privkey_evm.pem -out pubkey_evm.pem openssl rsa -pubout -in privkey_evm.pem -out pubkey_evm.pem
3. Copy public (+private if to sign on device) key to the device/qemu /etc/keys
Copy keys to /etc/keys: scp pubkey_evm.pem mad:/etc/keys
cp pubkey_evm.pem /etc/keys 4. Load keys and enable EVM
scp pubkey_evm.pem target:/etc/keys
or
cp x509_evm.pem /etc/keys
scp x509_evm.pem target:/etc/keys
evm_enable.sh
Generate trusted keys This should be done at early phase, before mounting root filesystem.
---------------------
Generation of trusted keys is a bit more complicated process and involves 5. Sign EVM and use hash value for IMA - common case
following steps:
* Creation of local IMA certification authority (CA).
It consist of private and public key certificate which are used
to sign and verify other keys.
* Build Linux kernel with embedded local IMA CA X509 certificate.
It is used to verify other keys added to the '.ima' trusted keyring
* Generate IMA private signing key and verification public key certificate,
which is signed using local IMA CA private key.
Configuration file ima-local-ca.genkey:
# Begining of the file
[ req ]
default_bits = 2048
distinguished_name = req_distinguished_name
prompt = no
string_mask = utf8only
x509_extensions = v3_ca
[ req_distinguished_name ]
O = IMA-CA
CN = IMA/EVM certificate signing key
emailAddress = ca@ima-ca
[ v3_ca ]
basicConstraints=CA:TRUE
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer
# keyUsage = cRLSign, keyCertSign
# EOF
Generate private key and X509 public key certificate:
openssl req -new -x509 -utf8 -sha1 -days 3650 -batch -config $GENKEY \
-outform DER -out ima-local-ca.x509 -keyout ima-local-ca.priv
Produce X509 in DER format for using while building the kernel:
openssl x509 -inform DER -in ima-local-ca.x509 -out ima-local-ca.pem
Configuration file ima.genkey:
# Begining of the file
[ req ]
default_bits = 1024
distinguished_name = req_distinguished_name
prompt = no
string_mask = utf8only
x509_extensions = v3_usr
[ req_distinguished_name ]
O = `hostname`
CN = `whoami` signing key
emailAddress = `whoami`@`hostname`
[ v3_usr ]
basicConstraints=critical,CA:FALSE
#basicConstraints=CA:FALSE
keyUsage=digitalSignature
#keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid
#authorityKeyIdentifier=keyid,issuer
# EOF
Generate private key and X509 public key certificate signing request:
openssl req -new -nodes -utf8 -sha1 -days 365 -batch -config $GENKEY \
-out csr_ima.pem -keyout privkey_ima.pem
Sign X509 public key certificate signing request with local IMA CA private key:
openssl x509 -req -in csr_ima.pem -days 365 -extfile $GENKEY -extensions v3_usr \
-CA ima-local-ca.pem -CAkey ima-local-ca.priv -CAcreateserial \
-outform DER -out x509_ima.der
Sign file data and metadata
---------------------------
Default key locations:
Private RSA key: /etc/keys/privkey_evm.pem
Public RSA key: /etc/keys/pubkey_evm.pem
X509 certificate: /etc/keys/x509_evm.der
Options to remember: '-k', '-r', '--rsa', '--uuid', '--smack'.
Sign file with EVM signature and calculate hash value for IMA:
evmctl sign --imahash test.txt evmctl sign --imahash test.txt
Sign file with both IMA and EVM signatures: 6. Sign IMA and EVM - for immutable files and modules
evmctl sign --imasig test.txt: evmctl sign --imasig test.txt
Sign file with IMA signature: 7. Sign whole filesystem
evmctl ima_sign test.txt evm_sign_all.sh
or
find / \( -fstype rootfs -o -fstype ext3 -o -fstype ext4 \) ! -path "/lib/modules/*" -type f -uid 0 -exec evmctl sign --imahash '{}' \;
find /lib/modules ! -name "*.ko" -type f -uid 0 -exec evmctl sign --imahash '{}' \;
# security.ima needs to have signature for modules
find /lib/modules -name "*.ko" -type f -uid 0 -exec evmctl sign --imasig '{}' \;
Sign recursively whole filesystem: # generate signatures in .sig files
find /lib/modules -name "*.ko" -type f -uid 0 -exec evmctl -n --sigfile ima_sign '{}' \;
evmctl -r sign --imahash / 8. Label filesystem in fix mode...
Fix recursively whole filesystem: ima_fix_dir.sh <dir>
evmctl -r ima_fix /
Sign filesystem selectively using 'find' command:
find / \( -fstype rootfs -o -fstype ext4 \) -exec evmctl sign --imahash '{}' \;
Fix filesystem selectively using 'find' command:
find / \( -fstype rootfs -o -fstype ext4 \) -exec sh -c "< '{}'" \;
Initialize IMA/EVM at early boot
--------------------------------
IMA/EVM initialization should be normally done from initial RAM file system
before mounting root filesystem.
Here is Ubuntu initramfs example script (/etc/initramfs-tools/scripts/local-top/ima.sh)
# mount securityfs if not mounted
SECFS=/sys/kernel/security
grep -q $SECFS /proc/mounts || mount -n -t securityfs securityfs $SECFS
# search for IMA trusted keyring, then for untrusted
ima_id="`awk '/\.ima/ { printf "%d", "0x"$1; }' /proc/keys`"
if [ -z "$ima_id" ]; then
ima_id=`keyctl search @u keyring _ima 2>/dev/null`
if [ -z "$ima_id" ]; then
ima_id=`keyctl newring _ima @u`
fi
fi
# import IMA X509 certificate
evmctl import /etc/keys/x509_ima.der $ima_id
# search for EVM keyring
evm_id=`keyctl search @u keyring _evm 2>/dev/null`
if [ -z "$evm_id" ]; then
evm_id=`keyctl newring _evm @u`
fi
# import EVM X509 certificate
evmctl import /etc/keys/x509_evm.der $evm_id
# a) import EVM encrypted key
cat /etc/keys/kmk | keyctl padd user kmk @u
keyctl add encrypted evm-key "load `cat /etc/keys/evm-key`" @u
# OR
# b) import EVM trusted key
keyctl add trusted kmk "load `cat /etc/keys/kmk`" @u
keyctl add encrypted evm-key "load `cat /etc/keys/evm-key`" @u
# enable EVM
echo "1" > /sys/kernel/security/evm
Optionally it is possible also to forbid adding, removing of new public keys
and certificates into keyrings and revoking keys using 'keyctl setperm' command:
# protect EVM keyring
keyctl setperm $evm_id 0x0b0b0000
# protect IMA keyring
keyctl setperm $ima_id 0x0b0b0000
# protecting IMA key from revoking (against DoS)
ima_key=`evmctl import /etc/keys/x509_ima.der $ima_id`
keyctl setperm $ima_key 0x0b0b0000
When using plain RSA public keys in PEM format, use 'evmctl import --rsa' for importing keys:
evmctl import --rsa /etc/keys/pubkey_evm.pem $evm_id
Latest version of keyctl allows to import X509 public key certificates:
cat /etc/keys/x509_ima.der | keyctl padd asymmetric '' $ima_id
FILES
-----
Examples of scripts to generate X509 public key certificates:
/usr/share/doc/ima-evm-utils/ima-genkey-self.sh
/usr/share/doc/ima-evm-utils/ima-genkey.sh
/usr/share/doc/ima-evm-utils/ima-gen-local-ca.sh
AUTHOR
------
Written by Dmitry Kasatkin, <dmitry.kasatkin at gmail.com> and others.
RESOURCES
---------
http://sourceforge.net/p/linux-ima/wiki/Home
http://sourceforge.net/p/linux-ima/ima-evm-utils
COPYING
-------
Copyright \(C) 2012 - 2014 Linux Integrity Project. Free use of this software is granted under
the terms of the GNU Public License (GPL).

View File

@ -1,4 +1,16 @@
#! /bin/sh #! /bin/sh
set -e set -e
autoreconf -i # new way
# strange, but need this for Makefile.am, because it has -I m4
test -d m4 || mkdir m4
autoreconf -f -i
# old way
#libtoolize --automake --copy --force
#aclocal
#autoconf --force
#autoheader --force
#automake --add-missing --copy --force-missing --gnu

View File

@ -1,4 +0,0 @@
#!/bin/sh
gcc -static -o evmctl.static -include config.h src/evmctl.c src/libimaevm.c -lcrypto -lkeyutils -ldl

105
build.sh
View File

@ -1,105 +0,0 @@
#!/bin/sh
# Copyright (c) 2020 Petr Vorel <pvorel@suse.cz>
set -e
CC="${CC:-gcc}"
CFLAGS="${CFLAGS:--Wformat -Werror=format-security -Werror=implicit-function-declaration -Werror=return-type -fno-common}"
PREFIX="${PREFIX:-$HOME/ima-evm-utils-install}"
export LD_LIBRARY_PATH="$PREFIX/lib64:$PREFIX/lib:/usr/local/lib64:/usr/local/lib"
export PATH="$PREFIX/bin:/usr/local/bin:$PATH"
title()
{
echo "===== $1 ====="
}
log_exit()
{
local ret="${3:-$?}"
local log="$1"
local msg="$2"
local prefix
echo "=== $log ==="
[ $ret -eq 0 ] || prefix="FAIL: "
cat $log
echo
echo "$prefix$msg, see output of $log above"
exit $ret
}
cd `dirname $0`
case "$VARIANT" in
i386)
echo "32-bit compilation"
export CFLAGS="-m32 $CFLAGS" LDFLAGS="-m32 $LDFLAGS"
export PKG_CONFIG_LIBDIR=/usr/lib/i386-linux-gnu/pkgconfig
;;
cross-compile)
host="${CC%-gcc}"
export CROSS_COMPILE="${host}-"
host="--host=$host"
echo "cross compilation: $host"
echo "CROSS_COMPILE: '$CROSS_COMPILE'"
;;
*)
if [ "$VARIANT" ]; then
echo "Wrong VARIANT: '$VARIANT'" >&2
exit 1
fi
echo "native build"
;;
esac
title "compiler version"
$CC --version
echo "CFLAGS: '$CFLAGS'"
echo "LDFLAGS: '$LDFLAGS'"
echo "PREFIX: '$PREFIX'"
title "configure"
./autogen.sh
./configure --prefix=$PREFIX $host || log_exit config.log "configure failed"
title "make"
make -j$(nproc)
make install
title "test"
if [ "$VARIANT" = "cross-compile" ]; then
echo "skip make check on cross compilation"
exit 0
fi
ret=0
VERBOSE=1 make check || ret=$?
title "logs"
if [ $ret -eq 0 ]; then
if [ -f tests/ima_hash.log ]; then
tail -3 tests/ima_hash.log
grep "skipped" tests/ima_hash.log && \
grep "skipped" tests/ima_hash.log | wc -l
fi
if [ -f tests/sign_verify.log ]; then
tail -3 tests/sign_verify.log
grep "skipped" tests/sign_verify.log && \
grep "skipped" tests/sign_verify.log | wc -l
fi
tail -20 tests/boot_aggregate.log
exit 0
fi
cat tests/test-suite.log
if [ $ret -eq 77 ]; then
msg="WARN: some tests skipped"
ret=0
else
msg="FAIL: tests exited: $ret"
fi
log_exit tests/test-suite.log "$msg" $ret

View File

@ -1,50 +0,0 @@
#!/bin/sh
# Copyright (c) 2020 Petr Vorel <pvorel@suse.cz>
set -ex
if [ -z "$CC" ]; then
echo "missing \$CC!" >&2
exit 1
fi
case "$TSS" in
ibmtss) echo "No IBM TSS package, will be installed from git" >&2; TSS=;;
tpm2-tss) TSS="tpm2-tss-dev";;
'') echo "Missing TSS!" >&2; exit 1;;
*) echo "Unsupported TSS: '$TSS'!" >&2; exit 1;;
esac
# ibmswtpm2 requires gcc
[ "$CC" = "gcc" ] || CC="gcc $CC"
apk update
apk add \
$CC $TSS \
asciidoc \
attr \
attr-dev \
autoconf \
automake \
diffutils \
docbook-xml \
docbook-xsl \
keyutils-dev \
libtool \
libxslt \
linux-headers \
make \
musl-dev \
openssl \
openssl-dev \
pkgconfig \
procps \
sudo \
wget \
which \
xxd
if [ ! "$TSS" ]; then
apk add git
../tests/install-tss.sh
fi

View File

@ -1,27 +0,0 @@
#!/bin/sh -ex
# SPDX-License-Identifier: GPL-2.0-only
#
# Install build env for ALT Linux
apt-get update -y
# rpm-build brings basic build environment with gcc, make, autotools, etc.
apt-get install -y \
$CC \
$TSS \
asciidoc \
attr \
docbook-style-xsl \
gnutls-utils \
libattr-devel \
libkeyutils-devel \
libp11 \
libssl-devel \
openssl \
openssl-gost-engine \
rpm-build \
softhsm \
wget \
xsltproc \
xxd \
&& control openssl-gost enabled

View File

@ -1 +0,0 @@
fedora.sh

View File

@ -1,23 +0,0 @@
#!/bin/sh
# Copyright (c) 2020 Petr Vorel <pvorel@suse.cz>
set -ex
if [ -z "$ARCH" ]; then
echo "missing \$ARCH!" >&2
exit 1
fi
case "$ARCH" in
arm64) gcc_arch="aarch64";;
ppc64el) gcc_arch="powerpc64le";;
s390x) gcc_arch="$ARCH";;
*) echo "unsupported arch: '$ARCH'!" >&2; exit 1;;
esac
dpkg --add-architecture $ARCH
apt update
apt install -y --no-install-recommends \
dpkg-dev \
gcc-${gcc_arch}-linux-gnu \
libc6-dev-${ARCH}-cross

View File

@ -1,11 +0,0 @@
#!/bin/sh
# Copyright (c) 2020 Petr Vorel <pvorel@suse.cz>
set -ex
dpkg --add-architecture i386
apt update
apt install -y --no-install-recommends \
linux-libc-dev:i386 \
gcc-multilib \
pkg-config:i386

View File

@ -1,55 +0,0 @@
#!/bin/sh
# Copyright (c) 2020 Petr Vorel <pvorel@suse.cz>
set -ex
if [ -z "$CC" ]; then
echo "missing \$CC!" >&2
exit 1
fi
# debian.*.sh must be run first
if [ "$ARCH" ]; then
ARCH=":$ARCH"
unset CC
else
apt update
fi
# ibmswtpm2 requires gcc
[ "$CC" = "gcc" ] || CC="gcc $CC"
case "$TSS" in
ibmtss) TSS="libtss-dev";;
tpm2-tss) TSS="libtss2-dev";;
'') echo "Missing TSS!" >&2; exit 1;;
*) [ "$TSS" ] && echo "Unsupported TSS: '$TSS'!" >&2; exit 1;;
esac
apt="apt install -y --no-install-recommends"
$apt \
$CC $TSS \
asciidoc \
attr \
autoconf \
automake \
diffutils \
debianutils \
docbook-xml \
docbook-xsl \
gzip \
libattr1-dev$ARCH \
libkeyutils-dev$ARCH \
libssl-dev$ARCH \
libtool \
make \
openssl \
pkg-config \
procps \
sudo \
wget \
xsltproc
$apt xxd || $apt vim-common
$apt libengine-gost-openssl1.1$ARCH || true
$apt softhsm gnutls-bin libengine-pkcs11-openssl1.1$ARCH || true

View File

@ -1,52 +0,0 @@
#!/bin/sh
# Copyright (c) 2020 Petr Vorel <pvorel@suse.cz>
set -e
if [ -z "$CC" ]; then
echo "missing \$CC!" >&2
exit 1
fi
case "$TSS" in
ibmtss) TSS="tss2-devel";;
tpm2-tss) TSS="tpm2-tss-devel";;
'') echo "Missing TSS!" >&2; exit 1;;
*) echo "Unsupported TSS: '$TSS'!" >&2; exit 1;;
esac
# ibmswtpm2 requires gcc
[ "$CC" = "gcc" ] || CC="gcc $CC"
yum -y install \
$CC $TSS \
asciidoc \
attr \
autoconf \
automake \
diffutils \
docbook-xsl \
gnutls-utils \
gzip \
keyutils-libs-devel \
libattr-devel \
libtool \
libxslt \
make \
openssl \
openssl-devel \
openssl-pkcs11 \
pkg-config \
procps \
sudo \
vim-common \
wget \
which
yum -y install docbook5-style-xsl || true
yum -y install swtpm || true
# SoftHSM is available via EPEL on CentOS
if [ -f /etc/centos-release ]; then
yum -y install epel-release
fi
yum -y install softhsm || true

View File

@ -1 +0,0 @@
tumbleweed.sh

View File

@ -1,50 +0,0 @@
#!/bin/sh
# Copyright (c) 2020 Petr Vorel <pvorel@suse.cz>
set -ex
if [ -z "$CC" ]; then
echo "missing \$CC!" >&2
exit 1
fi
case "$TSS" in
ibmtss) TSS="ibmtss-devel";;
tpm2-tss) TSS="tpm2-0-tss-devel";;
'') echo "Missing TSS!" >&2; exit 1;;
*) echo "Unsupported TSS: '$TSS'!" >&2; exit 1;;
esac
# clang has some gcc dependency
[ "$CC" = "gcc" ] || CC="gcc $CC"
zypper --non-interactive install --force-resolution --no-recommends \
$CC $TSS \
asciidoc \
attr \
autoconf \
automake \
diffutils \
docbook_5 \
docbook5-xsl-stylesheets \
gzip \
ibmswtpm2 \
keyutils-devel \
libattr-devel \
libopenssl-devel \
libtool \
make \
openssl \
pkg-config \
procps \
sudo \
vim \
wget \
which \
xsltproc
zypper --non-interactive install --force-resolution --no-recommends \
gnutls openssl-engine-libp11 softhsm || true
if [ -f /usr/lib/ibmtss/tpm_server -a ! -e /usr/local/bin/tpm_server ]; then
ln -s /usr/lib/ibmtss/tpm_server /usr/local/bin
fi

View File

@ -1 +0,0 @@
debian.sh

View File

@ -1,13 +1,12 @@
# autoconf script # autoconf script
AC_PREREQ([2.65]) AC_PREREQ([2.65])
AC_INIT(ima-evm-utils, 1.4, zohar@linux.ibm.com) AC_INIT(ima-evm-utils, 0.1.1, dmitry.kasatkin@intel.com)
AM_INIT_AUTOMAKE([foreign]) AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION)
AC_CONFIG_HEADERS([config.h]) AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_MACRO_DIR([m4])
AC_CANONICAL_HOST AC_CANONICAL_HOST
AC_USE_SYSTEM_EXTENSIONS
# Checks for programs. # Checks for programs.
AC_PROG_CC AC_PROG_CC
@ -25,34 +24,12 @@ LT_INIT
# Checks for header files. # Checks for header files.
AC_HEADER_STDC AC_HEADER_STDC
PKG_CHECK_MODULES(LIBCRYPTO, [libcrypto >= 0.9.8 ]) PKG_CHECK_MODULES(OPENSSL, [ openssl >= 0.9.8 ])
AC_SUBST(KERNEL_HEADERS) AC_SUBST(OPENSSL_CFLAGS)
AC_SUBST(OPENSSL_LIBS)
AC_CHECK_HEADER(unistd.h) AC_CHECK_HEADER(unistd.h)
AC_CHECK_HEADERS(openssl/conf.h) AC_CHECK_HEADERS(openssl/conf.h)
# Intel TSS
AC_CHECK_LIB([tss2-esys], [Esys_Free])
AC_CHECK_LIB([tss2-rc], [Tss2_RC_Decode])
AM_CONDITIONAL([USE_PCRTSS], [test "x$ac_cv_lib_tss2_esys_Esys_Free" = "xyes"])
# IBM TSS include files
AC_CHECK_HEADER(ibmtss/tss.h, [], [], [[#define TPM_POSIX]])
AM_CONDITIONAL([USE_IBMTSS], [test "x$ac_cv_header_ibmtss_tss_h" = "xyes"])
AC_CHECK_HEADERS(sys/xattr.h, , [AC_MSG_ERROR([sys/xattr.h header not found. You need the c-library development package.])])
AC_CHECK_HEADERS(keyutils.h, , [AC_MSG_ERROR([keyutils.h header not found. You need the libkeyutils development package.])])
AC_ARG_WITH(kernel_headers, [AS_HELP_STRING([--with-kernel-headers=PATH],
[specifies the Linux kernel-headers package location or kernel root directory you want to use])],
[KERNEL_HEADERS="$withval"],
[KERNEL_HEADERS=/lib/modules/$(uname -r)/source])
AC_ARG_ENABLE([openssl_conf],
[AS_HELP_STRING([--disable-openssl-conf], [disable loading of openssl config by evmctl])],
[if test "$enable_openssl_conf" = "no"; then
AC_DEFINE(DISABLE_OPENSSL_CONF, 1, [Define to disable loading of openssl config by evmctl.])
fi], [enable_openssl_conf=yes])
#debug support - yes for a while #debug support - yes for a while
PKG_ARG_ENABLE(debug, "yes", DEBUG, [Enable Debug support]) PKG_ARG_ENABLE(debug, "yes", DEBUG, [Enable Debug support])
if test $pkg_cv_enable_debug = yes; then if test $pkg_cv_enable_debug = yes; then
@ -61,9 +38,6 @@ else
CFLAGS="$CFLAGS -Wall -Wstrict-prototypes -pipe -fomit-frame-pointer" CFLAGS="$CFLAGS -Wall -Wstrict-prototypes -pipe -fomit-frame-pointer"
fi fi
EVMCTL_MANPAGE_DOCBOOK_XSL
AX_DEFAULT_HASH_ALGO([$KERNEL_HEADERS])
# for gcov # for gcov
#CFLAGS="$CFLAGS -Wall -fprofile-arcs -ftest-coverage" #CFLAGS="$CFLAGS -Wall -fprofile-arcs -ftest-coverage"
#CXXFLAGS="$CXXFLAGS -Wall -fprofile-arcs -ftest-coverage" #CXXFLAGS="$CXXFLAGS -Wall -fprofile-arcs -ftest-coverage"
@ -73,7 +47,7 @@ AX_DEFAULT_HASH_ALGO([$KERNEL_HEADERS])
AC_CONFIG_FILES([Makefile AC_CONFIG_FILES([Makefile
src/Makefile src/Makefile
tests/Makefile tests/Makefile
packaging/ima-evm-utils.spec ima-evm-utils.spec
]) ])
AC_OUTPUT AC_OUTPUT
@ -82,10 +56,5 @@ echo
echo echo
echo "Configuration:" echo "Configuration:"
echo " debug: $pkg_cv_enable_debug" echo " debug: $pkg_cv_enable_debug"
echo " default-hash: $HASH_ALGO"
echo " openssl-conf: $enable_openssl_conf"
echo " tss2-esys: $ac_cv_lib_tss2_esys_Esys_Free"
echo " tss2-rc-decode: $ac_cv_lib_tss2_rc_Tss2_RC_Decode"
echo " ibmtss: $ac_cv_header_ibmtss_tss_h"
echo " doc: $have_doc"
echo echo

View File

@ -1,29 +0,0 @@
#!/bin/sh
GENKEY=ima-local-ca.genkey
cat << __EOF__ >$GENKEY
[ req ]
default_bits = 2048
distinguished_name = req_distinguished_name
prompt = no
string_mask = utf8only
x509_extensions = v3_ca
[ req_distinguished_name ]
O = IMA-CA
CN = IMA/EVM certificate signing key
emailAddress = ca@ima-ca
[ v3_ca ]
basicConstraints=CA:TRUE
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer
# keyUsage = cRLSign, keyCertSign
__EOF__
openssl req -new -x509 -utf8 -sha1 -days 3650 -batch -config $GENKEY \
-outform DER -out ima-local-ca.x509 -keyout ima-local-ca.priv
openssl x509 -inform DER -in ima-local-ca.x509 -out ima-local-ca.pem

View File

@ -1,29 +0,0 @@
#!/bin/sh
GENKEY=x509_evm.genkey
cat << __EOF__ >$GENKEY
[ req ]
default_bits = 1024
distinguished_name = req_distinguished_name
prompt = no
string_mask = utf8only
x509_extensions = myexts
[ req_distinguished_name ]
O = `hostname`
CN = `whoami` signing key
emailAddress = `whoami`@`hostname`
[ myexts ]
basicConstraints=critical,CA:FALSE
keyUsage=digitalSignature
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid
__EOF__
openssl req -x509 -new -nodes -utf8 -sha1 -days 3650 -batch -config $GENKEY \
-outform DER -out x509_evm.der -keyout privkey_evm.pem
openssl rsa -pubout -in privkey_evm.pem -out pubkey_evm.pem

View File

@ -1,33 +0,0 @@
#!/bin/sh
GENKEY=ima.genkey
cat << __EOF__ >$GENKEY
[ req ]
default_bits = 1024
distinguished_name = req_distinguished_name
prompt = no
string_mask = utf8only
x509_extensions = v3_usr
[ req_distinguished_name ]
O = `hostname`
CN = `whoami` signing key
emailAddress = `whoami`@`hostname`
[ v3_usr ]
basicConstraints=critical,CA:FALSE
#basicConstraints=CA:FALSE
keyUsage=digitalSignature
#keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid
#authorityKeyIdentifier=keyid,issuer
__EOF__
openssl req -new -nodes -utf8 -sha1 -days 365 -batch -config $GENKEY \
-out csr_ima.pem -keyout privkey_ima.pem
openssl x509 -req -in csr_ima.pem -days 365 -extfile $GENKEY -extensions v3_usr \
-CA ima-local-ca.pem -CAkey ima-local-ca.priv -CAcreateserial \
-outform DER -out x509_ima.der

View File

@ -3,7 +3,7 @@ Version: @PACKAGE_VERSION@
Release: 1%{?dist} Release: 1%{?dist}
Summary: @PACKAGE_NAME@ - IMA/EVM control utility Summary: @PACKAGE_NAME@ - IMA/EVM control utility
Group: System/Libraries Group: System/Libraries
License: GPLv2 License: LGPLv2
#URL: #URL:
Source0: %{name}-%{version}.tar.gz Source0: %{name}-%{version}.tar.gz
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
@ -11,6 +11,7 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
BuildRequires: autoconf BuildRequires: autoconf
BuildRequires: automake BuildRequires: automake
BuildRequires: openssl-devel BuildRequires: openssl-devel
BuildRequires: libattr-devel
BuildRequires: keyutils-libs-devel BuildRequires: keyutils-libs-devel
%description %description
@ -43,8 +44,7 @@ exit 0
%files %files
%defattr(-,root,root,-) %defattr(-,root,root,-)
%{_bindir}/* %{_bindir}/*
%{_libdir}/libimaevm.* %{_libdir}/*
%{_includedir}/*
%changelog %changelog
* Thu Apr 05 2012 Dmitry Kasatkin <dmitry.kasatkin@intel.com> * Thu Apr 05 2012 Dmitry Kasatkin <dmitry.kasatkin@intel.com>

View File

@ -1,36 +0,0 @@
dnl Copyright (c) 2021 Bruno Meneguele <bmeneg@redhat.com>
dnl Check hash algorithm availability in the kernel
dnl
dnl $1 - $KERNEL_HEADERS
AC_DEFUN([AX_DEFAULT_HASH_ALGO], [
HASH_INFO_HEADER="$1/include/uapi/linux/hash_info.h"
AC_ARG_WITH([default_hash],
AS_HELP_STRING([--with-default-hash=ALGORITHM], [specifies the default hash algorithm to be used]),
[HASH_ALGO=$withval],
[HASH_ALGO=sha256])
AC_PROG_SED()
HASH_ALGO="$(echo $HASH_ALGO | $SED 's/\(.*\)/\L\1\E/')"
AC_CHECK_HEADER([$HASH_INFO_HEADER],
[HAVE_HASH_INFO_HEADER=yes],
[AC_MSG_WARN([$HASH_INFO_HEADER not found.])])
if test "x$HAVE_HASH_INFO_HEADER" = "x"; then
AC_MSG_RESULT([using $HASH_ALGO algorithm as default hash algorith])
AC_DEFINE_UNQUOTED(DEFAULT_HASH_ALGO, "$HASH_ALGO", [Define default hash algorithm])
else
AC_PROG_GREP()
$SED -n 's/HASH_ALGO_\(.*\),/\L\1\E/p' $HASH_INFO_HEADER | $GREP -w $HASH_ALGO > /dev/null
have_hash=$?
if test $have_hash -ne 0; then
AC_MSG_ERROR([$HASH_ALGO algorithm specified, but not provided by the kernel], 1)
else
AC_MSG_NOTICE([using $HASH_ALGO as default hash algorithm])
AC_DEFINE_UNQUOTED(DEFAULT_HASH_ALGO, "$HASH_ALGO", [Define default hash algorithm])
fi
fi
])

View File

@ -1,48 +0,0 @@
dnl Copyright (c) 2018-2020 Petr Vorel <pvorel@suse.cz>
dnl Find docbook manpage stylesheet
AC_DEFUN([EVMCTL_MANPAGE_DOCBOOK_XSL], [
DOCBOOK_XSL_URI="http://docbook.sourceforge.net/release/xsl/current"
DOCBOOK_XSL_PATH="manpages/docbook.xsl"
AC_PATH_PROGS(XMLCATALOG, xmlcatalog)
AC_ARG_WITH([xml-catalog],
AC_HELP_STRING([--with-xml-catalog=CATALOG],
[path to xml catalog to use]),,
[with_xml_catalog=/etc/xml/catalog])
XML_CATALOG_FILE="$with_xml_catalog"
AC_SUBST([XML_CATALOG_FILE])
if test "x${XMLCATALOG}" = "x"; then
AC_MSG_WARN([xmlcatalog not found, cannot search for $DOCBOOK_XSL_PATH])
else
AC_MSG_CHECKING([for XML catalog ($XML_CATALOG_FILE)])
if test -f "$XML_CATALOG_FILE"; then
have_xmlcatalog_file=yes
AC_MSG_RESULT([found])
else
AC_MSG_RESULT([not found, cannot search for $DOCBOOK_XSL_PATH])
fi
fi
if test "x${XMLCATALOG}" != "x" -a "x$have_xmlcatalog_file" = "xyes"; then
MANPAGE_DOCBOOK_XSL=$(${XMLCATALOG} ${XML_CATALOG_FILE} ${DOCBOOK_XSL_URI}/${DOCBOOK_XSL_PATH} | sed 's|^file:/\+|/|')
fi
if test "x${MANPAGE_DOCBOOK_XSL}" = "x"; then
MANPAGE_DOCBOOK_XSL="/usr/share/xml/docbook/stylesheet/docbook-xsl/manpages/docbook.xsl"
AC_MSG_WARN([trying a default path for $DOCBOOK_XSL_PATH])
fi
if test -f "$MANPAGE_DOCBOOK_XSL"; then
have_doc=yes
AC_MSG_NOTICE([using $MANPAGE_DOCBOOK_XSL for generating doc])
else
AC_MSG_WARN([$DOCBOOK_XSL_PATH not found, generating doc will be skipped])
MANPAGE_DOCBOOK_XSL=
have_doc=no
fi
AM_CONDITIONAL(MANPAGE_DOCBOOK_XSL, test "x$have_doc" = xyes)
AC_SUBST(MANPAGE_DOCBOOK_XSL)
])

View File

@ -1,52 +0,0 @@
Name: ima-evm-utils
Version: 1.4
Release: 1%{?dist}
Summary: ima-evm-utils - IMA/EVM control utility
Group: System/Libraries
License: GPLv2
#URL:
Source0: %{name}-%{version}.tar.gz
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
BuildRequires: autoconf
BuildRequires: automake
BuildRequires: openssl-devel
BuildRequires: keyutils-libs-devel
%description
This package provide IMA/EVM control utility
%prep
%setup -q
%build
./autogen.sh
%configure --prefix=/usr
make
%install
rm -rf %{buildroot}
make DESTDIR=%{buildroot} install
%clean
rm -rf %{buildroot}
%post
/sbin/ldconfig
exit 0
%preun -p /sbin/ldconfig
%postun
/sbin/ldconfig
%files
%defattr(-,root,root,-)
%{_bindir}/*
%{_libdir}/libimaevm.*
%{_includedir}/*
%changelog
* Thu Apr 05 2012 Dmitry Kasatkin <dmitry.kasatkin@intel.com>
- Initial RPM spec file

2
src/.gitignore vendored
View File

@ -1,2 +0,0 @@
hash_info.h
tmp_hash_info.h

View File

@ -1,45 +1,12 @@
lib_LTLIBRARIES = libimaevm.la
libimaevm_la_SOURCES = libimaevm.c
libimaevm_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBCRYPTO_CFLAGS)
# current[:revision[:age]]
# result: [current-age].age.revision
libimaevm_la_LDFLAGS = -version-info 3:0:0
libimaevm_la_LIBADD = $(LIBCRYPTO_LIBS)
include_HEADERS = imaevm.h
nodist_libimaevm_la_SOURCES = hash_info.h
BUILT_SOURCES = hash_info.h
EXTRA_DIST = hash_info.gen
hash_info.h: Makefile
$(srcdir)/hash_info.gen $(KERNEL_HEADERS) >$@
bin_PROGRAMS = evmctl bin_PROGRAMS = evmctl
evmctl_SOURCES = evmctl.c utils.c evmctl_SOURCES = evmctl.c
evmctl_CPPFLAGS = $(AM_CPPFLAGS) $(LIBCRYPTO_CFLAGS) evmctl_CPPFLAGS = $(OPENSSL_CFLAGS)
evmctl_LDFLAGS = $(LDFLAGS_READLINE) evmctl_LDFLAGS = $(LDFLAGS_READLINE)
evmctl_LDADD = $(LIBCRYPTO_LIBS) -lkeyutils libimaevm.la evmctl_LDADD = $(OPENSSL_LIBS) -lkeyutils
# USE_PCRTSS uses the Intel TSS INCLUDES = -I$(top_srcdir) -include config.h
if USE_PCRTSS
evmctl_SOURCES += pcr_tss.c
# USE_IBMTSS uses the IBM TSS
else
if USE_IBMTSS
evmctl_SOURCES += pcr_ibmtss.c
evmctl_LDADD += -libmtss
# uses the IBM TSS command line utilities
else
evmctl_SOURCES += pcr_tsspcrread.c
endif
endif
AM_CPPFLAGS = -I$(top_srcdir) -include config.h
CLEANFILES = hash_info.h tmp_hash_info.h
DISTCLEANFILES = @DISTCLEANFILES@ DISTCLEANFILES = @DISTCLEANFILES@

File diff suppressed because it is too large Load Diff

View File

@ -1,93 +0,0 @@
#!/bin/sh
#
# Generate hash_info.h from kernel headers
#
# Copyright (C) 2018 <vt@altlinux.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
KERNEL_HEADERS=$1
HASH_INFO_H=uapi/linux/hash_info.h
HASH_INFO=$KERNEL_HEADERS/include/$HASH_INFO_H
TMPHASHINFO="./tmp_hash_info.h"
gen_hashinfo() {
cat << __EOF__ >$TMPHASHINFO
/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
/*
* Hash Info: Hash algorithms information
*
* Copyright (c) 2013 Dmitry Kasatkin <d.kasatkin@samsung.com>
*
* 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.
*
*/
enum hash_algo {
HASH_ALGO_MD4,
HASH_ALGO_MD5,
HASH_ALGO_SHA1,
HASH_ALGO_RIPE_MD_160,
HASH_ALGO_SHA256,
HASH_ALGO_SHA384,
HASH_ALGO_SHA512,
HASH_ALGO_SHA224,
HASH_ALGO_RIPE_MD_128,
HASH_ALGO_RIPE_MD_256,
HASH_ALGO_RIPE_MD_320,
HASH_ALGO_WP_256,
HASH_ALGO_WP_384,
HASH_ALGO_WP_512,
HASH_ALGO_TGR_128,
HASH_ALGO_TGR_160,
HASH_ALGO_TGR_192,
HASH_ALGO_SM3_256,
HASH_ALGO__LAST
};
__EOF__
}
# Allow to specify kernel-headers past include/
if [ ! -e $HASH_INFO ]; then
HASH_INFO2=$KERNEL_HEADERS/$HASH_INFO_H
if [ -e $HASH_INFO2 ]; then
HASH_INFO=$HASH_INFO2
else
gen_hashinfo
HASH_INFO="$TMPHASHINFO"
fi
fi
if [ ! -e $HASH_INFO ]; then
echo "/* $HASH_INFO is not found */"
HASH_INFO=/dev/null
else
echo "/* $HASH_INFO is found */"
fi
echo "enum hash_algo {"
grep HASH_ALGO_.*, $HASH_INFO
printf "\tHASH_ALGO__LAST\n"
echo "};"
echo "const char *const hash_algo_name[HASH_ALGO__LAST] = {"
sed -n 's/HASH_ALGO_\(.*\),/\1 \L\1\E/p' $HASH_INFO | \
while read a b; do
# Normalize text hash name: sm3 algorithm name is different from
# the macro definition, which is also the only special case of an
# underscore between digits. Remove all other underscores.
b=$(echo "$b" | sed "s/sm3_256/sm3/g;s/_//g")
printf '\t%-26s = "%s",\n' "[HASH_ALGO_$a]" "$b"
done
echo "};"

View File

@ -1,237 +0,0 @@
/*
* ima-evm-utils - IMA/EVM support utilities
*
* Copyright (C) 2011 Nokia Corporation
* Copyright (C) 2011,2012,2013 Intel Corporation
* Copyright (C) 2013,2014 Samsung Electronics
*
* Authors:
* Dmitry Kasatkin <dmitry.kasatkin@nokia.com>
* <dmitry.kasatkin@intel.com>
* <d.kasatkin@samsung.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, the copyright holders give permission to link the
* code of portions of this program with the OpenSSL library under certain
* conditions as described in each individual source file and distribute
* linked combinations including the program with the OpenSSL library. You
* must comply with the GNU General Public License in all respects
* for all of the code used other than as permitted herein. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you do not
* wish to do so, delete this exception statement from your version. If you
* delete this exception statement from all source files in the program,
* then also delete it in the license file.
*
* File: imaevm.h
* IMA/EVM header file
*/
#ifndef _LIBIMAEVM_H
#define _LIBIMAEVM_H
#include <linux/fs.h>
#include <stdint.h>
#include <syslog.h>
#include <stdbool.h>
#include <errno.h>
#include <sys/types.h>
#include <openssl/rsa.h>
#include <openssl/engine.h>
#ifdef USE_FPRINTF
#define do_log(level, fmt, args...) \
({ if (level <= imaevm_params.verbose) fprintf(stderr, fmt, ##args); })
#define do_log_dump(level, p, len, cr) \
({ if (level <= imaevm_params.verbose) imaevm_do_hexdump(stderr, p, len, cr); })
#else
#define do_log(level, fmt, args...) syslog(level, fmt, ##args)
#define do_log_dump(level, p, len, cr)
#endif
#ifdef DEBUG
#define log_debug(fmt, args...) do_log(LOG_DEBUG, "%s:%d " fmt, __func__ , __LINE__ , ##args)
#define log_debug_dump(p, len) do_log_dump(LOG_DEBUG, p, len, true)
#define log_debug_dump_n(p, len) do_log_dump(LOG_DEBUG, p, len, false)
#else
#define log_debug(fmt, args...)
#define log_debug_dump(p, len)
#endif
#define log_dump(p, len) do_log_dump(LOG_INFO, p, len, true)
#define log_dump_n(p, len) do_log_dump(LOG_INFO, p, len, false)
#define log_info(fmt, args...) do_log(LOG_INFO, fmt, ##args)
#define log_err(fmt, args...) do_log(LOG_ERR, fmt, ##args)
#define log_errno(fmt, args...) do_log(LOG_ERR, fmt ": errno: %s (%d)\n", ##args, strerror(errno), errno)
#ifndef DEFAULT_HASH_ALGO
#define DEFAULT_HASH_ALGO "sha256"
#endif
#define DATA_SIZE 4096
#define SHA1_HASH_LEN 20
#define MAX_DIGEST_SIZE 64
#define MAX_SIGNATURE_SIZE 1024
#define __packed __attribute__((packed))
enum evm_ima_xattr_type {
IMA_XATTR_DIGEST = 0x01,
EVM_XATTR_HMAC,
EVM_IMA_XATTR_DIGSIG,
IMA_XATTR_DIGEST_NG,
EVM_XATTR_PORTABLE_DIGSIG,
};
struct h_misc {
unsigned long ino;
uint32_t generation;
uid_t uid;
gid_t gid;
unsigned short mode;
};
struct h_misc_32 {
uint32_t ino;
uint32_t generation;
uid_t uid;
gid_t gid;
unsigned short mode;
};
struct h_misc_64 {
uint64_t ino;
uint32_t generation;
uid_t uid;
gid_t gid;
unsigned short mode;
};
struct h_misc_digsig {
uid_t uid;
gid_t gid;
unsigned short mode;
};
enum pubkey_algo {
PUBKEY_ALGO_RSA,
PUBKEY_ALGO_MAX,
};
enum digest_algo {
DIGEST_ALGO_SHA1,
DIGEST_ALGO_SHA256,
DIGEST_ALGO_MAX
};
enum digsig_version {
DIGSIG_VERSION_1 = 1,
DIGSIG_VERSION_2
};
struct pubkey_hdr {
uint8_t version; /* key format version */
uint32_t timestamp; /* key made, always 0 for now */
uint8_t algo;
uint8_t nmpi;
char mpi[0];
} __packed;
struct signature_hdr {
uint8_t version; /* signature format version */
uint32_t timestamp; /* signature made */
uint8_t algo;
uint8_t hash;
uint8_t keyid[8];
uint8_t nmpi;
char mpi[0];
} __packed;
/* reflect enum hash_algo from include/uapi/linux/hash_info.h */
enum pkey_hash_algo {
PKEY_HASH_MD4,
PKEY_HASH_MD5,
PKEY_HASH_SHA1,
PKEY_HASH_RIPE_MD_160,
PKEY_HASH_SHA256,
PKEY_HASH_SHA384,
PKEY_HASH_SHA512,
PKEY_HASH_SHA224,
PKEY_HASH_RIPE_MD_128,
PKEY_HASH_RIPE_MD_256,
PKEY_HASH_RIPE_MD_320,
PKEY_HASH_WP_256,
PKEY_HASH_WP_384,
PKEY_HASH_WP_512,
PKEY_HASH_TGR_128,
PKEY_HASH_TGR_160,
PKEY_HASH_TGR_192,
PKEY_HASH_SM3_256,
PKEY_HASH_STREEBOG_256,
PKEY_HASH_STREEBOG_512,
PKEY_HASH__LAST
};
/*
* signature format v2 - for using with asymmetric keys
*/
struct signature_v2_hdr {
uint8_t version; /* signature format version */
uint8_t hash_algo; /* Digest algorithm [enum pkey_hash_algo] */
uint32_t keyid; /* IMA key identifier - not X509/PGP specific*/
uint16_t sig_size; /* signature size */
uint8_t sig[0]; /* signature payload */
} __packed;
struct libimaevm_params {
int verbose;
int x509;
const char *hash_algo;
const char *keyfile;
const char *keypass;
uint32_t keyid; /* keyid overriding value, unless 0. (Host order.) */
ENGINE *eng;
};
struct RSA_ASN1_template {
const uint8_t *data;
size_t size;
};
#define NUM_PCRS 24
#define DEFAULT_PCR 10
extern struct libimaevm_params imaevm_params;
void imaevm_do_hexdump(FILE *fp, const void *ptr, int len, bool cr);
void imaevm_hexdump(const void *ptr, int len);
int ima_calc_hash(const char *file, uint8_t *hash);
int imaevm_get_hash_algo(const char *algo);
RSA *read_pub_key(const char *keyfile, int x509);
EVP_PKEY *read_pub_pkey(const char *keyfile, int x509);
void calc_keyid_v1(uint8_t *keyid, char *str, const unsigned char *pkey, int len);
void calc_keyid_v2(uint32_t *keyid, char *str, EVP_PKEY *pkey);
int key2bin(RSA *key, unsigned char *pub);
uint32_t imaevm_read_keyid(const char *certfile);
int sign_hash(const char *algo, const unsigned char *hash, int size, const char *keyfile, const char *keypass, unsigned char *sig);
int verify_hash(const char *file, const unsigned char *hash, int size, unsigned char *sig, int siglen);
int ima_verify_signature(const char *file, unsigned char *sig, int siglen, unsigned char *digest, int digestlen);
void init_public_keys(const char *keyfiles);
int imaevm_hash_algo_from_sig(unsigned char *sig);
const char *imaevm_hash_algo_by_id(int algo);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +0,0 @@
int tpm2_pcr_supported(void);
int tpm2_pcr_read(const char *algo_name, uint32_t pcr_handle, uint8_t *hwpcr,
int len, char **errmsg);

View File

@ -1,164 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Support PCR reading implementation based on IBM TSS2
*
* Copyright (C) 2021 IBM Ken Goldman <kgoldman@us.ibm.com>
*/
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <openssl/sha.h>
#define USE_FPRINTF
#include "utils.h"
#include "imaevm.h"
#define TPM_POSIX /* use Posix, not Windows constructs in TSS */
#undef MAX_DIGEST_SIZE /* imaevm uses a different value than the TSS */
#include <ibmtss/tss.h>
#define CMD "tsspcrread"
static char path[PATH_MAX];
int tpm2_pcr_supported(void)
{
if (imaevm_params.verbose > LOG_INFO)
log_info("Using %s to read PCRs.\n", CMD);
if (get_cmd_path(CMD, path, sizeof(path))) {
log_debug("Couldn't find '%s' in $PATH\n", CMD);
return 0;
}
log_debug("Found '%s' in $PATH\n", CMD);
return 1;
}
/* Table mapping C strings to TCG algorithm identifiers */
typedef struct tdAlgorithm_Map {
const char *algorithm_string;
TPMI_ALG_HASH algid;
} Algorithm_Map;
Algorithm_Map algorithm_map[] = {
{ "sha1", TPM_ALG_SHA1},
{ "sha256", TPM_ALG_SHA256},
#if 0 /* uncomment as these digest algorithms are supported */
{ "", TPM_ALG_SHA384},
{ "", TPM_ALG_SHA512},
{ "", TPM_ALG_SM3_256},
{ "", TPM_ALG_SHA3_256},
{ "", TPM_ALG_SHA3_384},
{ "", TPM_ALG_SHA3_512},
#endif
};
/*
* algorithm_string_to_algid() converts a digest algorithm from a C string to a
* TCG algorithm identifier as defined in the TCG Algorithm Regisrty..
*
* Returns TPM_ALG_ERROR if the string has an unsupported value.
*/
static TPMI_ALG_HASH algorithm_string_to_algid(const char *algorithm_string)
{
size_t i;
for (i=0 ; i < sizeof(algorithm_map)/sizeof(Algorithm_Map) ; i++) {
if (strcmp(algorithm_string, algorithm_map[i].algorithm_string)
== 0) {
return algorithm_map[i].algid; /* if match */
}
}
return TPM_ALG_ERROR;
}
/*
* tpm2_pcr_read - read the PCR
*
* algo_name: PCR digest algorithm (the PCR bank) as a C string
* pcr_handle: PCR number to read
* hwpcr: buffer for the PCR output in binary
* len: allocated size of hwpcr and should match the digest algorithm
*/
int tpm2_pcr_read(const char *algo_name, uint32_t pcr_handle, uint8_t *hwpcr,
int len, char **errmsg)
{
int ret = 0; /* function return code */
TPM_RC rc = 0; /* TCG return code */
TPM_RC rc1 = 0; /* secondary return code */
PCR_Read_In pcr_read_in; /* command input */
PCR_Read_Out pcr_read_out; /* response output */
TSS_CONTEXT *tss_context = NULL;
TPMI_ALG_HASH alg_id; /* PCR algorithm */
alg_id = algorithm_string_to_algid(algo_name);
if (alg_id == TPM_ALG_ERROR) {
ret = asprintf(errmsg, "tpm2_pcr_read: unknown algorithm %s",
algo_name);
if (ret == -1) /* the contents of errmsg is undefined */
*errmsg = NULL;
rc = 1;
goto end;
}
rc = TSS_Create(&tss_context);
if (rc != 0)
goto end;
/* call TSS to execute the command */
pcr_read_in.pcrSelectionIn.count = 1;
pcr_read_in.pcrSelectionIn.pcrSelections[0].hash = alg_id;
pcr_read_in.pcrSelectionIn.pcrSelections[0].sizeofSelect = 3;
pcr_read_in.pcrSelectionIn.pcrSelections[0].pcrSelect[0] = 0;
pcr_read_in.pcrSelectionIn.pcrSelections[0].pcrSelect[1] = 0;
pcr_read_in.pcrSelectionIn.pcrSelections[0].pcrSelect[2] = 0;
pcr_read_in.pcrSelectionIn.pcrSelections[0].pcrSelect[pcr_handle / 8] =
1 << (pcr_handle % 8);
rc = TSS_Execute(tss_context,
(RESPONSE_PARAMETERS *)&pcr_read_out,
(COMMAND_PARAMETERS *)&pcr_read_in,
NULL,
TPM_CC_PCR_Read,
TPM_RH_NULL, NULL, 0);
if (rc != 0)
goto end;
/* nothing read, bank missing */
if (pcr_read_out.pcrValues.count == 0) {
ret = asprintf(errmsg, "tpm2_pcr_read: returned count 0 for %s",
algo_name);
if (ret == -1) /* the contents of errmsg is undefined */
*errmsg = NULL;
rc = 1;
goto end;
}
/* len parameter did not match the digest algorithm */
else if (pcr_read_out.pcrValues.digests[0].t.size != len) {
ret = asprintf(errmsg,
"tpm2_pcr_read: "
"expected length %d actual %u for %s",
len, pcr_read_out.pcrValues.digests[0].t.size,
algo_name);
if (ret == -1) /* the contents of errmsg is undefined */
*errmsg = NULL;
rc = 1;
goto end;
} else {
memcpy(hwpcr,
pcr_read_out.pcrValues.digests[0].t.buffer,
pcr_read_out.pcrValues.digests[0].t.size);
}
end:
/* Call delete even on errors to free context resources */
rc1 = TSS_Delete(tss_context);
/* map TCG return code to function return code */
if ((rc == 0) && (rc1 == 0))
return 0;
else
return -1;
}

View File

@ -1,192 +0,0 @@
/*
* ima-evm-utils - IMA/EVM support utilities
*
* Copyright (C) 2011 Nokia Corporation
* Copyright (C) 2011,2012,2013 Intel Corporation
* Copyright (C) 2013,2014 Samsung Electronics
*
* Authors:
* Dmitry Kasatkin <dmitry.kasatkin@nokia.com>
* <dmitry.kasatkin@intel.com>
* <d.kasatkin@samsung.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, the copyright holders give permission to link the
* code of portions of this program with the OpenSSL library under certain
* conditions as described in each individual source file and distribute
* linked combinations including the program with the OpenSSL library. You
* must comply with the GNU General Public License in all respects
* for all of the code used other than as permitted herein. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you do not
* wish to do so, delete this exception statement from your version. If you
* delete this exception statement from all source files in the program,
* then also delete it in the license file.
*
* File: pcr_tss.c
* PCR reading implementation based on Intel TSS2
*/
#include <stdio.h>
#include <string.h>
#include <openssl/sha.h>
#ifdef HAVE_LIBTSS2_ESYS
# include <tss2/tss2_esys.h>
# ifdef HAVE_LIBTSS2_RC
# include <tss2/tss2_rc.h>
# define LIB "tss2-rc-decode"
# else
# define LIB "tss2-esys"
# endif
#endif /* HAVE_LIBTSS2_ESYS */
#define USE_FPRINTF
#include "imaevm.h"
int tpm2_pcr_supported(void)
{
if (imaevm_params.verbose > LOG_INFO)
log_info("Using %s to read PCRs.\n", LIB);
return 1;
}
static int pcr_selections_match(TPML_PCR_SELECTION *a, TPML_PCR_SELECTION *b)
{
int i, j;
if (a->count != b->count)
return 0;
for (i = 0; i < a->count; i++) {
if (a->pcrSelections[i].hash != b->pcrSelections[i].hash)
return 0;
if (a->pcrSelections[i].sizeofSelect != b->pcrSelections[i].sizeofSelect)
return 0;
for (j = 0; j < a->pcrSelections[i].sizeofSelect; j++) {
if (a->pcrSelections[i].pcrSelect[j] != b->pcrSelections[i].pcrSelect[j])
return 0;
}
}
return 1;
}
static inline int tpm2_set_errmsg(char **errmsg, const char *message, TSS2_RC ret)
{
#ifdef HAVE_LIBTSS2_RC
return asprintf(errmsg, "%s: %s", message, Tss2_RC_Decode(ret));
#else
return asprintf(errmsg, "%s: #%d", message, ret);
#endif
}
static TPM2_ALG_ID algo_to_tss2(const char *algo_name)
{
if (!strcmp(algo_name, "sha1"))
return TPM2_ALG_SHA1;
else if (!strcmp(algo_name, "sha256"))
return TPM2_ALG_SHA256;
return TPM2_ALG_ERROR;
}
int tpm2_pcr_read(const char *algo_name, uint32_t pcr_handle, uint8_t *hwpcr,
int len, char **errmsg)
{
TSS2_ABI_VERSION abi_version = {
.tssCreator = 1,
.tssFamily = 2,
.tssLevel = 1,
.tssVersion = 108,
};
ESYS_CONTEXT *ctx = NULL;
TSS2_RC ret = 0;
TPML_PCR_SELECTION *pcr_select_out;
TPML_DIGEST *pcr_digests;
UINT32 pcr_update_counter;
TPM2_ALG_ID algid = algo_to_tss2(algo_name);
if (algid == TPM2_ALG_ERROR) {
ret = asprintf(errmsg, "unsupported tss2 algorithm");
if (ret == -1) /* the contents of errmsg are undefined */
*errmsg = NULL;
return -1;
}
TPML_PCR_SELECTION pcr_select_in = {
.count = 1,
.pcrSelections = {
{
.hash = algid,
.sizeofSelect = 3,
.pcrSelect = { 0x00, 0x00, 0x00 },
}
}
};
pcr_select_in.pcrSelections[0].pcrSelect[pcr_handle / 8] =
(1 << (pcr_handle % 8));
ret = Esys_Initialize(&ctx, NULL, &abi_version);
if (ret != TPM2_RC_SUCCESS) {
ret = tpm2_set_errmsg(errmsg, "esys initialize failed", ret);
if (ret == -1) /* the contents of errmsg are undefined */
*errmsg = NULL;
return -1;
}
ret = Esys_PCR_Read(ctx,
ESYS_TR_NONE,
ESYS_TR_NONE,
ESYS_TR_NONE,
&pcr_select_in,
&pcr_update_counter,
&pcr_select_out,
&pcr_digests);
Esys_Finalize(&ctx);
if (ret != TPM2_RC_SUCCESS) {
ret = tpm2_set_errmsg(errmsg, "esys PCR reading failed", ret);
if (ret == -1) /* the contents of errmsg is undefined */
*errmsg = NULL;
return -1;
}
if (!pcr_selections_match(&pcr_select_in, pcr_select_out)) {
Esys_Free(pcr_select_out);
Esys_Free(pcr_digests);
ret = asprintf(errmsg, "TPM returned incorrect PCRs");
if (ret == -1) /* the contents of errmsg are undefined */
*errmsg = NULL;
return -1;
}
Esys_Free(pcr_select_out);
if (pcr_digests->count != 1 || pcr_digests->digests[0].size != len) {
Esys_Free(pcr_digests);
ret = asprintf(errmsg, "TPM returned incorrect digests");
if (ret == -1) /* the contents of errmsg is undefined */
*errmsg = NULL;
return -1;
}
memcpy(hwpcr, pcr_digests->digests[0].buffer, len);
Esys_Free(pcr_digests);
return 0;
}

View File

@ -1,111 +0,0 @@
/*
* ima-evm-utils - IMA/EVM support utilities
*
* Copyright (C) 2011 Nokia Corporation
* Copyright (C) 2011,2012,2013 Intel Corporation
* Copyright (C) 2013,2014 Samsung Electronics
*
* Authors:
* Dmitry Kasatkin <dmitry.kasatkin@nokia.com>
* <dmitry.kasatkin@intel.com>
* <d.kasatkin@samsung.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, the copyright holders give permission to link the
* code of portions of this program with the OpenSSL library under certain
* conditions as described in each individual source file and distribute
* linked combinations including the program with the OpenSSL library. You
* must comply with the GNU General Public License in all respects
* for all of the code used other than as permitted herein. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you do not
* wish to do so, delete this exception statement from your version. If you
* delete this exception statement from all source files in the program,
* then also delete it in the license file.
*
* File: pcr_tsspcrread.c
* PCR reading implementation based on IBM TSS2
*/
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <openssl/sha.h>
#define USE_FPRINTF
#include "utils.h"
#include "imaevm.h"
#define CMD "tsspcrread"
static char path[PATH_MAX];
int tpm2_pcr_supported(void)
{
if (imaevm_params.verbose > LOG_INFO)
log_info("Using %s to read PCRs.\n", CMD);
if (get_cmd_path(CMD, path, sizeof(path))) {
log_debug("Couldn't find '%s' in $PATH\n", CMD);
return 0;
}
log_debug("Found '%s' in $PATH\n", CMD);
return 1;
}
int tpm2_pcr_read(const char *algo_name, uint32_t pcr_handle, uint8_t *hwpcr,
int len, char **errmsg)
{
FILE *fp;
char pcr[100]; /* may contain an error */
char cmd[PATH_MAX + 50];
int ret;
sprintf(cmd, "%s -halg %s -ha %u -ns 2> /dev/null",
path, algo_name, pcr_handle);
fp = popen(cmd, "r");
if (!fp) {
ret = asprintf(errmsg, "popen failed: %s", strerror(errno));
if (ret == -1) /* the contents of errmsg is undefined */
*errmsg = NULL;
return -1;
}
if (fgets(pcr, sizeof(pcr), fp) == NULL) {
ret = asprintf(errmsg, "tsspcrread failed: %s",
strerror(errno));
if (ret == -1) /* the contents of errmsg is undefined */
*errmsg = NULL;
ret = pclose(fp);
return -1;
}
/* get the popen "cmd" return code */
ret = pclose(fp);
/* Treat an unallocated bank as an error */
if (!ret && (strlen(pcr) < SHA_DIGEST_LENGTH))
ret = -1;
if (!ret)
hex2bin(hwpcr, pcr, len);
else
*errmsg = strndup(pcr, strlen(pcr) - 1); /* remove newline */
return ret;
}

View File

@ -1,115 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* utils: set of common functions
*
* Copyright (C) 2020 Patrick Uiterwijk <patrick@puiterwijk.org>
* Copyright (C) 2010 Cyril Hrubis <chrubis@suse.cz>
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include "utils.h"
#ifndef MIN
# define MIN(a, b) ({ \
typeof(a) _a = (a); \
typeof(b) _b = (b); \
_a < _b ? _a : _b; \
})
#endif /* MIN */
static int file_exist(const char *path)
{
struct stat st;
if (!access(path, R_OK) && !stat(path, &st) && S_ISREG(st.st_mode))
return 1;
return 0;
}
int get_cmd_path(const char *prog_name, char *buf, size_t buf_len)
{
const char *path = (const char *)getenv("PATH");
const char *start = path;
const char *end;
size_t size, ret;
if (path == NULL)
return -1;
do {
end = strchr(start, ':');
if (end != NULL)
snprintf(buf, MIN(buf_len, (size_t) (end - start + 1)),
"%s", start);
else
snprintf(buf, buf_len, "%s", start);
size = strlen(buf);
/*
* "::" inside $PATH, $PATH ending with ':' or $PATH starting
* with ':' should be expanded into current working directory.
*/
if (size == 0) {
snprintf(buf, buf_len, ".");
size = strlen(buf);
}
/*
* If there is no '/' ad the end of path from $PATH add it.
*/
if (buf[size - 1] != '/')
ret =
snprintf(buf + size, buf_len - size, "/%s",
prog_name);
else
ret =
snprintf(buf + size, buf_len - size, "%s",
prog_name);
if (buf_len - size > ret && file_exist(buf))
return 0;
if (end != NULL)
start = end + 1;
} while (end != NULL);
return -1;
}
int hex_to_bin(char ch)
{
if ((ch >= '0') && (ch <= '9'))
return ch - '0';
ch = tolower(ch);
if ((ch >= 'a') && (ch <= 'f'))
return ch - 'a' + 10;
return -1;
}
int hex2bin(void *dst, const char *src, size_t count)
{
int hi, lo;
while (count--) {
if (*src == ' ')
src++;
hi = hex_to_bin(*src++);
lo = hex_to_bin(*src++);
if ((hi < 0) || (lo < 0))
return -1;
*(uint8_t *)dst++ = (hi << 4) | lo;
}
return 0;
}

View File

@ -1,6 +0,0 @@
#include <ctype.h>
#include <sys/types.h>
int get_cmd_path(const char *prog_name, char *buf, size_t buf_len);
int hex_to_bin(char ch);
int hex2bin(void *dst, const char *src, size_t count);

16
tests/.gitignore vendored
View File

@ -1,16 +0,0 @@
# Generated by test driver
*.log
*.trs
# Generated by tests
*.txt
*.out
*.sig
*.sig2
# Generated certs and keys (by gen-keys.sh)
*.cer
*.pub
*.key
*.conf

View File

@ -1,12 +1,7 @@
check_SCRIPTS = pkglib_PROGRAMS = openclose
TESTS = $(check_SCRIPTS)
check_SCRIPTS += ima_hash.test sign_verify.test boot_aggregate.test openclose_SOURCES = openclose.c
clean-local: dist_pkglib_SCRIPTS = evm_enable.sh evm_genkey.sh evm_sign_all.sh evm_sign_modules.sh ima_fix_dir.sh \
-rm -f *.txt *.out *.sig *.sig2 evm_hmac_all.sh evm_hmac_modules.sh
distclean: distclean-keys
.PHONY: distclean-keys
distclean-keys:
./gen-keys.sh clean

View File

@ -1,197 +0,0 @@
#!/bin/bash
#
# Calculate the boot_aggregate for each TPM bank, verifying that the
# boot_aggregate in the IMA measurement list matches one of them.
#
# A software TPM may be used to verify the boot_aggregate. If a
# software TPM is not already running on the system, this test
# starts one and initializes the TPM PCR banks by walking the sample
# binary_bios_measurements event log, included in this directory, and
# extending the TPM PCRs. The associated ascii_runtime_measurements
# for verifying the calculated boot_aggregate is included in this
# directory as well.
trap cleanup SIGINT SIGTERM EXIT
# Base VERBOSE on the environment variable, if set.
VERBOSE="${VERBOSE:-0}"
cd "$(dirname "$0")"
export PATH=../src:$PATH
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH
. ./functions.sh
_require evmctl
TSSDIR="$(dirname -- "$(which tssstartup)")"
PCRFILE="/sys/class/tpm/tpm0/device/pcrs"
MISC_PCRFILE="/sys/class/misc/tpm0/device/pcrs"
# Only stop this test's software TPM
cleanup() {
if [ -n "${SWTPM_PID}" ]; then
kill -SIGTERM "${SWTPM_PID}"
elif [ -n "${TPMSERVER_PID}" ]; then
"${TSSDIR}/tsstpmcmd" -stop
fi
}
# Try to start a software TPM if needed.
swtpm_start() {
local tpm_server swtpm
tpm_server="$(which tpm_server)"
swtpm="$(which swtpm)"
if [ -z "${tpm_server}" ] && [ -z "${swtpm}" ]; then
echo "${CYAN}SKIP: Software TPM (tpm_server and swtpm) not found${NORM}"
return "$SKIP"
fi
if [ -n "${swtpm}" ]; then
pgrep swtpm
if [ $? -eq 0 ]; then
echo "INFO: Software TPM (swtpm) already running"
return 114
else
echo "INFO: Starting software TPM: ${swtpm}"
mkdir -p ./myvtpm
${swtpm} socket --tpmstate dir=./myvtpm --tpm2 --ctrl type=tcp,port=2322 --server type=tcp,port=2321 --flags not-need-init > /dev/null 2>&1 &
SWTPM_PID=$!
fi
elif [ -n "${tpm_server}" ]; then
# tpm_server uses the Microsoft simulator encapsulated packet format
export TPM_SERVER_TYPE="mssim"
pgrep tpm_server
if [ $? -eq 0 ]; then
echo "INFO: Software TPM (tpm_server) already running"
return 114
else
echo "INFO: Starting software TPM: ${tpm_server}"
${tpm_server} > /dev/null 2>&1 &
TPMSERVER_PID=$!
fi
fi
return 0
}
# Initialize the software TPM using the sample binary_bios_measurements log.
swtpm_init() {
if [ ! -f "${TSSDIR}/tssstartup" ] || [ ! -f "${TSSDIR}/tsseventextend" ]; then
echo "${CYAN}SKIP: tssstartup and tsseventextend needed for test${NORM}"
return "$SKIP"
fi
echo "INFO: Sending software TPM startup"
"${TSSDIR}/tssstartup"
if [ $? -ne 0 ]; then
echo "INFO: Retry sending software TPM startup"
sleep 1
"${TSSDIR}/tssstartup"
fi
if [ $? -ne 0 ]; then
echo "INFO: Software TPM startup failed"
return "$SKIP"
fi
echo "INFO: Walking ${BINARY_BIOS_MEASUREMENTS} initializing the software TPM"
# $(${TSSDIR}/tsseventextend -tpm -if "${BINARY_BIOS_MEASUREMENTS}" -v) 2>&1 > /dev/null
"${TSSDIR}/tsseventextend" -tpm -if "${BINARY_BIOS_MEASUREMENTS}" -v > /dev/null 2>&1
}
# In VERBOSE mode, display the calculated TPM PCRs for the different banks.
display_pcrs() {
local PCRMAX=9
local banks=("sha1" "sha256")
local i;
for bank in "${banks[@]}"; do
echo "INFO: Displaying ${bank} TPM bank (PCRs 0 - 9)"
for i in $(seq 0 $PCRMAX); do
rc=0
pcr=$("${TSSDIR}/tsspcrread" -halg "${bank}" -ha "${i}" -ns)
if [ $rc -ne 0 ]; then
echo "INFO: tsspcrread failed: $pcr"
break
fi
echo "$i: $pcr"
done
done
}
# The first entry in the IMA measurement list is the "boot_aggregate".
# For each kexec, an additional "boot_aggregate" will appear in the
# measurement list, assuming the previous measurement list is carried
# across the kexec.
#
# Verify that the last "boot_aggregate" record in the IMA measurement
# list matches.
check() {
echo "INFO: Calculating the boot_aggregate (PCRs 0 - 9) for multiple banks"
bootaggr=$(evmctl ima_boot_aggregate)
if [ $? -ne 0 ]; then
echo "${CYAN}SKIP: evmctl ima_boot_aggregate: $bootaggr${NORM}"
exit "$SKIP"
fi
boot_aggr=( $bootaggr )
echo "INFO: Searching for the boot_aggregate in ${ASCII_RUNTIME_MEASUREMENTS}"
for hash in "${boot_aggr[@]}"; do
if [ "$VERBOSE" != "0" ]; then
echo "$hash"
fi
if grep -e " boot_aggregate$" -e " boot_aggregate.$" "${ASCII_RUNTIME_MEASUREMENTS}" | tail -n 1 | grep -q "${hash}"; then
echo "${GREEN}SUCCESS: boot_aggregate ${hash} found${NORM}"
return "$OK"
fi
done
echo "${RED}FAILURE: boot_aggregate not found${NORM}"
echo "$bootaggr"
return "$FAIL"
}
if [ "$(id -u)" = 0 ] && [ -c "/dev/tpm0" ]; then
ASCII_RUNTIME_MEASUREMENTS="/sys/kernel/security/ima/ascii_runtime_measurements"
if [ ! -d "/sys/kernel/security/ima" ]; then
echo "${CYAN}SKIP: CONFIG_IMA not enabled${NORM}"
exit "$SKIP"
fi
else
BINARY_BIOS_MEASUREMENTS="./sample-binary_bios_measurements-pcrs-8-9"
ASCII_RUNTIME_MEASUREMENTS="./sample-ascii_runtime_measurements-pcrs-8-9"
export TPM_INTERFACE_TYPE="socsim"
export TPM_COMMAND_PORT=2321
export TPM_PLATFORM_PORT=2322
export TPM_SERVER_NAME="localhost"
# swtpm uses the raw, unencapsulated packet format
export TPM_SERVER_TYPE="raw"
fi
# Start and initialize a software TPM as needed
if [ "$(id -u)" != 0 ] || [ ! -c "/dev/tpm0" ]; then
if [ -f "$PCRFILE" ] || [ -f "$MISC_PCRFILE" ]; then
echo "${CYAN}SKIP: system has discrete TPM 1.2, sample TPM 2.0 event log test not supported.${NORM}"
exit "$SKIP"
fi
swtpm_start
error=$?
if [ $error -eq "$SKIP" ]; then
echo "skip: swtpm not installed"
exit "$SKIP"
fi
if [ $error -eq 0 ]; then
swtpm_init
if [ $? -eq "$SKIP" ]; then
echo "testing boot_aggregate without entries"
exit "$SKIP"
fi
fi
if [ "$VERBOSE" != "0" ]; then
display_pcrs
fi
fi
expect_pass check

25
tests/evm_enable.sh Executable file
View File

@ -0,0 +1,25 @@
#!/bin/sh
# import EVM HMAC key
keyctl clear @u
keyctl add user kmk "testing123" @u
keyctl add encrypted evm-key "load `cat /etc/keys/evm-key`" @u
# import Moule public key
mod_id=`keyctl newring _module @u`
evmctl import /etc/keys/pubkey_evm.pem $mod_id
# import IMA public key
ima_id=`keyctl newring _ima @u`
evmctl import /etc/keys/pubkey_evm.pem $ima_id
# import EVM public key
evm_id=`keyctl newring _evm @u`
evmctl import /etc/keys/pubkey_evm.pem $evm_id
# enable EVM
echo "1" > /sys/kernel/security/evm
# enable module checking
echo "1" > /sys/kernel/security/ima/module_check

8
tests/evm_genkey.sh Executable file
View File

@ -0,0 +1,8 @@
#!/bin/sh
keyctl add user kmk "testing123" @u
key=`keyctl add encrypted evm-key "new user:kmk 32" @u`
keyctl print $key >/etc/keys/evm-key
keyctl list @u

14
tests/evm_hmac_all.sh Executable file
View File

@ -0,0 +1,14 @@
#!/bin/sh
verbose=""
if [ "$1" = "-v" ] ; then
verbose="-v"
shift 1
fi
dir=${1:-/}
echo "Label: $dir"
find $dir \( -fstype rootfs -o -fstype ext3 -o -fstype ext4 \) \( -type f -o -type d \) -exec evmctl hmac --imahash $verbose '{}' \;

14
tests/evm_hmac_modules.sh Executable file
View File

@ -0,0 +1,14 @@
#!/bin/sh
verbose=""
if [ "$1" = "-v" ] ; then
verbose="-v"
shift 1
fi
dir=${1:-/lib/modules}
echo "HMAC modules: $dir"
find $dir -name "*.ko" -type f -exec evmctl hmac --imasig $verbose '{}' \;

14
tests/evm_sign_all.sh Executable file
View File

@ -0,0 +1,14 @@
#!/bin/sh
verbose=""
if [ "$1" = "-v" ] ; then
verbose="-v"
shift 1
fi
dir=${1:-/}
echo "Label: $dir"
find $dir \( -fstype rootfs -o -fstype ext3 -o -fstype ext4 \) -type f -exec evmctl sign --imahash $verbose '{}' \;

14
tests/evm_sign_modules.sh Executable file
View File

@ -0,0 +1,14 @@
#!/bin/sh
verbose=""
if [ "$1" = "-v" ] ; then
verbose="-v"
shift 1
fi
dir=${1:-/lib/modules}
echo "Signing modules: $dir"
find $dir -name "*.ko" -type f -exec evmctl sign --imasig $verbose '{}' \;

View File

@ -1,315 +0,0 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
#
# ima-evm-utils tests bash functions
#
# Copyright (C) 2020 Vitaly Chikunov <vt@altlinux.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# Tests accounting
declare -i testspass=0 testsfail=0 testsskip=0
# Exit codes (compatible with automake)
declare -r OK=0
declare -r FAIL=1
declare -r HARDFAIL=99 # hard failure no matter testing mode
declare -r SKIP=77
# You can set env VERBOSE=1 to see more output from evmctl
VERBOSE=${VERBOSE:-0}
V=vvvv
V=${V:0:$VERBOSE}
V=${V:+-$V}
# Exit if env FAILEARLY is defined.
# Used in expect_{pass,fail}.
exit_early() {
if [ "$FAILEARLY" ]; then
exit "$1"
fi
}
# Require particular executables to be present
_require() {
ret=
for i; do
if ! type $i; then
echo "$i is required for test"
ret=1
fi
done
[ $ret ] && exit "$HARDFAIL"
}
# Non-TTY output is never colored
if [ -t 1 ]; then
RED=$'\e[1;31m'
GREEN=$'\e[1;32m'
YELLOW=$'\e[1;33m'
BLUE=$'\e[1;34m'
CYAN=$'\e[1;36m'
NORM=$'\e[m'
export RED GREEN YELLOW BLUE CYAN NORM
fi
# Test mode determined by TFAIL variable:
# undefined: to success testing
# defined: failure testing
TFAIL=
TMODE=+ # mode character to prepend running command in log
declare -i TNESTED=0 # just for sanity checking
# Run positive test (one that should pass) and account its result
expect_pass() {
local -i ret
if [ $TNESTED -gt 0 ]; then
echo $RED"expect_pass should not be run nested"$NORM
testsfail+=1
exit "$HARDFAIL"
fi
TFAIL=
TMODE=+
TNESTED+=1
[ "$VERBOSE" -gt 1 ] && echo "____ START positive test: $*"
"$@"
ret=$?
[ "$VERBOSE" -gt 1 ] && echo "^^^^ STOP ($ret) positive test: $*"
TNESTED+=-1
case $ret in
0) testspass+=1 ;;
77) testsskip+=1 ;;
99) testsfail+=1; exit_early 1 ;;
*) testsfail+=1; exit_early 2 ;;
esac
return $ret
}
# Eval negative test (one that should fail) and account its result
expect_fail() {
local ret
if [ $TNESTED -gt 0 ]; then
echo $RED"expect_fail should not be run nested"$NORM
testsfail+=1
exit "$HARDFAIL"
fi
TFAIL=yes
TMODE=-
TNESTED+=1
[ "$VERBOSE" -gt 1 ] && echo "____ START negative test: $*"
"$@"
ret=$?
[ "$VERBOSE" -gt 1 ] && echo "^^^^ STOP ($ret) negative test: $*"
TNESTED+=-1
case $ret in
0) testsfail+=1; exit_early 3 ;;
77) testsskip+=1 ;;
99) testsfail+=1; exit_early 4 ;;
*) testspass+=1 ;;
esac
# Restore defaults (as in positive tests)
# for tests to run without wrappers
TFAIL=
TMODE=+
return $ret
}
# return true if current test is positive
_test_expected_to_pass() {
[ ! $TFAIL ]
}
# return true if current test is negative
_test_expected_to_fail() {
[ $TFAIL ]
}
# Show blank line and color following text to red
# if it's real error (ie we are in expect_pass mode).
color_red_on_failure() {
if _test_expected_to_pass; then
echo "$RED"
COLOR_RESTORE=true
fi
}
# For hard errors
color_red() {
echo "$RED"
COLOR_RESTORE=true
}
color_restore() {
[ $COLOR_RESTORE ] && echo "$NORM"
COLOR_RESTORE=
}
ADD_DEL=
ADD_TEXT_FOR=
# _evmctl_run should be run as `_evmctl_run ... || return'
_evmctl_run() {
local op=$1 out=$1-$$.out
local text_for=${FOR:+for $ADD_TEXT_FOR}
# Additional parameters:
# ADD_DEL: additional files to rm on failure
# ADD_TEXT_FOR: append to text as 'for $ADD_TEXT_FOR'
cmd="evmctl $V $EVMCTL_ENGINE $*"
echo $YELLOW$TMODE "$cmd"$NORM
$cmd >"$out" 2>&1
ret=$?
# Shell special and signal exit codes (except 255)
if [ $ret -ge 126 ] && [ $ret -lt 255 ]; then
color_red
echo "evmctl $op failed hard with ($ret) $text_for"
sed 's/^/ /' "$out"
color_restore
rm "$out" $ADD_DEL
ADD_DEL=
ADD_TEXT_FOR=
return "$HARDFAIL"
elif [ $ret -gt 0 ]; then
color_red_on_failure
echo "evmctl $op failed" ${TFAIL:+properly} "with ($ret) $text_for"
# Show evmctl output only in verbose mode or if real failure.
if _test_expected_to_pass || [ "$VERBOSE" ]; then
sed 's/^/ /' "$out"
fi
color_restore
rm "$out" $ADD_DEL
ADD_DEL=
ADD_TEXT_FOR=
return "$FAIL"
elif _test_expected_to_fail; then
color_red
echo "evmctl $op wrongly succeeded $text_for"
sed 's/^/ /' "$out"
color_restore
else
[ "$VERBOSE" ] && sed 's/^/ /' "$out"
fi
rm "$out"
ADD_DEL=
ADD_TEXT_FOR=
return "$OK"
}
# Extract xattr $attr from $file into $out file skipping $pref'ix
_extract_xattr() {
local file=$1 attr=$2 out=$3 pref=$4
getfattr -n "$attr" -e hex "$file" \
| grep "^$attr=" \
| sed "s/^$attr=$pref//" \
| xxd -r -p > "$out"
}
# Test if xattr $attr in $file matches $prefix
# Show error and fail otherwise.
_test_xattr() {
local file=$1 attr=$2 prefix=$3
local text_for=${ADD_TEXT_FOR:+ for $ADD_TEXT_FOR}
if ! getfattr -n "$attr" -e hex "$file" | egrep -qx "$attr=$prefix"; then
color_red_on_failure
echo "Did not find expected hash$text_for:"
echo " $attr=$prefix"
echo ""
echo "Actual output below:"
getfattr -n "$attr" -e hex "$file" | sed 's/^/ /'
color_restore
rm "$file"
ADD_TEXT_FOR=
return "$FAIL"
fi
ADD_TEXT_FOR=
}
# Try to enable gost-engine if needed.
_enable_gost_engine() {
# Do not enable if it's already working (enabled by user)
if ! openssl md_gost12_256 /dev/null >/dev/null 2>&1 \
&& openssl engine gost >/dev/null 2>&1; then
export EVMCTL_ENGINE="--engine gost"
export OPENSSL_ENGINE="-engine gost"
fi
}
# Show test stats and exit into automake test system
# with proper exit code (same as ours). Do cleanups.
_report_exit_and_cleanup() {
if [ -n "${WORKDIR}" ]; then
rm -rf "${WORKDIR}"
fi
if [ $testsfail -gt 0 ]; then
echo "================================="
echo " Run with FAILEARLY=1 $0 $*"
echo " To stop after first failure"
echo "================================="
fi
[ $testspass -gt 0 ] && echo -n "$GREEN" || echo -n "$NORM"
echo -n "PASS: $testspass"
[ $testsskip -gt 0 ] && echo -n "$YELLOW" || echo -n "$NORM"
echo -n " SKIP: $testsskip"
[ $testsfail -gt 0 ] && echo -n "$RED" || echo -n "$NORM"
echo " FAIL: $testsfail"
echo "$NORM"
if [ $testsfail -gt 0 ]; then
exit "$FAIL"
elif [ $testspass -gt 0 ]; then
exit "$OK"
else
exit "$SKIP"
fi
}
# Setup SoftHSM for local testing by calling the softhsm_setup script.
# Use the provided workdir as the directory where SoftHSM will store its state
# into.
# Upon successfully setting up SoftHSM, this function sets the global variables
# OPENSSL_ENGINE and OPENSSL_KEYFORM so that the openssl command line tool can
# use SoftHSM. Also the PKCS11_KEYURI global variable is set to the test key's
# pkcs11 URI.
_softhsm_setup() {
local workdir="$1"
local msg
export SOFTHSM_SETUP_CONFIGDIR="${workdir}/softhsm"
export SOFTHSM2_CONF="${workdir}/softhsm/softhsm2.conf"
mkdir -p "${SOFTHSM_SETUP_CONFIGDIR}"
msg=$(./softhsm_setup setup 2>&1)
if [ $? -eq 0 ]; then
echo "softhsm_setup setup succeeded: $msg"
PKCS11_KEYURI=$(echo $msg | sed -n 's|^keyuri: \(.*\)|\1|p')
export EVMCTL_ENGINE="--engine pkcs11"
export OPENSSL_ENGINE="-engine pkcs11"
export OPENSSL_KEYFORM="-keyform engine"
else
echo "softhsm_setup setup failed: ${msg}"
fi
}
# Tear down the SoftHSM setup and clean up the environment
_softhsm_teardown() {
./softhsm_setup teardown &>/dev/null
rm -rf "${SOFTHSM_SETUP_CONFIGDIR}"
unset SOFTHSM_SETUP_CONFIGDIR SOFTHSM2_CONF PKCS11_KEYURI \
EVMCTL_ENGINE OPENSSL_ENGINE OPENSSL_KEYFORM
}

View File

@ -1,161 +0,0 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
#
# Generate keys for the tests
#
# Copyright (C) 2020 Vitaly Chikunov <vt@altlinux.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
cd "$(dirname "$0")" || exit 1
PATH=../src:$PATH
type openssl
log() {
echo >&2 - "$*"
eval "$@"
}
if [ "$1" = clean ]; then
rm -f test-ca.conf
elif [ "$1" = force ] || [ ! -e test-ca.conf ] \
|| [ gen-keys.sh -nt test-ca.conf ]; then
cat > test-ca.conf <<- EOF
[ req ]
distinguished_name = req_distinguished_name
prompt = no
string_mask = utf8only
x509_extensions = v3_ca
[ req_distinguished_name ]
O = IMA-CA
CN = IMA/EVM certificate signing key
emailAddress = ca@ima-ca
[ v3_ca ]
basicConstraints=CA:TRUE
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer
[ skid ]
basicConstraints=CA:TRUE
subjectKeyIdentifier=12345678
authorityKeyIdentifier=keyid:always,issuer
EOF
fi
# RSA
# Second key will be used for wrong key tests.
for m in 1024 1024_skid 2048; do
if [ "$1" = clean ] || [ "$1" = force ] \
|| [ gen-keys.sh -nt test-rsa$m.key ]; then
rm -f test-rsa$m.cer test-rsa$m.key test-rsa$m.pub
fi
if [ "$1" = clean ]; then
continue
fi
if [ -z "${m%%*_*}" ]; then
# Add named extension.
bits=${m%_*}
ext="-extensions ${m#*_}"
else
bits=$m
ext=
fi
if [ ! -e test-rsa$m.key ]; then
log openssl req -verbose -new -nodes -utf8 -sha1 -days 10000 -batch -x509 $ext \
-config test-ca.conf \
-newkey rsa:$bits \
-out test-rsa$m.cer -outform DER \
-keyout test-rsa$m.key
# for v1 signatures
log openssl pkey -in test-rsa$m.key -out test-rsa$m.pub -pubout
if [ $m = 1024_skid ]; then
# Create combined key+cert.
log openssl x509 -inform DER -in test-rsa$m.cer >> test-rsa$m.key
fi
fi
done
for curve in prime192v1 prime256v1; do
if [ "$1" = clean ] || [ "$1" = force ]; then
rm -f test-$curve.cer test-$curve.key test-$curve.pub
fi
if [ "$1" = clean ]; then
continue
fi
if [ ! -e test-$curve.key ]; then
log openssl req -verbose -new -nodes -utf8 -sha1 -days 10000 -batch -x509 \
-config test-ca.conf \
-newkey ec \
-pkeyopt ec_paramgen_curve:$curve \
-out test-$curve.cer -outform DER \
-keyout test-$curve.key
if [ -s test-$curve.key ]; then
log openssl pkey -in test-$curve.key -out test-$curve.pub -pubout
fi
fi
done
# EC-RDSA
for m in \
gost2012_256:A \
gost2012_256:B \
gost2012_256:C \
gost2012_512:A \
gost2012_512:B; do
IFS=':' read -r algo param <<< "$m"
if [ "$1" = clean ] || [ "$1" = force ]; then
rm -f "test-$algo-$param.key" "test-$algo-$param.cer" "test-$algo-$param.pub"
fi
if [ "$1" = clean ]; then
continue
fi
[ -e "test-$algo-$param.key" ] && continue
log openssl req -nodes -x509 -utf8 -days 10000 -batch \
-config test-ca.conf \
-newkey "$algo" \
-pkeyopt "paramset:$param" \
-out "test-$algo-$param.cer" -outform DER \
-keyout "test-$algo-$param.key"
if [ -s "test-$algo-$param.key" ]; then
log openssl pkey -in "test-$algo-$param.key" -out "test-$algo-$param.pub" -pubout
fi
done
# SM2, If openssl 3.0 is installed, gen SM2 keys using
if [ -x /opt/openssl3/bin/openssl ]; then
(PATH=/opt/openssl3/bin:$PATH LD_LIBRARY_PATH=/opt/openssl3/lib
for curve in sm2; do
if [ "$1" = clean ] || [ "$1" = force ]; then
rm -f test-$curve.cer test-$curve.key test-$curve.pub
fi
if [ "$1" = clean ]; then
continue
fi
if [ ! -e test-$curve.key ]; then
log openssl req -verbose -new -nodes -utf8 -days 10000 -batch -x509 \
-sm3 -sigopt "distid:1234567812345678" \
-config test-ca.conf \
-copy_extensions copyall \
-newkey $curve \
-out test-$curve.cer -outform DER \
-keyout test-$curve.key
if [ -s test-$curve.key ]; then
log openssl pkey -in test-$curve.key -out test-$curve.pub -pubout
fi
fi
done)
fi
# This script leaves test-ca.conf, *.cer, *.pub, *.key files for sing/verify tests.
# They are never deleted except by `make distclean'.

8
tests/ima_fix_dir.sh Executable file
View File

@ -0,0 +1,8 @@
#!/bin/sh
dir=${1:-/}
echo "Fixing dir: $dir"
find $dir \( -fstype rootfs -o -fstype ext3 -o -fstype ext4 \) -type f -exec openclose '{}' \;

View File

@ -1,79 +0,0 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
#
# evmctl ima_hash tests
#
# Copyright (C) 2020 Vitaly Chikunov <vt@altlinux.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
cd "$(dirname "$0")" || exit 1
PATH=../src:$PATH
source ./functions.sh
_require evmctl openssl getfattr
trap _report_exit_and_cleanup EXIT
set -f # disable globbing
check() {
local alg=$1 prefix=$2 chash=$3 hash
local file=$alg-hash.txt
rm -f "$file"
touch "$file"
# Generate hash with openssl, if it failed skip test,
# unless it's negative test, then pass to evmctl
cmd="openssl dgst $OPENSSL_ENGINE -$alg $file"
echo - "$cmd"
hash=$(set -o pipefail; $cmd 2>/dev/null | cut -d' ' -f2)
if [ $? -ne 0 ] && _test_expected_to_pass; then
echo "${CYAN}$alg test is skipped$NORM"
rm "$file"
return "$SKIP"
fi
if [ "$chash" ] && [ "$chash" != "$hash" ]; then
color_red
echo "Invalid hash for $alg from openssl"
echo "Expected: $chash"
echo "Returned: $hash"
color_restore
rm "$file"
return "$HARDFAIL"
fi
ADD_TEXT_FOR=$alg ADD_DEL=$file \
_evmctl_run ima_hash --hashalgo "$alg" --xattr-user "$file" || return
ADD_TEXT_FOR=$alg \
_test_xattr "$file" user.ima "$prefix$hash" || return
rm "$file"
return "$OK"
}
# check args: algo hdr-prefix canonic-hash
expect_pass check md4 0x01 31d6cfe0d16ae931b73c59d7e0c089c0
expect_pass check md5 0x01 d41d8cd98f00b204e9800998ecf8427e
expect_pass check sha1 0x01 da39a3ee5e6b4b0d3255bfef95601890afd80709
expect_fail check SHA1 0x01 # uppercase
expect_fail check sha512-224 0x01 # valid for pkcs1
expect_fail check sha512-256 0x01 # valid for pkcs1
expect_fail check unknown 0x01 # nonexistent
expect_pass check sha224 0x0407 d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f
expect_pass check sha256 0x0404 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
expect_pass check sha384 0x0405 38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b
expect_pass check sha512 0x0406 cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e
expect_pass check rmd160 0x0403 9c1185a5c5e9fc54612808977ee8f548b2258d31
expect_pass check sm3 0x0411 1ab21d8355cfa17f8e61194831e81a8f22bec8c728fefb747ed035eb5082aa2b
_enable_gost_engine
expect_pass check md_gost12_256 0x0412 3f539a213e97c802cc229d474c6aa32a825a360b2a933a949fd925208d9ce1bb
expect_pass check streebog256 0x0412 3f539a213e97c802cc229d474c6aa32a825a360b2a933a949fd925208d9ce1bb
expect_pass check md_gost12_512 0x0413 8e945da209aa869f0455928529bcae4679e9873ab707b55315f56ceb98bef0a7362f715528356ee83cda5f2aac4c6ad2ba3a715c1bcd81cb8e9f90bf4c1c1a8a
expect_pass check streebog512 0x0413 8e945da209aa869f0455928529bcae4679e9873ab707b55315f56ceb98bef0a7362f715528356ee83cda5f2aac4c6ad2ba3a715c1bcd81cb8e9f90bf4c1c1a8a

View File

@ -1,23 +0,0 @@
#!/bin/bash
set -ex
if [ -z "$COMPILE_SSL" ]; then
echo "Missing \$COMPILE_SSL!" >&2
exit 1
fi
version=${COMPILE_SSL}
wget --no-check-certificate https://github.com/openssl/openssl/archive/refs/tags/${version}.tar.gz
tar --no-same-owner -xzf ${version}.tar.gz
cd openssl-${version}
./Configure --prefix=/opt/openssl3 --openssldir=/opt/openssl3/ssl
make -j$(nproc)
# only install apps and library
sudo make install_sw
cd ..
rm -rf ${version}.tar.gz
rm -rf openssl-${version}

View File

@ -1,21 +0,0 @@
#!/bin/sh -ex
# No need to run via sudo if we already have permissions.
# Also, some distros do not have sudo configured for root:
# `root is not in the sudoers file. This incident will be reported.'
if [ -w /usr/local/bin ]; then
SUDO=
else
SUDO=sudo
fi
version=1637
wget --no-check-certificate https://sourceforge.net/projects/ibmswtpm2/files/ibmtpm${version}.tar.gz/download
mkdir ibmtpm$version
cd ibmtpm$version
tar --no-same-owner -xvzf ../download
cd src
make -j$(nproc)
$SUDO cp tpm_server /usr/local/bin/
cd ../..

View File

@ -1,8 +0,0 @@
#!/bin/sh
set -ex
git clone https://git.code.sf.net/p/ibmtpm20tss/tss
cd tss
autoreconf -i && ./configure --disable-tpm-1.2 --disable-hwtpm && make -j$(nproc) && sudo make install
cd ..
rm -rf tss

20
tests/openclose.c Normal file
View File

@ -0,0 +1,20 @@
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int fd;
fd = open(argv[1], O_RDONLY);
if (fd < 0) {
perror("open()");
exit(1);
}
close(fd);
return 0;
}

View File

@ -1 +0,0 @@
10 2e03b3fdb0014fc8bae2a07ca33ae67125b290f3 ima-ng sha256:83d19723ef3b3c05bb8ae70d86b3886c158f2408f1b71ed265886a7b79eb700e boot_aggregate

View File

@ -1,25 +0,0 @@
pcrread: tsspcrread -halg sha1
0: 92c1850372e9493929aa9a2e9ea953e21ff1be45
1: 41c54039ca2750ea60d8ab7c48b142b10aba5667
2: b2a83b0ebf2f8374299a5b2bdfc31ea955ad7236
3: b2a83b0ebf2f8374299a5b2bdfc31ea955ad7236
4: 4c1a19aad90f770956ff5ee00334a2d548b1a350
5: a1444a8a9904666165730168b3ae489447d3cef7
6: b2a83b0ebf2f8374299a5b2bdfc31ea955ad7236
7: 5c6327a67ff36f138e0b7bb1d2eafbf8a6e52ebf
8: fed489d2e5f9f85136e5ff53553d5f8b978dbe1a
9: a2fa191f2622bb014702013bfebfca9fe210d9e5
10: 3134641a3e8a1f5f75fa850bb21c3104d6ab863b
11: 0000000000000000000000000000000000000000
12: 0000000000000000000000000000000000000000
13: 0000000000000000000000000000000000000000
14: 71161a5707051fa7d6f584d812240b2e80f61942
15: 0000000000000000000000000000000000000000
16: 0000000000000000000000000000000000000000
17: ffffffffffffffffffffffffffffffffffffffff
18: ffffffffffffffffffffffffffffffffffffffff
19: ffffffffffffffffffffffffffffffffffffffff
20: ffffffffffffffffffffffffffffffffffffffff
21: ffffffffffffffffffffffffffffffffffffffff
22: ffffffffffffffffffffffffffffffffffffffff
23: 0000000000000000000000000000000000000000

View File

@ -1,439 +0,0 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
#
# evmctl {,ima_}{sign,verify} tests
#
# Copyright (C) 2020 Vitaly Chikunov <vt@altlinux.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
cd "$(dirname "$0")" || exit 1
PATH=../src:$PATH
source ./functions.sh
_require cmp evmctl getfattr openssl xxd
if cmp -b 2>&1 | grep -q "invalid option"; then
echo "cmp does not support -b (cmp from busybox?) Use cmp from diffutils"
exit "$HARDFAIL"
fi
./gen-keys.sh >/dev/null 2>&1
trap _report_exit_and_cleanup EXIT
WORKDIR=$(mktemp -d)
set -f # disable globbing
# Determine keyid from a cert
_keyid_from_cert() {
local cer=${1%.*}.cer cmd
local tmp
cer=test-${cer#test-}
# shellcheck disable=SC2086
cmd="openssl x509 $OPENSSL_ENGINE \
-in $cer -inform DER -pubkey -noout"
id=$($cmd 2>/dev/null \
| openssl asn1parse \
| grep BIT.STRING \
| tail -n1 \
| cut -d: -f1)
if [ -z "$id" ]; then
echo - "$cmd" >&2
echo "Cannot asn1parse $cer to determine keyid" >&2
exit 1
fi
tmp=$(mktemp)
# shellcheck disable=SC2086
openssl x509 $OPENSSL_ENGINE \
-in "$cer" -inform DER -pubkey -noout 2>/dev/null \
| openssl asn1parse -strparse "$id" -out "$tmp" -noout
# shellcheck disable=SC2002
cat "$tmp" \
| openssl dgst -c -sha1 \
| cut -d' ' -f2 \
| grep -o ":..:..:..:..$" \
| tr -d :
rm -f "$tmp"
}
# Convert test $type into evmctl op prefix
_op() {
if [ "$1" = ima ]; then
echo ima_
fi
}
# Convert test $type into xattr name
_xattr() {
if [ "$1" = ima ]; then
echo user.ima
else
echo user.evm
fi
}
# Check that detached signature matches xattr signature
_test_sigfile() {
local file=$1 attr=$2 file_sig=$3 file_sig2=$4
if [ ! -e "$file_sig" ]; then
color_red
echo "evmctl ima_sign: no detached signature $file_sig"
color_restore
rm "$file"
return "$FAIL"
fi
_extract_xattr "$file" "$attr" "$file_sig2"
if ! cmp -bl "$file_sig" "$file_sig2"; then
color_red
echo "evmctl ima_sign: xattr signature on $file differ from detached $file_sig"
color_restore
rm "$file" "$file_sig" "$file_sig2"
return "$FAIL"
fi
# Leave '$file_sig' for ima_verify --sigfile test.
rm "$file_sig2"
}
# Run single sign command
_evmctl_sign() {
local type=$1 key=$2 alg=$3 file=$4 opts=$5
# Can check --sigfile for ima_sign
[ "$type" = ima ] && opts+=" --sigfile"
# shellcheck disable=SC2086
ADD_TEXT_FOR="$alg ($key)" ADD_DEL=$file \
_evmctl_run "$(_op "$type")sign" $opts \
--hashalgo "$alg" --key "$key" --xattr-user "$file" || return
if [ "$type" = ima ]; then
_test_sigfile "$file" "$(_xattr "$type")" "$file.sig" "$file.sig2"
fi
}
# Run and test {ima_,}sign operation
check_sign() {
# Arguments are passed via global vars:
# TYPE (ima or evm),
# KEY,
# ALG (hash algo),
# PREFIX (signature header prefix in hex),
# OPTS (additional options for evmctl),
# FILE (working file to sign).
local "$@"
local key verifykey
local FILE=${FILE:-$ALG.txt}
# Normalize key filename if it's not a pkcs11 URI
if [ ${KEY:0:7} != pkcs11: ]; then
key=${KEY%.*}.key
key=test-${key#test-}
else
key=${KEY}
fi
# Append suffix to files for negative tests, because we may
# leave only good files for verify tests.
_test_expected_to_fail && FILE+='~'
rm -f $FILE
if ! touch $FILE; then
color_red
echo "Can't create test file: $FILE"
color_restore
return "$HARDFAIL"
fi
if _test_expected_to_pass; then
# Can openssl work with this digest?
cmd="openssl dgst $OPENSSL_ENGINE $OPENSSL_KEYFORM -$ALG $FILE"
echo - "$cmd"
if ! $cmd >/dev/null; then
echo "${CYAN}$ALG ($key) test is skipped (openssl is unable to digest)$NORM"
return "$SKIP"
fi
if [ "${key:0:7}" != pkcs11: ] && [ ! -e "$key" ]; then
echo "${CYAN}$ALG ($key) test is skipped (key file not found)$NORM"
return "$SKIP"
fi
# Can openssl sign with this digest and key?
cmd="openssl dgst $OPENSSL_ENGINE $OPENSSL_KEYFORM -$ALG -sign $key -hex $FILE"
echo - "$cmd"
if ! $cmd >/dev/null; then
echo "${CYAN}$ALG ($key) test is skipped (openssl is unable to sign)$NORM"
return "$SKIP"
fi
fi
# Insert keyid from cert into PREFIX in-place of marker `:K:'
if [[ $PREFIX =~ :K: ]]; then
keyid=$(_keyid_from_cert "$key")
if [ $? -ne 0 ]; then
color_red
echo "Unable to determine keyid for $key"
color_restore
return "$HARDFAIL"
fi
[ "$VERBOSE" -gt 2 ] && echo " Expected keyid: $keyid"
PREFIX=${PREFIX/:K:/$keyid}
fi
# Perform signing by evmctl
_evmctl_sign "$TYPE" "$key" "$ALG" "$FILE" "$OPTS" || return
# First simple pattern match the signature.
ADD_TEXT_FOR=$ALG \
_test_xattr "$FILE" "$(_xattr "$TYPE")" "$PREFIX.*" || return
# This is all we can do for v1 signatures.
[[ "$OPTS" =~ --rsa ]] && return "$OK"
# This is all we can do for evm.
[[ "$TYPE" =~ evm ]] && return "$OK"
# When using the SM2/3 algorithm, the openssl tool uses USERID for verify,
# which is incompatible with calling API directly, so skip it.
[[ "$ALG" == sm3 ]] && return "$OK"
# Extract signature to a file
_extract_xattr "$FILE" "$(_xattr "$TYPE")" "$FILE.sig2" "$PREFIX"
# Verify extracted signature with openssl
if [ "${key:0:7}" != pkcs11: ]; then
verifykey=${key%.*}.pub
else
verifykey=${key}
fi
cmd="openssl dgst $OPENSSL_ENGINE $OPENSSL_KEYFORM -$ALG -verify ${verifykey} \
-signature $FILE.sig2 $FILE"
echo - "$cmd"
if ! $cmd; then
color_red_on_failure
echo "Signature v2 verification with openssl is failed."
color_restore
rm "$FILE.sig2"
return "$FAIL"
fi
rm "$FILE.sig2"
return "$OK"
}
# Test verify operation
check_verify() {
# Arguments are passed via global vars:
# TYPE (ima or evm),
# KEY,
# ALG (hash algo),
# OPTS (additional options for evmctl),
# FILE (filename to verify).
local "$@"
# shellcheck disable=SC2086
if ! openssl dgst $OPENSSL_ENGINE -"$ALG" /dev/null >/dev/null 2>&1; then
echo $CYAN"$ALG ($KEY) test is skipped (openssl does not support $ALG)"$NORM
return $SKIP
fi
# shellcheck disable=SC2086
ADD_TEXT_FOR="$FILE ($KEY)" \
_evmctl_run "$(_op "$TYPE")verify" --key "$KEY" --xattr-user $OPTS "$FILE"
}
# Test runners
# Perform sign and verify ima and evm testing
sign_verify() {
local key=$1 alg=$2 prefix="$3" opts="$4"
local file=$alg.txt
# Set defaults:
# Public key is different for v1 and v2 (where x509 cert is used).
if [[ $opts =~ --rsa ]]; then
KEY=test-$key.pub
else
KEY=test-$key.cer
fi
ALG=$alg
PREFIX=$prefix
OPTS=$opts
FILE=$file
TYPE=ima
if expect_pass check_sign; then
# Normal verify with proper key should pass
expect_pass check_verify
expect_pass check_verify OPTS="--sigfile"
# Multiple files and some don't verify
expect_fail check_verify FILE="/dev/null $file"
rm "$FILE.sig"
fi
TYPE=evm
# Avoid running blkid for evm tests which may require root
# No generation on overlayfs:
# ioctl(3, FS_IOC_GETVERSION, 0x7ffd8e0bd628) = -1 ENOTTY (Inappropriate ioctl for device)
OPTS="$opts --uuid --generation 0"
if expect_pass check_sign; then
# Normal verify with proper key
expect_pass check_verify
# Verify with wrong key
expect_fail check_verify KEY=rsa2048
fi
# Note: Leaving TYPE=evm and file is evm signed
}
# Test --keys
try_different_keys() {
# This run after sign_verify which leaves
# TYPE=evm and file is evm signed
# v2 signing can work with multiple keys in --key option
if [[ ! $OPTS =~ --rsa ]]; then
# Have correct key in the key list
expect_pass check_verify KEY="test-rsa2048.cer,$KEY"
expect_pass check_verify KEY="/dev/null,$KEY,"
fi
# Try key that is not used for signing
expect_fail check_verify KEY=rsa2048
# Try completely wrong key files
expect_fail check_verify KEY=/dev/null
expect_fail check_verify KEY=/dev/zero
}
try_different_sigs() {
# TYPE=evm and file is evm signed
# Test --imasig
if expect_pass check_sign OPTS="$OPTS --imasig"; then
# Verify both evm and ima sigs
expect_pass check_verify
expect_pass check_verify TYPE=ima
fi
# Test --imahash
if expect_pass check_sign OPTS="$OPTS --imahash"; then
expect_pass check_verify
# IMA hash is not verifiable by ima_verify
expect_fail check_verify TYPE=ima
fi
# Test --portable (only supported for V2 signatures)
if expect_pass check_sign OPTS="$OPTS --portable --imahash" PREFIX=0x05; then
if [[ "$OPTS" =~ --rsa ]]; then
expect_fail check_verify
else
expect_pass check_verify
fi
fi
# Test -i (immutable)
expect_pass check_sign OPTS="$OPTS -i" PREFIX=0x0303
# Cannot be verified for now
}
# Single test args: type key hash signature-prefix "evmctl-options"
# sign_verify args: key hash signature-prefix "evmctl-options"
# Only single test can be prefixed with expect_{fail,pass}
# `sign_verify' can not be prefixed with expect_{fail,pass} because
# it runs multiple tests inside. See more tests there.
# signature-prefix can contain `:K:' which will be resolved to keyid (v2 only)
## Test v1 signatures
# Signature v1 only supports sha1 and sha256 so any other should fail
expect_fail \
check_sign TYPE=ima KEY=rsa1024 ALG=md5 PREFIX=0x0301 OPTS=--rsa
sign_verify rsa1024 sha1 0x0301 --rsa
sign_verify rsa1024 sha256 0x0301 --rsa
try_different_keys
try_different_sigs
## Test v2 signatures with RSA PKCS#1
# List of allowed hashes much greater but not all are supported.
sign_verify rsa1024 md5 0x030201:K:0080
sign_verify rsa1024 sha1 0x030202:K:0080
sign_verify rsa1024 sha224 0x030207:K:0080
expect_pass check_sign TYPE=ima KEY=rsa1024 ALG=sha256 PREFIX=0x030204aabbccdd0080 OPTS=--keyid=aabbccdd
expect_pass check_sign TYPE=ima KEY=rsa1024 ALG=sha256 PREFIX=0x030204:K:0080 OPTS=--keyid-from-cert=test-rsa1024.cer
expect_pass check_sign TYPE=ima KEY=rsa1024_skid ALG=sha256 PREFIX=0x030204123456780080
sign_verify rsa1024 sha256 0x030204:K:0080
try_different_keys
try_different_sigs
sign_verify rsa1024 sha384 0x030205:K:0080
sign_verify rsa1024 sha512 0x030206:K:0080
sign_verify rsa1024 rmd160 0x030203:K:0080
# Test v2 signatures with ECDSA
# Signature length is typically 0x34-0x38 bytes long, very rarely 0x33
sign_verify prime192v1 sha1 0x030202:K:003[345678]
sign_verify prime192v1 sha224 0x030207:K:003[345678]
sign_verify prime192v1 sha256 0x030204:K:003[345678]
sign_verify prime192v1 sha384 0x030205:K:003[345678]
sign_verify prime192v1 sha512 0x030206:K:003[345678]
# Signature length is typically 0x44-0x48 bytes long, very rarely 0x43
sign_verify prime256v1 sha1 0x030202:K:004[345678]
sign_verify prime256v1 sha224 0x030207:K:004[345678]
sign_verify prime256v1 sha256 0x030204:K:004[345678]
sign_verify prime256v1 sha384 0x030205:K:004[345678]
sign_verify prime256v1 sha512 0x030206:K:004[345678]
# If openssl 3.0 is installed, test the SM2/3 algorithm combination
if [ -x /opt/openssl3/bin/openssl ]; then
PATH=/opt/openssl3/bin:$PATH LD_LIBRARY_PATH=/opt/openssl3/lib \
sign_verify sm2 sm3 0x030211:K:004[345678]
fi
# Test v2 signatures with EC-RDSA
_enable_gost_engine
sign_verify gost2012_256-A md_gost12_256 0x030212:K:0040
sign_verify gost2012_256-B md_gost12_256 0x030212:K:0040
sign_verify gost2012_256-C md_gost12_256 0x030212:K:0040
sign_verify gost2012_512-A md_gost12_512 0x030213:K:0080
sign_verify gost2012_512-B md_gost12_512 0x030213:K:0080
# Test if signing with wrong key length does not work.
expect_fail \
check_sign TYPE=ima KEY=gost2012_512-B ALG=md_gost12_256 PREFIX=0x0302 OPTS=
expect_fail \
check_sign TYPE=ima KEY=gost2012_256-B ALG=md_gost12_512 PREFIX=0x0302 OPTS=
# Test signing with key described by pkcs11 URI
_softhsm_setup "${WORKDIR}"
if [ -n "${PKCS11_KEYURI}" ]; then
expect_pass check_sign FILE=pkcs11test TYPE=ima KEY=${PKCS11_KEYURI} ALG=sha256 PREFIX=0x030204aabbccdd0100 OPTS=--keyid=aabbccdd
expect_pass check_sign FILE=pkcs11test TYPE=ima KEY=${PKCS11_KEYURI} ALG=sha1 PREFIX=0x030202aabbccdd0100 OPTS=--keyid=aabbccdd
else
# to have a constant number of tests, skip these two tests
__skip() { echo "pkcs11 test is skipped: could not setup softhsm"; return $SKIP; }
expect_pass __skip
expect_pass __skip
fi
_softhsm_teardown "${WORKDIR}"

View File

@ -1,293 +0,0 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: GPL-2.0 and BSD-3-clause
# This program originates from 'swtpm' project (https://github.com/stefanberger/swtpm/)
if [ -z "$(type -P p11tool)" ]; then
echo "Need p11tool from gnutls"
exit 77
fi
if [ -z "$(type -P softhsm2-util)" ]; then
echo "Need softhsm2-util from softhsm2 package"
exit 77
fi
MAJOR=$(softhsm2-util -v | cut -d '.' -f1)
MINOR=$(softhsm2-util -v | cut -d '.' -f2)
if [ ${MAJOR} -lt 2 ] || [ ${MAJOR} -eq 2 -a ${MINOR} -lt 2 ]; then
echo "Need softhsm v2.2.0 or later"
exit 77
fi
NAME=swtpm-test
PIN=${PIN:-1234}
SO_PIN=${SO_PIN:-1234}
SOFTHSM_SETUP_CONFIGDIR=${SOFTHSM_SETUP_CONFIGDIR:-~/.config/softhsm2}
export SOFTHSM2_CONF=${SOFTHSM_SETUP_CONFIGDIR}/softhsm2.conf
UNAME_S="$(uname -s)"
case "${UNAME_S}" in
Darwin)
msg=$(sudo -v -n)
if [ $? -ne 0 ]; then
echo "Need password-less sudo rights on OS X to change /etc/gnutls/pkcs11.conf"
exit 1
fi
;;
esac
teardown_softhsm() {
local configdir=${SOFTHSM_SETUP_CONFIGDIR}
local configfile=${SOFTHSM2_CONF}
local bakconfigfile=${configfile}.bak
local tokendir=${configdir}/tokens
softhsm2-util --token "${NAME}" --delete-token &>/dev/null
case "${UNAME_S}" in
Darwin*)
if [ -f /etc/gnutls/pkcs11.conf.bak ]; then
sudo rm -f /etc/gnutls/pkcs11.conf
sudo mv /etc/gnutls/pkcs11.conf.bak \
/etc/gnutls/pkcs11.conf &>/dev/null
fi
;;
esac
if [ -f "$bakconfigfile" ]; then
mv "$bakconfigfile" "$configfile"
else
rm -f "$configfile"
fi
if [ -d "$tokendir" ]; then
rm -rf "${tokendir}"
fi
return 0
}
setup_softhsm() {
local msg tokenuri keyuri
local configdir=${SOFTHSM_SETUP_CONFIGDIR}
local configfile=${SOFTHSM2_CONF}
local bakconfigfile=${configfile}.bak
local tokendir=${configdir}/tokens
local rc
case "${UNAME_S}" in
Darwin*)
if [ -f /etc/gnutls/pkcs11.conf.bak ]; then
echo "/etc/gnutls/pkcs11.conf.bak already exists; need to 'teardown' first"
return 1
fi
sudo mv /etc/gnutls/pkcs11.conf \
/etc/gnutls/pkcs11.conf.bak &>/dev/null
if [ $(id -u) -eq 0 ]; then
SONAME="$(sudo -u nobody brew ls --verbose softhsm | \
grep -E "\.so$")"
else
SONAME="$(brew ls --verbose softhsm | \
grep -E "\.so$")"
fi
sudo mkdir -p /etc/gnutls &>/dev/null
sudo bash -c "echo "load=${SONAME}" > /etc/gnutls/pkcs11.conf"
;;
esac
if ! [ -d $configdir ]; then
mkdir -p $configdir
fi
mkdir -p ${tokendir}
if [ -f $configfile ]; then
mv "$configfile" "$bakconfigfile"
fi
if ! [ -f $configfile ]; then
cat <<_EOF_ > $configfile
directories.tokendir = ${tokendir}
objectstore.backend = file
log.level = DEBUG
slots.removable = false
_EOF_
fi
msg=$(p11tool --list-tokens 2>&1 | grep "token=${NAME}" | tail -n1)
if [ $? -ne 0 ]; then
echo "Could not list existing tokens"
echo "$msg"
fi
tokenuri=$(echo "$msg" | sed -n 's/.*URL: \([[:print:]*]\)/\1/p')
if [ -z "$tokenuri" ]; then
msg=$(softhsm2-util \
--init-token --pin ${PIN} --so-pin ${SO_PIN} \
--free --label ${NAME} 2>&1)
if [ $? -ne 0 ]; then
echo "Could not initialize token"
echo "$msg"
return 2
fi
slot=$(echo "$msg" | \
sed -n 's/.* reassigned to slot \([0-9]*\)$/\1/p')
if [ -z "$slot" ]; then
slot=$(softhsm2-util --show-slots | \
grep -E "^Slot " | head -n1 |
sed -n 's/Slot \([0-9]*\)/\1/p')
if [ -z "$slot" ]; then
echo "Could not parse slot number from output."
echo "$msg"
return 3
fi
fi
msg=$(p11tool --list-tokens 2>&1 | \
grep "token=${NAME}" | tail -n1)
if [ $? -ne 0 ]; then
echo "Could not list existing tokens"
echo "$msg"
fi
tokenuri=$(echo "$msg" | sed -n 's/.*URL: \([[:print:]*]\)/\1/p')
if [ -z "${tokenuri}" ]; then
echo "Could not get tokenuri!"
return 4
fi
# more recent versions of p11tool have --generate-privkey ...
msg=$(GNUTLS_PIN=$PIN p11tool \
--generate-privkey=rsa --bits 2048 --label mykey --login \
"${tokenuri}" 2>&1)
if [ $? -ne 0 ]; then
# ... older versions have --generate-rsa
msg=$(GNUTLS_PIN=$PIN p11tool \
--generate-rsa --bits 2048 --label mykey --login \
"${tokenuri}" 2>&1)
if [ $? -ne 0 ]; then
echo "Could not create RSA key!"
echo "$msg"
return 5
fi
fi
fi
getkeyuri_softhsm $slot
rc=$?
if [ $rc -ne 0 ]; then
teardown_softhsm
fi
return $rc
}
_getkeyuri_softhsm() {
local msg tokenuri keyuri
msg=$(p11tool --list-tokens 2>&1 | grep "token=${NAME}")
if [ $? -ne 0 ]; then
echo "Could not list existing tokens"
echo "$msg"
return 5
fi
tokenuri=$(echo "$msg" | sed -n 's/.*URL: \([[:print:]*]\)/\1/p')
if [ -z "$tokenuri" ]; then
echo "Could not get token URL"
echo "$msg"
return 6
fi
msg=$(p11tool --list-all ${tokenuri} 2>&1)
if [ $? -ne 0 ]; then
echo "Could not list object under token $tokenuri"
echo "$msg"
softhsm2-util --show-slots
return 7
fi
keyuri=$(echo "$msg" | sed -n 's/.*URL: \([[:print:]*]\)/\1/p')
if [ -z "$keyuri" ]; then
echo "Could not get key URL"
echo "$msg"
return 8
fi
echo "$keyuri"
return 0
}
getkeyuri_softhsm() {
local keyuri rc
keyuri=$(_getkeyuri_softhsm)
rc=$?
if [ $rc -ne 0 ]; then
return $rc
fi
echo "keyuri: $keyuri?pin-value=${PIN}" #&module-name=softhsm2"
return 0
}
getpubkey_softhsm() {
local keyuri rc
keyuri=$(_getkeyuri_softhsm)
rc=$?
if [ $rc -ne 0 ]; then
return $rc
fi
GNUTLS_PIN=${PIN} p11tool --export-pubkey "${keyuri}" --login 2>/dev/null
return $?
}
usage() {
cat <<_EOF_
Usage: $0 [command]
Supported commands are:
setup : Setup the user's account for softhsm and create a
token and key with a test configuration
getkeyuri : Get the key's URI; may only be called after setup
getpubkey : Get the public key in PEM format; may only be called after setup
teardown : Remove the temporary softhsm test configuration
_EOF_
}
main() {
local ret
if [ $# -lt 1 ]; then
usage $0
echo -e "Missing command.\n\n"
return 1
fi
case "$1" in
setup)
setup_softhsm
ret=$?
;;
getkeyuri)
getkeyuri_softhsm
ret=$?
;;
getpubkey)
getpubkey_softhsm
ret=$?
;;
teardown)
teardown_softhsm
ret=$?
;;
*)
echo -e "Unsupported command: $1\n\n"
usage $0
ret=1
esac
return $ret
}
main "$@"
exit $?

View File

@ -1,3 +0,0 @@
10 cf41b43c4031672fcc2bd358b309ad33b977424f ima-ng sha256:f1b4c7c9b27e94569f4c2b64051c452bc609c3cb891dd7fae06b758f8bc83d14 boot_aggregate
10 983dcd8e6f7c84a1a5f10e762d1850623966ceab ima-ng sha256:ae06e032a65fed8102aff5f8f31c678dcf2eb25b826f77ecb699faa0411f89e0 /init
10 b6e4d01c73f6e4b698eaf48e7d76a2bae0c02514 ima-ng sha256:4b1764ee112aa8b2a6ae9a3a2f1e272b6601681f610708497673cd49e5bd2f5c /bin/sh

Binary file not shown.