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

1 Commits

Author SHA1 Message Date
f27e2f7d99 ima-evm-utils: Fix reading of sigfile
Fix reading of detached IMA signature (--sigfile). Error message:

  Reading to sha1.txt.sig
  Failed to fread 147 bytes: sha1.txt.sig
  Failed reading: sha1.txt

Reported-by: Mimi Zohar <zohar@linux.ibm.com>
Fixes: 08a51e7460 ("ima-evm-utils: Fix file2bin stat and fopen relations")
Signed-off-by: Vitaly Chikunov <vt@altlinux.org>
Reviewed-by: Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>
(cherry picked from commit 19b77c8667)
2020-10-23 13:59:07 -04:00
42 changed files with 260 additions and 1951 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

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"

27
INSTALL
View File

@ -9,33 +9,10 @@ are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. This file is offered as-is,
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
==================
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
more-detailed instructions are generic; see the `README' file for
instructions specific to this package. Some packages provide this
@ -74,7 +51,7 @@ of `autoconf'.
The simplest way to compile this package is:
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
some messages telling which features it is checking for.

View File

@ -1,7 +1,5 @@
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 = autogen.sh $(doc_DATA)
@ -25,7 +23,6 @@ rpm: $(tarname)
cp $(tarname) $(SRCS)/
rpmbuild -ba --nodeps $(SPEC)
if MANPAGE_DOCBOOK_XSL
evmctl.1.html: README
@asciidoc -o $@ $<
@ -38,6 +35,5 @@ rmman:
rm -f evmctl.1
doc: evmctl.1.html rmman evmctl.1
endif
.PHONY: $(tarname)

29
NEWS
View File

@ -1,32 +1,3 @@
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:

16
README
View File

@ -28,7 +28,6 @@ COMMANDS
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
@ -41,21 +40,17 @@ COMMANDS
OPTIONS
-------
-a, --hashalgo sha1, sha224, sha256, sha384, sha512
-a, --hashalgo sha1 (default), 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)
-t, --type file types to fix 'fdsxm' (f: file, d: directory, s: block/char/symlink)
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
@ -71,10 +66,6 @@ OPTIONS
-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
------------
@ -133,9 +124,6 @@ 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
----------------

View File

