mirror of
https://git.code.sf.net/p/linux-ima/ima-evm-utils
synced 2025-04-28 14:43:37 +02:00
Merge branch 'pkcs11-support-v4' into next
From the cover letter: Add support for signing with pkcs11 URIs so that pkcs11-enabled devices can also be used for file signing. Extend the existing sign_verify.test with tests for the new pkcs11 URI support. Use SoftHSM, when available, as a pkcs11 device for testing.
This commit is contained in:
commit
5356b0487a
5
README
5
README
@ -48,6 +48,7 @@ OPTIONS
|
||||
--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
|
||||
@ -70,6 +71,10 @@ 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
|
||||
------------
|
||||
|
@ -12,12 +12,15 @@ apt-get install -y \
|
||||
asciidoc \
|
||||
attr \
|
||||
docbook-style-xsl \
|
||||
gnutls-utils \
|
||||
libattr-devel \
|
||||
libkeyutils-devel \
|
||||
libp11 \
|
||||
libssl-devel \
|
||||
openssl \
|
||||
openssl-gost-engine \
|
||||
rpm-build \
|
||||
softhsm \
|
||||
wget \
|
||||
xsltproc \
|
||||
xxd \
|
||||
|
@ -48,7 +48,8 @@ $apt \
|
||||
procps \
|
||||
sudo \
|
||||
wget \
|
||||
xsltproc \
|
||||
xsltproc
|
||||
|
||||
$apt xxd || $apt vim-common
|
||||
$apt libengine-gost-openssl1.1$ARCH || true
|
||||
$apt softhsm gnutls-bin libengine-pkcs11-openssl1.1$ARCH || true
|
||||
|
@ -25,6 +25,7 @@ yum -y install \
|
||||
automake \
|
||||
diffutils \
|
||||
docbook-xsl \
|
||||
gnutls-utils \
|
||||
gzip \
|
||||
keyutils-libs-devel \
|
||||
libattr-devel \
|
||||
@ -33,6 +34,7 @@ yum -y install \
|
||||
make \
|
||||
openssl \
|
||||
openssl-devel \
|
||||
openssl-pkcs11 \
|
||||
pkg-config \
|
||||
procps \
|
||||
sudo \
|
||||
@ -42,3 +44,9 @@ yum -y install \
|
||||
|
||||
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
|
@ -42,6 +42,9 @@ zypper --non-interactive install --force-resolution --no-recommends \
|
||||
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
|
||||
|
54
src/evmctl.c
54
src/evmctl.c
@ -2507,6 +2507,7 @@ static void usage(void)
|
||||
" --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"
|
||||
@ -2534,6 +2535,9 @@ static void usage(void)
|
||||
" --ignore-violations ignore ToMToU measurement violations\n"
|
||||
" -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");
|
||||
}
|
||||
|
||||
@ -2637,10 +2641,26 @@ static char *get_password(void)
|
||||
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;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int err = 0, c, lind;
|
||||
ENGINE *eng = NULL;
|
||||
unsigned long keyid;
|
||||
char *eptr;
|
||||
|
||||
@ -2761,17 +2781,9 @@ int main(int argc, char *argv[])
|
||||
verify_list_sig = 1;
|
||||
break;
|
||||
case 139: /* --engine e */
|
||||
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);
|
||||
imaevm_params.eng = setup_engine(optarg);
|
||||
if (!imaevm_params.eng)
|
||||
goto error;
|
||||
break;
|
||||
case 140: /* --xattr-user */
|
||||
xattr_ima = "user.ima";
|
||||
@ -2822,6 +2834,17 @@ 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
|
||||
@ -2842,9 +2865,10 @@ int main(int argc, char *argv[])
|
||||
err = 125;
|
||||
}
|
||||
|
||||
if (eng) {
|
||||
ENGINE_finish(eng);
|
||||
ENGINE_free(eng);
|
||||
error:
|
||||
if (imaevm_params.eng) {
|
||||
ENGINE_finish(imaevm_params.eng);
|
||||
ENGINE_free(imaevm_params.eng);
|
||||
#if OPENSSL_API_COMPAT < 0x10100000L
|
||||
ENGINE_cleanup();
|
||||
#endif
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/engine.h>
|
||||
|
||||
#ifdef USE_FPRINTF
|
||||
#define do_log(level, fmt, args...) \
|
||||
@ -197,6 +198,7 @@ struct libimaevm_params {
|
||||
const char *keyfile;
|
||||
const char *keypass;
|
||||
uint32_t keyid; /* keyid overriding value, unless 0. (Host order.) */
|
||||
ENGINE *eng;
|
||||
};
|
||||
|
||||
struct RSA_ASN1_template {
|
||||
|
@ -60,6 +60,7 @@
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/engine.h>
|
||||
|
||||
#include "imaevm.h"
|
||||
#include "hash_info.h"
|
||||
@ -804,20 +805,44 @@ static EVP_PKEY *read_priv_pkey(const char *keyfile, const char *keypass)
|
||||
FILE *fp;
|
||||
EVP_PKEY *pkey;
|
||||
|
||||
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();
|
||||
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);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
return pkey;
|
||||
|
||||
err_engine:
|
||||
output_openssl_errors();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static RSA *read_priv_key(const char *keyfile, const char *keypass)
|
||||
|
@ -248,8 +248,12 @@ _enable_gost_engine() {
|
||||
}
|
||||
|
||||
# Show test stats and exit into automake test system
|
||||
# with proper exit code (same as ours).
|
||||
_report_exit() {
|
||||
# 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 $*"
|
||||
@ -272,3 +276,40 @@ _report_exit() {
|
||||
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
|
||||
}
|
@ -20,7 +20,7 @@ PATH=../src:$PATH
|
||||
source ./functions.sh
|
||||
_require evmctl openssl getfattr
|
||||
|
||||
trap _report_exit EXIT
|
||||
trap _report_exit_and_cleanup EXIT
|
||||
set -f # disable globbing
|
||||
|
||||
check() {
|
||||
|
@ -28,7 +28,8 @@ fi
|
||||
|
||||
./gen-keys.sh >/dev/null 2>&1
|
||||
|
||||
trap _report_exit EXIT
|
||||
trap _report_exit_and_cleanup EXIT
|
||||
WORKDIR=$(mktemp -d)
|
||||
set -f # disable globbing
|
||||
|
||||
# Determine keyid from a cert
|
||||
@ -132,11 +133,16 @@ check_sign() {
|
||||
# OPTS (additional options for evmctl),
|
||||
# FILE (working file to sign).
|
||||
local "$@"
|
||||
local KEY=${KEY%.*}.key
|
||||
local key verifykey
|
||||
local FILE=${FILE:-$ALG.txt}
|
||||
|
||||
# Normalize key filename
|
||||
KEY=test-${KEY#test-}
|
||||
# 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.
|
||||
@ -152,33 +158,33 @@ check_sign() {
|
||||
|
||||
if _test_expected_to_pass; then
|
||||
# Can openssl work with this digest?
|
||||
cmd="openssl dgst $OPENSSL_ENGINE -$ALG $FILE"
|
||||
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"
|
||||
echo "${CYAN}$ALG ($key) test is skipped (openssl is unable to digest)$NORM"
|
||||
return "$SKIP"
|
||||
fi
|
||||
|
||||
if [ ! -e "$KEY" ]; then
|
||||
echo "${CYAN}$ALG ($KEY) test is skipped (key file not found)$NORM"
|
||||
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 -$ALG -sign $KEY -hex $FILE"
|
||||
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"
|
||||
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
|
||||
@ -187,7 +193,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 \
|
||||
@ -207,7 +213,13 @@ check_sign() {
|
||||
_extract_xattr "$FILE" "$(_xattr "$TYPE")" "$FILE.sig2" "$PREFIX"
|
||||
|
||||
# Verify extracted signature with openssl
|
||||
cmd="openssl dgst $OPENSSL_ENGINE -$ALG -verify ${KEY%.*}.pub \
|
||||
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
|
||||
@ -413,3 +425,15 @@ 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}"
|
||||
|
293
tests/softhsm_setup
Executable file
293
tests/softhsm_setup
Executable file
@ -0,0 +1,293 @@
|
||||
#!/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 $?
|
Loading…
x
Reference in New Issue
Block a user