@ -1,4 +1,16 @@
#! /bin/sh
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

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,7 +1,7 @@
# autoconf script
AC_PREREQ([2.65])
AC_INIT(ima-evm-utils, 1.4, zohar@linux.ibm.com)
AC_INIT(ima-evm-utils, 1.3.1, zohar@linux.ibm.com)
AM_INIT_AUTOMAKE([foreign])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIR([m4])
@ -30,14 +30,9 @@ AC_SUBST(KERNEL_HEADERS)
AC_CHECK_HEADER(unistd.h)
AC_CHECK_HEADERS(openssl/conf.h)
# Intel TSS
AC_CHECK_LIB([tss2-esys], [Esys_Free])
AC_CHECK_LIB([tss2-esys], [Esys_PCR_Read])
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"])
AM_CONDITIONAL([USE_PCRTSS], [test "x$ac_cv_lib_tss2_esys_Esys_PCR_Read" = "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.])])
@ -62,7 +57,6 @@ else
fi
EVMCTL_MANPAGE_DOCBOOK_XSL
AX_DEFAULT_HASH_ALGO([$KERNEL_HEADERS])
# for gcov
#CFLAGS="$CFLAGS -Wall -fprofile-arcs -ftest-coverage"
@ -82,10 +76,7 @@ echo
echo
echo "Configuration:"
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-esys: $ac_cv_lib_tss2_esys_Esys_PCR_Read"
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

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,10 +1,7 @@
dnl Copyright (c) 2018-2020 Petr Vorel <pvorel@suse.cz>
dnl Copyright (c) 2018 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],
@ -12,37 +9,20 @@ AC_DEFUN([EVMCTL_MANPAGE_DOCBOOK_XSL], [
[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])
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_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
AC_MSG_RESULT([not found])
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:/\+|/|')
DOCBOOK_XSL_URI="http://docbook.sourceforge.net/release/xsl/current"
DOCBOOK_XSL_PATH="manpages/docbook.xsl"
MANPAGE_DOCBOOK_XSL=$(${XMLCATALOG} ${XML_CATALOG_FILE} ${DOCBOOK_XSL_URI}/${DOCBOOK_XSL_PATH} | sed -n 's|^file:/\+|/|p;q')
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,5 +1,5 @@
Name: ima-evm-utils
Version: 1.4
Version: 1.3.1
Release: 1%{?dist}
Summary: ima-evm-utils - IMA/EVM control utility
Group: System/Libraries

1
src/.gitignore vendored
View File

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

View File

@ -4,7 +4,7 @@ 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_LDFLAGS = -version-info 2:0:0
libimaevm_la_LIBADD = $(LIBCRYPTO_LIBS)
include_HEADERS = imaevm.h
@ -22,21 +22,10 @@ evmctl_CPPFLAGS = $(AM_CPPFLAGS) $(LIBCRYPTO_CFLAGS)
evmctl_LDFLAGS = $(LDFLAGS_READLINE)
evmctl_LDADD = $(LIBCRYPTO_LIBS) -lkeyutils libimaevm.la
# USE_PCRTSS uses the Intel TSS
if USE_PCRTSS
evmctl_SOURCES += pcr_tss.c
# USE_IBMTSS uses the IBM TSS
evmctl_SOURCES += pcr_tss.c
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
evmctl_SOURCES += pcr_tsspcrread.c
endif
AM_CPPFLAGS = -I$(top_srcdir) -include config.h

View File

@ -42,7 +42,6 @@
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
@ -58,14 +57,12 @@
#include <termios.h>
#include <assert.h>
#include <openssl/asn1.h>
#include <openssl/sha.h>
#include <openssl/pem.h>
#include <openssl/hmac.h>
#include <openssl/err.h>
#include <openssl/rsa.h>
#include <openssl/engine.h>
#include <openssl/x509v3.h>
#include "hash_info.h"
#include "pcr.h"
#include "utils.h"
@ -128,7 +125,6 @@ static char *caps_str;
static char *ima_str;
static char *selinux_str;
static char *search_type;
static char *verify_bank;
static int verify_list_sig;
static int recursive;
static int msize;
@ -145,6 +141,10 @@ typedef int (*find_cb_t)(const char *path);
static int find(const char *path, int dts, find_cb_t func);
#define REG_MASK (1 << DT_REG)
#define DIR_MASK (1 << DT_DIR)
#define LNK_MASK (1 << DT_LNK)
#define CHR_MASK (1 << DT_CHR)
#define BLK_MASK (1 << DT_BLK)
struct command cmds[];
static void print_usage(struct command *cmd);
@ -365,7 +365,9 @@ static int calc_evm_hash(const char *file, unsigned char *hash)
st.st_mode = strtoul(mode_str, NULL, 10);
if (!evm_immutable) {
if (S_ISREG(st.st_mode) && !generation_str) {
if ((S_ISREG(st.st_mode) || S_ISDIR(st.st_mode)) && !generation_str) {
/* we cannot at the momement to get generation of
special files kernel API does not support it */
int fd = open(file, 0);
if (fd < 0) {
@ -402,8 +404,6 @@ static int calc_evm_hash(const char *file, unsigned char *hash)
}
for (xattrname = evm_config_xattrnames; *xattrname != NULL; xattrname++) {
int use_xattr_ima = 0;
if (!strcmp(*xattrname, XATTR_NAME_SELINUX) && selinux_str) {
err = strlen(selinux_str) + 1;
if (err > sizeof(xattr_value)) {
@ -420,15 +420,6 @@ static int calc_evm_hash(const char *file, unsigned char *hash)
return -1;
}
hex2bin(xattr_value, ima_str, err);
} else if (!strcmp(*xattrname, XATTR_NAME_IMA) && evm_portable){
err = lgetxattr(file, xattr_ima, xattr_value,
sizeof(xattr_value));
if (err < 0) {
log_err("EVM portable sig: %s required\n",
xattr_ima);
return -1;
}
use_xattr_ima = 1;
} else if (!strcmp(*xattrname, XATTR_NAME_CAPS) && (hmac_flags & HMAC_FLAG_CAPS_SET)) {
if (!caps_str)
continue;
@ -451,8 +442,7 @@ static int calc_evm_hash(const char *file, unsigned char *hash)
}
}
/*log_debug("name: %s, value: %s, size: %d\n", *xattrname, xattr_value, err);*/
log_info("name: %s, size: %d\n",
use_xattr_ima ? xattr_ima : *xattrname, err);
log_info("name: %s, size: %d\n", *xattrname, err);
log_debug_dump(xattr_value, err);
err = EVP_DigestUpdate(pctx, xattr_value, err);
if (!err) {
@ -665,6 +655,10 @@ static int get_file_type(const char *path, const char *search_type)
switch (search_type[i]) {
case 'f':
dts |= REG_MASK; break;
case 'd':
dts |= DIR_MASK; break;
case 's':
dts |= BLK_MASK | CHR_MASK | LNK_MASK; break;
case 'x':
check_xattr = true; break;
case 'm':
@ -813,20 +807,11 @@ static int verify_evm(const char *file)
return len;
}
if ((sig[0] != EVM_IMA_XATTR_DIGSIG) &&
(sig[0] != EVM_XATTR_PORTABLE_DIGSIG)) {
if (sig[0] != 0x03) {
log_err("%s has no signature\n", xattr_evm);
return -1;
}
if (sig[0] == EVM_XATTR_PORTABLE_DIGSIG) {
if (sig[1] != DIGSIG_VERSION_2) {
log_err("Portable sig: invalid type\n");
return -1;
}
evm_portable = true;
}
sig_hash_algo = imaevm_hash_algo_from_sig(sig + 1);
if (sig_hash_algo < 0) {
log_err("unknown hash algo: %s\n", file);
@ -1109,15 +1094,16 @@ static int calc_evm_hmac(const char *file, const char *keyfile, unsigned char *h
/* EVM key is 128 bytes */
memcpy(evmkey, key, keylen);
if (keylen < sizeof(evmkey))
memset(evmkey + keylen, 0, sizeof(evmkey) - keylen);
memset(evmkey + keylen, 0, sizeof(evmkey) - keylen);
if (lstat(file, &st)) {
log_err("Failed to stat: %s\n", file);
goto out;
}
if (S_ISREG(st.st_mode)) {
if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode)) {
/* we cannot at the momement to get generation of special files..
* kernel API does not support it */
int fd = open(file, 0);
if (fd < 0) {
@ -1363,6 +1349,9 @@ static int find(const char *path, int dts, find_cb_t func)
return -1;
}
if (dts & DIR_MASK)
func(path);
closedir(dir);
return 0;
@ -1605,15 +1594,10 @@ static struct tpm_bank_info *init_tpm_banks(int *num_banks)
/*
* Compare the calculated TPM PCR banks against the PCR values read.
* The banks_mask parameter allows to select which banks to consider.
* A banks_maks of 0x3 would consider banks 1 and 2, 0x2 would only
* consider the 2nd bank, ~0 would consider all banks.
*
* On failure to match any TPM bank, fail comparison.
*/
static int compare_tpm_banks(int num_banks, struct tpm_bank_info *bank,
struct tpm_bank_info *tpm_bank,
unsigned int banks_mask, unsigned long entry_num)
struct tpm_bank_info *tpm_bank)
{
int i, j;
int ret = 0;
@ -1621,9 +1605,6 @@ static int compare_tpm_banks(int num_banks, struct tpm_bank_info *bank,
for (i = 0; i < num_banks; i++) {
if (!bank[i].supported || !tpm_bank[i].supported)
continue;
/* do we need to look at the n-th bank ? */
if ((banks_mask & (1 << i)) == 0)
continue;
for (j = 0; j < NUM_PCRS; j++) {
if (memcmp(bank[i].pcr[j], zero, bank[i].digest_size)
== 0)
@ -1644,8 +1625,8 @@ static int compare_tpm_banks(int num_banks, struct tpm_bank_info *bank,
log_dump(tpm_bank[i].pcr[j], tpm_bank[i].digest_size);
if (!ret)
log_info("%s PCR-%d: succeed at entry %lu\n",
bank[i].algo_name, j, entry_num);
log_info("%s PCR-%d: succeed\n",
bank[i].algo_name, j);
else
log_info("%s: PCRAgg %d does not match TPM PCR-%d\n",
bank[i].algo_name, j, j);
@ -1914,8 +1895,7 @@ static int read_tpm_banks(int num_banks, struct tpm_bank_info *bank)
{
int tpm_enabled = 0;
char *errmsg = NULL;
int i;
uint32_t pcr_handle;
int i, j;
int err;
/* If --pcrs was specified, read only from the specified file(s) */
@ -1935,12 +1915,9 @@ static int read_tpm_banks(int num_banks, struct tpm_bank_info *bank)
/* Read PCRs from multiple TPM 2.0 banks */
for (i = 0; i < num_banks; i++) {
err = 0;
for (pcr_handle = 0;
pcr_handle < NUM_PCRS && !err;
pcr_handle++) {
err = tpm2_pcr_read(bank[i].algo_name, pcr_handle,
bank[i].pcr[pcr_handle],
bank[i].digest_size,
for (j = 0; j < NUM_PCRS && !err; j++) {
err = tpm2_pcr_read(bank[i].algo_name, j,
bank[i].pcr[j], bank[i].digest_size,
&errmsg);
if (err) {
log_debug("Failed to read %s PCRs: (%s)\n",
@ -1964,9 +1941,6 @@ static int ima_measurement(const char *file)
int num_banks = 0;
int tpmbanks = 1;
int first_record = 1;
unsigned int pseudo_padded_banks_mask, pseudo_banks_mask;
unsigned long entry_num = 0;
int c;
struct template_entry entry = { .template = 0 };
FILE *fp;
@ -2000,27 +1974,7 @@ static int ima_measurement(const char *file)
if (read_tpm_banks(num_banks, tpm_banks) != 0)
tpmbanks = 0;
/* A mask where each bit represents the banks to check against */
pseudo_banks_mask = (1 << num_banks) - 1;
pseudo_padded_banks_mask = pseudo_banks_mask;
/* Instead of verifying all the banks, only verify a single bank */
for (c = 0; c < num_banks; c++) {
if (verify_bank
&& strcmp(pseudo_padded_banks[c].algo_name, verify_bank)) {
pseudo_banks_mask ^= (1 << c);
pseudo_padded_banks_mask ^= (1 << c);
break;
}
}
while (fread(&entry.header, sizeof(entry.header), 1, fp) == 1) {
entry_num++;
if (entry.header.pcr >= NUM_PCRS) {
log_err("Invalid PCR %d.\n", entry.header.pcr);
fclose(fp);
exit(1);
}
while (fread(&entry.header, sizeof(entry.header), 1, fp)) {
if (entry.header.name_len > TCG_EVENT_NAME_LEN_MAX) {
log_err("%d ERROR: event name too long!\n",
entry.header.name_len);
@ -2132,33 +2086,18 @@ static int ima_measurement(const char *file)
if (!tpmbanks)
continue;
for (c = 0; c < num_banks; c++) {
if ((pseudo_banks_mask & (1 << c)) == 0)
continue;
/* The measurement list might contain too many entries,
* compare the re-calculated TPM PCR values after each
* extend.
*/
err = compare_tpm_banks(num_banks, pseudo_banks,
tpm_banks, 1 << c, entry_num);
if (!err)
pseudo_banks_mask ^= (1 << c);
}
if (pseudo_banks_mask == 0)
/* The measurement list might contain too many entries,
* compare the re-calculated TPM PCR values after each
* extend.
*/
err = compare_tpm_banks(num_banks, pseudo_banks, tpm_banks);
if (!err)
break;
for (c = 0; c < num_banks; c++) {
if ((pseudo_padded_banks_mask & (1 << c)) == 0)
continue;
/* Compare against original SHA1 zero padded TPM PCR values */
err_padded = compare_tpm_banks(num_banks,
pseudo_padded_banks,
tpm_banks,
1 << c, entry_num);
if (!err_padded)
pseudo_padded_banks_mask ^= (1 << c);
}
if (pseudo_padded_banks_mask == 0)
/* Compare against original SHA1 zero padded TPM PCR values */
err_padded = compare_tpm_banks(num_banks, pseudo_padded_banks,
tpm_banks);
if (!err_padded)
break;
}
@ -2236,12 +2175,12 @@ static int read_binary_bios_measurements(char *file, struct tpm_bank_info *bank)
log_info("Reading the TPM 1.2 event log %s.\n", file);
/* Extend the pseudo TPM PCRs with the event digest */
while (fread(&event, sizeof(event.header), 1, fp) == 1) {
while (fread(&event, sizeof(event.header), 1, fp)) {
if (imaevm_params.verbose > LOG_INFO) {
log_info("%02u ", event.header.pcr);
log_dump(event.header.digest, SHA_DIGEST_LENGTH);
}
if (event.header.pcr >= NUM_PCRS) {
if (event.header.pcr > NUM_PCRS) {
log_err("Invalid PCR %d.\n", event.header.pcr);
err = 1;
break;
@ -2500,21 +2439,17 @@ static void usage(void)
printf(
"\n"
" -a, --hashalgo sha1, sha224, sha256, sha384, sha512, streebog256, streebog512 (default: %s)\n"
" -a, --hashalgo sha1 (default), sha224, sha256, sha384, sha512, streebog256, streebog512\n"
" -s, --imasig make IMA signature\n"
" -d, --imahash make IMA hash\n"
" -f, --sigfile store IMA signature in .sig file instead of xattr\n"
" --xattr-user store xattrs in user namespace (for testing purposes)\n"
" --rsa use RSA key type and signing scheme v1\n"
" -k, --key path to signing key (default: /etc/keys/{privkey,pubkey}_evm.pem)\n"
" or a pkcs11 URI\n"
" --keyid n overwrite signature keyid with a 32-bit value in hex (for signing)\n"
" --keyid-from-cert file\n"
" read keyid value from SKID of a x509 cert file\n"
" -o, --portable generate portable EVM signatures\n"
" -p, --pass password for encrypted signing key\n"
" -r, --recursive recurse into directories (sign)\n"
" -t, --type file types to fix 'fxm' (f: file)\n"
" -t, --type file types to fix 'fdsxm' (f: file, d: directory, s: block/char/symlink)\n"
" x - skip fixing if both ima and evm xattrs exist (use with caution)\n"
" m - stay on the same filesystem (like 'find -xdev')\n"
" -n print result to stdout instead of setting xattr\n"
@ -2532,13 +2467,10 @@ static void usage(void)
" --caps use custom Capabilities for EVM(unspecified: from FS, empty: do not use)\n"
" --verify-sig verify measurement list signatures\n"
" --engine e preload OpenSSL engine e (such as: gost)\n"
" --ignore-violations ignore ToMToU measurement violations\n"
" --ignore-violations ignore ToMToU measurement violations"
" -v increase verbosity level\n"
" -h, --help display this help and exit\n"
"\n"
"Environment variables:\n\n"
"EVMCTL_KEY_PASSWORD : Private key password to use; do not use --pass option\n"
"\n", DEFAULT_HASH_ALGO);
"\n");
}
struct command cmds[] = {
@ -2552,8 +2484,8 @@ struct command cmds[] = {
{"ima_verify", cmd_verify_ima, 0, "file", "Verify IMA signature (for debugging).\n"},
{"ima_setxattr", cmd_setxattr_ima, 0, "[--sigfile file]", "Set IMA signature from sigfile\n"},
{"ima_hash", cmd_hash_ima, 0, "file", "Make file content hash.\n"},
{"ima_measurement", cmd_ima_measurement, 0, "[--ignore-violations] [--verify-sig [--key key1, key2, ...]] [--pcrs [hash-algorithm,]file [--pcrs hash-algorithm,file] ...] [--verify-bank hash-algorithm] file", "Verify measurement list (experimental).\n"},
{"ima_boot_aggregate", cmd_ima_bootaggr, 0, "[--pcrs hash-algorithm,file] [TPM 1.2 BIOS event log]", "Calculate per TPM bank boot_aggregate digests\n"},
{"ima_measurement", cmd_ima_measurement, 0, "[--ignore-violations] [--verify-sig [--key key1, key2, ...]] [--pcrs [hash-algorithm,]file [--pcrs hash-algorithm,file] ...] file", "Verify measurement list (experimental).\n"},
{"ima_boot_aggregate", cmd_ima_bootaggr, 0, "[file]", "Calculate per TPM bank boot_aggregate digests\n"},
{"ima_fix", cmd_ima_fix, 0, "[-t fdsxm] path", "Recursively fix IMA/EVM xattrs in fix mode.\n"},
{"ima_clear", cmd_ima_clear, 0, "[-t fdsxm] path", "Recursively remove IMA/EVM xattrs.\n"},
{"sign_hash", cmd_sign_hash, 0, "[--key key] [--pass [password]", "Sign hashes from shaXsum output.\n"},
@ -2593,9 +2525,6 @@ static struct option opts[] = {
{"xattr-user", 0, 0, 140},
{"ignore-violations", 0, 0, 141},
{"pcrs", 1, 0, 142},
{"verify-bank", 2, 0, 143},
{"keyid", 1, 0, 144},
{"keyid-from-cert", 1, 0, 145},
{}
};
@ -2633,36 +2562,13 @@ static char *get_password(void)
return NULL;
}
if (pwd == NULL) {
free(password);
return NULL;
}
return password;
}
static ENGINE *setup_engine(const char *engine_id)
{
ENGINE *eng = ENGINE_by_id(engine_id);
if (!eng) {
log_err("engine %s isn't available\n", optarg);
ERR_print_errors_fp(stderr);
} else if (!ENGINE_init(eng)) {
log_err("engine %s init failed\n", optarg);
ERR_print_errors_fp(stderr);
ENGINE_free(eng);
eng = NULL;
}
if (eng)
ENGINE_set_default(eng, ENGINE_METHOD_ALL);
return eng;
return pwd;
}
int main(int argc, char *argv[])
{
int err = 0, c, lind;
unsigned long keyid;
char *eptr;
ENGINE *eng = NULL;
#if !(OPENSSL_VERSION_NUMBER < 0x10100000)
OPENSSL_init_crypto(
@ -2781,9 +2687,17 @@ int main(int argc, char *argv[])
verify_list_sig = 1;
break;
case 139: /* --engine e */
imaevm_params.eng = setup_engine(optarg);
if (!imaevm_params.eng)
goto error;
eng = ENGINE_by_id(optarg);
if (!eng) {
log_err("engine %s isn't available\n", optarg);
ERR_print_errors_fp(stderr);
} else if (!ENGINE_init(eng)) {
log_err("engine %s init failed\n", optarg);
ERR_print_errors_fp(stderr);
ENGINE_free(eng);
eng = NULL;
}
ENGINE_set_default(eng, ENGINE_METHOD_ALL);
break;
case 140: /* --xattr-user */
xattr_ima = "user.ima";
@ -2799,33 +2713,6 @@ int main(int argc, char *argv[])
}
pcrfile[npcrfile++] = optarg;
break;
case 143:
verify_bank = optarg;
break;
case 144:
errno = 0;
keyid = strtoul(optarg, &eptr, 16);
/*
* ULONG_MAX is error from strtoul(3),
* UINT_MAX is `imaevm_params.keyid' maximum value,
* 0 is reserved for keyid being unset.
*/
if (errno || eptr - optarg != strlen(optarg) ||
keyid == ULONG_MAX || keyid > UINT_MAX ||
keyid == 0) {
log_err("Invalid keyid value.\n");
exit(1);
}
imaevm_params.keyid = keyid;
break;
case 145:
keyid = imaevm_read_keyid(optarg);
if (keyid == 0) {
log_err("Error reading keyid.\n");
exit(1);
}
imaevm_params.keyid = keyid;
break;
case '?':
exit(1);
break;
@ -2834,17 +2721,6 @@ int main(int argc, char *argv[])
}
}
if (!imaevm_params.keypass)
imaevm_params.keypass = getenv("EVMCTL_KEY_PASSWORD");
if (imaevm_params.keyfile != NULL &&
imaevm_params.eng == NULL &&
!strncmp(imaevm_params.keyfile, "pkcs11:", 7)) {
imaevm_params.eng = setup_engine("pkcs11");
if (!imaevm_params.eng)
goto error;
}
if (argv[optind] == NULL)
usage();
else
@ -2865,10 +2741,9 @@ int main(int argc, char *argv[])
err = 125;
}
error:
if (imaevm_params.eng) {
ENGINE_finish(imaevm_params.eng);
ENGINE_free(imaevm_params.eng);
if (eng) {
ENGINE_finish(eng);
ENGINE_free(eng);
#if OPENSSL_API_COMPAT < 0x10100000L
ENGINE_cleanup();
#endif

View File

@ -84,10 +84,9 @@ 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")
# Normalize text hash name: if it contains underscore between
# digits replace it with a dash, other underscores are removed.
b=$(echo "$b" | sed "s/\([0-9]\)_\([0-9]\)/\1-\2/g;s/_//g")
printf '\t%-26s = "%s",\n' "[HASH_ALGO_$a]" "$b"
done
echo "};"

View File

@ -48,7 +48,6 @@
#include <errno.h>
#include <sys/types.h>
#include <openssl/rsa.h>
#include <openssl/engine.h>
#ifdef USE_FPRINTF
#define do_log(level, fmt, args...) \
@ -75,10 +74,6 @@
#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
@ -201,8 +196,6 @@ struct libimaevm_params {
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 {
@ -225,7 +218,6 @@ 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);

View File

@ -45,7 +45,6 @@
#include <sys/param.h>
#include <sys/stat.h>
#include <asm/byteorder.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <dirent.h>
#include <string.h>
@ -53,14 +52,11 @@
#include <assert.h>
#include <ctype.h>
#include <openssl/asn1.h>
#include <openssl/crypto.h>
#include <openssl/pem.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/err.h>
#include <openssl/engine.h>
#include "imaevm.h"
#include "hash_info.h"
@ -89,19 +85,19 @@ static const char *const pkey_hash_algo_kern[PKEY_HASH__LAST] = {
struct libimaevm_params imaevm_params = {
.verbose = LOG_INFO,
.x509 = 1,
.hash_algo = DEFAULT_HASH_ALGO,
.hash_algo = "sha1",
};
static void __attribute__ ((constructor)) libinit(void);
void imaevm_do_hexdump(FILE *fp, const void *ptr, int len, bool newline)
void imaevm_do_hexdump(FILE *fp, const void *ptr, int len, bool cr)
{
int i;
uint8_t *data = (uint8_t *) ptr;
for (i = 0; i < len; i++)
fprintf(fp, "%02x", data[i]);
if (newline)
if (cr)
fprintf(fp, "\n");
}
@ -160,7 +156,7 @@ static int add_file_hash(const char *file, EVP_MD_CTX *ctx)
for (size = stats.st_size; size; size -= len) {
len = MIN(size, bs);
if (fread(data, len, 1, fp) != 1) {
if (!fread(data, len, 1, fp)) {
if (ferror(fp)) {
log_err("fread() failed\n\n");
goto out;
@ -181,6 +177,67 @@ out:
return err;
}
static int add_dir_hash(const char *file, EVP_MD_CTX *ctx)
{
int err;
struct dirent *de;
DIR *dir;
unsigned long long ino, off;
unsigned int type;
int result = 0;
dir = opendir(file);
if (!dir) {
log_err("Failed to open: %s\n", file);
return -1;
}
while ((de = readdir(dir))) {
ino = de->d_ino;
off = de->d_off;
type = de->d_type;
log_debug("entry: %s, ino: %llu, type: %u, off: %llu, reclen: %hu\n",
de->d_name, ino, type, off, de->d_reclen);
err = EVP_DigestUpdate(ctx, de->d_name, strlen(de->d_name));
/*err |= EVP_DigestUpdate(ctx, &off, sizeof(off));*/
err |= EVP_DigestUpdate(ctx, &ino, sizeof(ino));
err |= EVP_DigestUpdate(ctx, &type, sizeof(type));
if (!err) {
log_err("EVP_DigestUpdate() failed\n");
output_openssl_errors();
result = 1;
break;
}
}
closedir(dir);
return result;
}
static int add_link_hash(const char *path, EVP_MD_CTX *ctx)
{
int err;
char buf[1024];
err = readlink(path, buf, sizeof(buf));
if (err <= 0)
return -1;
log_info("link: %s -> %.*s\n", path, err, buf);
return !EVP_DigestUpdate(ctx, buf, err);
}
static int add_dev_hash(struct stat *st, EVP_MD_CTX *ctx)
{
uint32_t dev = st->st_rdev;
unsigned major = (dev & 0xfff00) >> 8;
unsigned minor = (dev & 0xff) | ((dev >> 12) & 0xfff00);
log_info("device: %u:%u\n", major, minor);
return !EVP_DigestUpdate(ctx, &dev, sizeof(dev));
}
int ima_calc_hash(const char *file, uint8_t *hash)
{
const EVP_MD *md;
@ -221,8 +278,18 @@ int ima_calc_hash(const char *file, uint8_t *hash)
case S_IFREG:
err = add_file_hash(file, pctx);
break;
case S_IFDIR:
err = add_dir_hash(file, pctx);
break;
case S_IFLNK:
err = add_link_hash(file, pctx);
break;
case S_IFIFO: case S_IFSOCK:
case S_IFCHR: case S_IFBLK:
err = add_dev_hash(&st, pctx);
break;
default:
log_err("Unsupported file type (0x%x)", st.st_mode & S_IFMT);
log_errno("Unsupported file type");
err = -1;
goto err;
}
@ -396,6 +463,8 @@ void init_public_keys(const char *keyfiles)
keyfiles_free = tmp_keyfiles;
while ((keyfile = strsep(&tmp_keyfiles, ", \t")) != NULL) {
if (!keyfile)
break;
if ((*keyfile == '\0') || (*keyfile == ' ') ||
(*keyfile == '\t'))
continue;
@ -449,16 +518,6 @@ static int verify_hash_v2(const char *file, const unsigned char *hash, int size,
return -1;
}
#if defined(EVP_PKEY_SM2) && OPENSSL_VERSION_NUMBER < 0x30000000
/* If EC key are used, check whether it is SM2 key */
if (EVP_PKEY_id(pkey) == EVP_PKEY_EC) {
EC_KEY *ec = EVP_PKEY_get0_EC_KEY(pkey);
int curve = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec));
if (curve == NID_sm2)
EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2);
}
#endif
st = "EVP_PKEY_CTX_new";
if (!(ctx = EVP_PKEY_CTX_new(pkey, NULL)))
goto err;
@ -688,161 +747,25 @@ void calc_keyid_v2(uint32_t *keyid, char *str, EVP_PKEY *pkey)
X509_PUBKEY_free(pk);
}
/*
* Extract SKID from x509 in openssl portable way.
*/
static const unsigned char *x509_get_skid(X509 *x, int *len)
{
#if OPENSSL_VERSION_NUMBER < 0x10100000
ASN1_STRING *skid;
/*
* This will cache extensions.
* OpenSSL uses this method itself.
*/
if (X509_check_purpose(x, -1, -1) != 1)
return NULL;
skid = x->skid;
#else
const ASN1_OCTET_STRING *skid = X509_get0_subject_key_id(x);
#endif
if (len)
*len = ASN1_STRING_length(skid);
#if OPENSSL_VERSION_NUMBER < 0x10100000
return ASN1_STRING_data(x->skid);
#else
return ASN1_STRING_get0_data(skid);
#endif
}
/*
* read_keyid_from_cert() - Read keyid from SKID from x509 certificate file
* @keyid_be: Output 32-bit keyid in network order (BE);
* @certfile: Input filename.
* @try_der: true: try to read in DER from if there is no PEM,
* cert is considered mandatory and error will be issued
* if there is no cert;
* false: only try to read in PEM form, cert is considered
* optional.
* Return: 0 on success, -1 on error.
*/
static int read_keyid_from_cert(uint32_t *keyid_be, const char *certfile, int try_der)
{
X509 *x = NULL;
FILE *fp;
const unsigned char *skid;
int skid_len;
if (!(fp = fopen(certfile, "r"))) {
log_err("Cannot open %s: %s\n", certfile, strerror(errno));
return -1;
}
if (!PEM_read_X509(fp, &x, NULL, NULL)) {
if (ERR_GET_REASON(ERR_peek_last_error()) == PEM_R_NO_START_LINE) {
ERR_clear_error();
if (try_der) {
rewind(fp);
d2i_X509_fp(fp, &x);
} else {
/*
* Cert is optional and there is just no PEM
* header, then issue debug message and stop
* trying.
*/
log_debug("%s: x509 certificate not found\n",
certfile);
fclose(fp);
return -1;
}
}
}
fclose(fp);
if (!x) {
ERR_print_errors_fp(stderr);
log_err("read keyid: %s: Error reading x509 certificate\n",
certfile);
}
if (!(skid = x509_get_skid(x, &skid_len))) {
log_err("read keyid: %s: SKID not found\n", certfile);
goto err_free;
}
if (skid_len < sizeof(*keyid_be)) {
log_err("read keyid: %s: SKID too short (len %d)\n", certfile,
skid_len);
goto err_free;
}
memcpy(keyid_be, skid + skid_len - sizeof(*keyid_be), sizeof(*keyid_be));
log_info("keyid %04x (from %s)\n", ntohl(*keyid_be), certfile);
X509_free(x);
return 0;
err_free:
X509_free(x);
return -1;
}
/*
* imaevm_read_keyid() - Read 32-bit keyid from the cert file
* @certfile: File with certificate in PEM or DER form.
*
* Try to read keyid from Subject Key Identifier (SKID) of x509 certificate.
* Autodetect if cert is in PEM (tried first) or DER encoding.
*
* Return: 0 on error or 32-bit keyid in host order otherwise.
*/
uint32_t imaevm_read_keyid(const char *certfile)
{
uint32_t keyid_be = 0;
read_keyid_from_cert(&keyid_be, certfile, true);
/* On error keyid_be will not be set, returning 0. */
return ntohl(keyid_be);
}
static EVP_PKEY *read_priv_pkey(const char *keyfile, const char *keypass)
{
FILE *fp;
EVP_PKEY *pkey;
if (!strncmp(keyfile, "pkcs11:", 7)) {
if (!imaevm_params.keyid) {
log_err("When using a pkcs11 URI you must provide the keyid with an option\n");
return NULL;
}
if (keypass) {
if (!ENGINE_ctrl_cmd_string(imaevm_params.eng, "PIN", keypass, 0)) {
log_err("Failed to set the PIN for the private key\n");
goto err_engine;
}
}
pkey = ENGINE_load_private_key(imaevm_params.eng, keyfile, NULL, NULL);
if (!pkey) {
log_err("Failed to load private key %s\n", keyfile);
goto err_engine;
}
} else {
fp = fopen(keyfile, "r");
if (!fp) {
log_err("Failed to open keyfile: %s\n", keyfile);
return NULL;
}
pkey = PEM_read_PrivateKey(fp, NULL, NULL, (void *)keypass);
if (!pkey) {
log_err("Failed to PEM_read_PrivateKey key file: %s\n",
keyfile);
output_openssl_errors();
}
fclose(fp);
fp = fopen(keyfile, "r");
if (!fp) {
log_err("Failed to open keyfile: %s\n", keyfile);
return NULL;
}
pkey = PEM_read_PrivateKey(fp, NULL, NULL, (void *)keypass);
if (!pkey) {
log_err("Failed to PEM_read_PrivateKey key file: %s\n",
keyfile);
output_openssl_errors();
}
fclose(fp);
return pkey;
err_engine:
output_openssl_errors();
return NULL;
}
static RSA *read_priv_key(const char *keyfile, const char *keypass)
@ -993,7 +916,7 @@ static int sign_hash_v2(const char *algo, const unsigned char *hash,
return -1;
}
log_info("hash(%s): ", algo);
log_info("hash(%s): ", imaevm_params.hash_algo);
log_dump(hash, size);
pkey = read_priv_pkey(keyfile, imaevm_params.keypass);
@ -1009,24 +932,7 @@ static int sign_hash_v2(const char *algo, const unsigned char *hash,
return -1;
}
#if defined(EVP_PKEY_SM2) && OPENSSL_VERSION_NUMBER < 0x30000000
/* If EC key are used, check whether it is SM2 key */
if (EVP_PKEY_id(pkey) == EVP_PKEY_EC) {
EC_KEY *ec = EVP_PKEY_get0_EC_KEY(pkey);
int curve = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec));
if (curve == NID_sm2)
EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2);
}
#endif
if (imaevm_params.keyid)
keyid = htonl(imaevm_params.keyid);
else {
int keyid_read_failed = read_keyid_from_cert(&keyid, keyfile, false);
if (keyid_read_failed)
calc_keyid_v2(&keyid, name, pkey);
}
calc_keyid_v2(&keyid, name, pkey);
hdr->keyid = keyid;
st = "EVP_PKEY_CTX_new";
@ -1036,7 +942,7 @@ static int sign_hash_v2(const char *algo, const unsigned char *hash,
if (!EVP_PKEY_sign_init(ctx))
goto err;
st = "EVP_get_digestbyname";
if (!(md = EVP_get_digestbyname(algo)))
if (!(md = EVP_get_digestbyname(imaevm_params.hash_algo)))
goto err;
st = "EVP_PKEY_CTX_set_signature_md";
if (!EVP_PKEY_CTX_set_signature_md(ctx, md))

View File

@ -1,3 +1,3 @@
int tpm2_pcr_supported(void);
int tpm2_pcr_read(const char *algo_name, uint32_t pcr_handle, uint8_t *hwpcr,
int tpm2_pcr_read(const char *algo_name, int idx, 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

@ -106,7 +106,7 @@ static TPM2_ALG_ID algo_to_tss2(const char *algo_name)
return TPM2_ALG_ERROR;
}
int tpm2_pcr_read(const char *algo_name, uint32_t pcr_handle, uint8_t *hwpcr,
int tpm2_pcr_read(const char *algo_name, int idx, uint8_t *hwpcr,
int len, char **errmsg)
{
TSS2_ABI_VERSION abi_version = {
@ -140,8 +140,7 @@ int tpm2_pcr_read(const char *algo_name, uint32_t pcr_handle, uint8_t *hwpcr,
}
};
pcr_select_in.pcrSelections[0].pcrSelect[pcr_handle / 8] =
(1 << (pcr_handle % 8));
pcr_select_in.pcrSelections[0].pcrSelect[idx / 8] = (1 << (idx % 8));
ret = Esys_Initialize(&ctx, NULL, &abi_version);
if (ret != TPM2_RC_SUCCESS) {

View File

@ -60,15 +60,15 @@ int tpm2_pcr_supported(void)
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);
log_debug("Couldn't find '%s' in $PATH", CMD);
return 0;
}
log_debug("Found '%s' in $PATH\n", CMD);
log_debug("Found '%s' in $PATH", CMD);
return 1;
}
int tpm2_pcr_read(const char *algo_name, uint32_t pcr_handle, uint8_t *hwpcr,
int tpm2_pcr_read(const char *algo_name, int idx, uint8_t *hwpcr,
int len, char **errmsg)
{
FILE *fp;
@ -76,8 +76,8 @@ int tpm2_pcr_read(const char *algo_name, uint32_t pcr_handle, uint8_t *hwpcr,
char cmd[PATH_MAX + 50];
int ret;
sprintf(cmd, "%s -halg %s -ha %u -ns 2> /dev/null",
path, algo_name, pcr_handle);
sprintf(cmd, "%s -halg %s -ha %d -ns 2> /dev/null",
path, algo_name, idx);
fp = popen(cmd, "r");
if (!fp) {
ret = asprintf(errmsg, "popen failed: %s", strerror(errno));

View File

@ -77,8 +77,7 @@ int get_cmd_path(const char *prog_name, char *buf, size_t buf_len)
if (buf_len - size > ret && file_exist(buf))
return 0;
if (end != NULL)
start = end + 1;
start = end + 1;
} while (end != NULL);

View File

@ -26,49 +26,44 @@ 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
if [ "$(id -u)" = 0 ] && [ -c "/dev/tpm0" ]; then
ASCII_RUNTIME_MEASUREMENTS="/sys/kernel/security/ima/ascii_runtime_measurements"
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
fi
# Only stop this test's software TPM. Preferred method: "tsstpmcmd -stop"
cleanup() {
if [ -n "${SWTPM_PID}" ]; then
kill -SIGTERM "${SWTPM_PID}"
elif [ -n "${TPMSERVER_PID}" ]; then
"${TSSDIR}/tsstpmcmd" -stop
if [ ! -z "${SWTPM_PPID}" ]; then
if [ -f "${TSSDIR}/tsstpmcmd" ]; then
"${TSSDIR}/tsstpmcmd" -stop
else
pkill -P "${SWTPM_PPID}"
fi
fi
}
# Try to start a software TPM if needed.
swtpm_start() {
local tpm_server swtpm
local 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}"
swtpm="$(which tpm_server)"
if [ -z "${swtpm}" ]; then
echo "${CYAN}SKIP: Softare TPM (tpm_server) 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
pgrep tpm_server
if [ $? -eq 0 ]; then
echo "INFO: Software TPM (tpm_server) already running"
return 114
else
echo "INFO: Starting software TPM: ${swtpm}"
${swtpm} > /dev/null 2>&1 &
SWTPM_PPID=$!
fi
return 0
}
@ -80,20 +75,8 @@ swtpm_init() {
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}/tssstartup"
# $(${TSSDIR}/tsseventextend -tpm -if "${BINARY_BIOS_MEASUREMENTS}" -v) 2>&1 > /dev/null
"${TSSDIR}/tsseventextend" -tpm -if "${BINARY_BIOS_MEASUREMENTS}" -v > /dev/null 2>&1
}
@ -118,7 +101,7 @@ display_pcrs() {
done
}
# The first entry in the IMA measurement list is the "boot_aggregate".
# The first entry in the IMA measuremnet 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.
@ -150,24 +133,6 @@ check() {
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

View File

@ -248,12 +248,8 @@ _enable_gost_engine() {
}
# 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
# with proper exit code (same as ours).
_report_exit() {
if [ $testsfail -gt 0 ]; then
echo "================================="
echo " Run with FAILEARLY=1 $0 $*"
@ -276,40 +272,3 @@ _report_exit_and_cleanup() {
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

@ -20,14 +20,13 @@ PATH=../src:$PATH
type openssl
log() {
echo >&2 - "$*"
echo - "$*"
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
elif [ "$1" = force ] || [ ! -e test-ca.conf ]; then
cat > test-ca.conf <<- EOF
[ req ]
distinguished_name = req_distinguished_name
@ -44,64 +43,26 @@ cat > test-ca.conf <<- EOF
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
for m in 1024 2048; do
if [ "$1" = clean ] || [ "$1" = force ]; 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 \
log openssl req -verbose -new -nodes -utf8 -sha1 -days 10000 -batch -x509 \
-config test-ca.conf \
-newkey rsa:$bits \
-newkey rsa:$m \
-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
@ -131,31 +92,6 @@ for m in \
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'.

View File

@ -20,7 +20,7 @@ PATH=../src:$PATH
source ./functions.sh
_require evmctl openssl getfattr
trap _report_exit_and_cleanup EXIT
trap _report_exit EXIT
set -f # disable globbing
check() {
@ -70,7 +70,8 @@ expect_pass check sha256 0x0404 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649
expect_pass check sha384 0x0405 38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b
expect_pass check sha512 0x0406 cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e
expect_pass check rmd160 0x0403 9c1185a5c5e9fc54612808977ee8f548b2258d31
expect_pass check sm3 0x0411 1ab21d8355cfa17f8e61194831e81a8f22bec8c728fefb747ed035eb5082aa2b
expect_fail check sm3 0x01
expect_fail check sm3-256 0x01
_enable_gost_engine
expect_pass check md_gost12_256 0x0412 3f539a213e97c802cc229d474c6aa32a825a360b2a933a949fd925208d9ce1bb
expect_pass check streebog256 0x0412 3f539a213e97c802cc229d474c6aa32a825a360b2a933a949fd925208d9ce1bb

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

View File

@ -18,18 +18,10 @@
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
_require evmctl openssl xxd getfattr
./gen-keys.sh >/dev/null 2>&1
trap _report_exit_and_cleanup EXIT
WORKDIR=$(mktemp -d)
trap _report_exit EXIT
set -f # disable globbing
# Determine keyid from a cert
@ -44,7 +36,6 @@ _keyid_from_cert() {
id=$($cmd 2>/dev/null \
| openssl asn1parse \
| grep BIT.STRING \
| tail -n1 \
| cut -d: -f1)
if [ -z "$id" ]; then
echo - "$cmd" >&2
@ -102,8 +93,7 @@ _test_sigfile() {
return "$FAIL"
fi
# Leave '$file_sig' for ima_verify --sigfile test.
rm "$file_sig2"
rm "$file_sig" "$file_sig2"
}
# Run single sign command
@ -133,16 +123,11 @@ check_sign() {
# OPTS (additional options for evmctl),
# FILE (working file to sign).
local "$@"
local key verifykey
local KEY=${KEY%.*}.key
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
# Normalize key filename
KEY=test-${KEY#test-}
# Append suffix to files for negative tests, because we may
# leave only good files for verify tests.
@ -158,33 +143,33 @@ check_sign() {
if _test_expected_to_pass; then
# Can openssl work with this digest?
cmd="openssl dgst $OPENSSL_ENGINE $OPENSSL_KEYFORM -$ALG $FILE"
cmd="openssl dgst $OPENSSL_ENGINE -$ALG $FILE"
echo - "$cmd"
if ! $cmd >/dev/null; then
echo "${CYAN}$ALG ($key) test is skipped (openssl is unable to digest)$NORM"
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"
if [ ! -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"
cmd="openssl dgst $OPENSSL_ENGINE -$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"
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")
keyid=$(_keyid_from_cert "$KEY")
if [ $? -ne 0 ]; then
color_red
echo "Unable to determine keyid for $key"
echo "Unable to determine keyid for $KEY"
color_restore
return "$HARDFAIL"
fi
@ -193,7 +178,7 @@ check_sign() {
fi
# Perform signing by evmctl
_evmctl_sign "$TYPE" "$key" "$ALG" "$FILE" "$OPTS" || return
_evmctl_sign "$TYPE" "$KEY" "$ALG" "$FILE" "$OPTS" || return
# First simple pattern match the signature.
ADD_TEXT_FOR=$ALG \
@ -205,21 +190,11 @@ check_sign() {
# 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} \
cmd="openssl dgst $OPENSSL_ENGINE -$ALG -verify ${KEY%.*}.pub \
-signature $FILE.sig2 $FILE"
echo - "$cmd"
if ! $cmd; then
@ -279,12 +254,9 @@ sign_verify() {
# 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
@ -345,14 +317,9 @@ try_different_sigs() {
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 --portable
expect_pass check_sign OPTS="$OPTS --portable" PREFIX=0x05
# Cannot be verified for now, until that support is added to evmctl
# Test -i (immutable)
expect_pass check_sign OPTS="$OPTS -i" PREFIX=0x0303
@ -381,9 +348,6 @@ sign_verify rsa1024 sha256 0x0301 --rsa
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
@ -391,27 +355,6 @@ 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
@ -425,15 +368,3 @@ expect_fail \
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 $?