mirror of
https://github.com/stefanberger/swtpm.git
synced 2025-08-22 19:04:35 +00:00

Apply the password for the signing key and parent key when creating a
platform certificate. The bug was introduced in commit 961bb827
"samples: Use new pwd format option for secretly passing passwords"
Extend a test case to ensure that the passwords are always used.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
642 lines
16 KiB
Bash
Executable File
642 lines
16 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
#
|
|
# sample/swtpm-localca
|
|
#
|
|
# Authors: Stefan Berger <stefanb@us.ibm.com>
|
|
#
|
|
# (c) Copyright IBM Corporation 2014, 2015.
|
|
#
|
|
# All rights reserved.
|
|
#
|
|
# Redistribution and use in source and binary forms, with or without
|
|
# modification, are permitted provided that the following conditions are
|
|
# met:
|
|
#
|
|
# Redistributions of source code must retain the above copyright notice,
|
|
# this list of conditions and the following disclaimer.
|
|
#
|
|
# Redistributions in binary form must reproduce the above copyright notice,
|
|
# this list of conditions and the following disclaimer in the documentation
|
|
# and/or other materials provided with the distribution.
|
|
#
|
|
# Neither the names of the IBM Corporation nor the names of its contributors
|
|
# may be used to endorse or promote products derived from this software
|
|
# without specific prior written permission.
|
|
#
|
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
|
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
|
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
|
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
#
|
|
|
|
# some flags
|
|
SETUP_TPM2_F=1
|
|
# for TPM 2 EK
|
|
ALLOW_SIGNING_F=2
|
|
DECRYPTION_F=4
|
|
|
|
LOCALCA_OPTIONS="swtpm-localca.options"
|
|
if [ -n "$XDG_CONFIG_HOME" ] && [ -r "$XDG_CONFIG_HOME/$LOCALCA_OPTIONS" ]; then
|
|
LOCALCA_OPTIONS="$XDG_CONFIG_HOME/$LOCALCA_OPTIONS"
|
|
elif [ -n "$HOME" ] && [ -r "$HOME/.config/$LOCALCA_OPTIONS" ]; then
|
|
LOCALCA_OPTIONS="$HOME/.config/$LOCALCA_OPTIONS"
|
|
else
|
|
LOCALCA_OPTIONS="@SYSCONFDIR@/$LOCALCA_OPTIONS"
|
|
fi
|
|
|
|
LOCALCA_CONFIG="swtpm-localca.conf"
|
|
if [ -n "$XDG_CONFIG_HOME" ] && [ -r "$XDG_CONFIG_HOME/$LOCALCA_CONFIG" ]; then
|
|
LOCALCA_CONFIG="$XDG_CONFIG_HOME/$LOCALCA_CONFIG"
|
|
elif [ -n "$HOME" ] && [ -r "$HOME/.config/$LOCALCA_CONFIG" ]; then
|
|
LOCALCA_CONFIG="$HOME/.config/$LOCALCA_CONFIG"
|
|
else
|
|
LOCALCA_CONFIG="@SYSCONFDIR@/$LOCALCA_CONFIG"
|
|
fi
|
|
|
|
# Default logging goes to stderr
|
|
LOGFILE=""
|
|
|
|
UNAME_S=$(uname -s)
|
|
|
|
logit()
|
|
{
|
|
if [ -z "$LOGFILE" ]; then
|
|
echo "$@" >&1
|
|
else
|
|
echo "$@" >> "$LOGFILE"
|
|
fi
|
|
}
|
|
|
|
logerr()
|
|
{
|
|
if [ -z "$LOGFILE" ]; then
|
|
echo "Error: $*" >&2
|
|
else
|
|
echo "Error: $*" >> "$LOGFILE"
|
|
fi
|
|
}
|
|
|
|
flock_fd()
|
|
{
|
|
local fd=$1
|
|
|
|
case "${UNAME_S}" in
|
|
Darwin)
|
|
flock "$fd";;
|
|
*)
|
|
flock -x "$fd";;
|
|
esac
|
|
}
|
|
|
|
# Escape a string for call with eval. Replace any occurrences of '$(' with
|
|
# '(' to avoid subshells and escape '][;|&()'`'<>!\#*' since those are shell
|
|
# special characters. Unescape any already-escaped characters and then
|
|
# escape again. Do NOT escape '${' since we use it for variable substitution
|
|
# but escape all other $-sequences. Squeeze all sequences of multiple '\'.
|
|
escape_eval() {
|
|
echo "$1" | \
|
|
sed -e 's/\$(/(/g' \
|
|
-e 's/\\\([][;|&()`<>!#*]\)/\1/g' -e 's/\([][;|&()`<>!#*]\)/\\\1/g' \
|
|
-e "s/\\\'/'/g" -e "s/'/\\\'/g" \
|
|
-e 's/$\([^{]\)/\\$\\\1/g' | \
|
|
tr -s '\\'
|
|
}
|
|
|
|
# Get a configuration value from a configuration file
|
|
# @param1: The file with the options
|
|
# @param2: The name of the option
|
|
# @param3: The default value
|
|
get_config_value() {
|
|
local configfile="$1"
|
|
local configname="$(echo "$2" | sed 's/-/\\-/g')"
|
|
local defaultvalue="$3"
|
|
local tmp
|
|
|
|
if [ ! -r "$configfile" ]; then
|
|
logerr "Cannot read config file $configfile"
|
|
return 1
|
|
fi
|
|
|
|
tmp=$(sed -n "s/^${configname}[[:space:]]*=[[:space:]]*//p" \
|
|
"$configfile")
|
|
tmp=${tmp%% }
|
|
if [ -z "$tmp" ]; then
|
|
if [ -n "$defaultvalue" ]; then
|
|
echo "$defaultvalue"
|
|
else
|
|
return 1
|
|
fi
|
|
else
|
|
# only use eval if there are any ${ that are not \${
|
|
# or the command starts with '${'
|
|
if [ "$tmp" != "${tmp%[^\\]\${*}" ] || \
|
|
[ "${tmp:0:2}" = '${' ]; then
|
|
tmp="$(escape_eval "$tmp")"
|
|
echo "$(eval echo "$tmp")"
|
|
else
|
|
# unescape any previously required '\;'
|
|
echo "$tmp" | sed -e 's/\\;/;/g'
|
|
fi
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
make_dir() {
|
|
local dir="$1"
|
|
|
|
if [ ! -d "$dir" ]; then
|
|
logit "Creating swtpm-local dir '${dir}'."
|
|
mkdir -p "$dir"
|
|
if [ $? -ne 0 ]; then
|
|
logerr "Could not create directory '${dir}."
|
|
exit 1
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# Get the next serial number for the certificate
|
|
#
|
|
# If an error occurs nothing is echo'ed and the return code 1 is returned,
|
|
# otherwise the next serial number is echo'ed with a return code of 0.
|
|
get_next_cert_serial() {
|
|
local serial
|
|
|
|
touch "${LOCK}"
|
|
(
|
|
# Avoid concurrent creation of next serial
|
|
flock_fd 100
|
|
if [ $? -ne 0 ]; then
|
|
logerr "Could not get lock ${LOCK}"
|
|
return 1
|
|
fi
|
|
if [ ! -r "${CERTSERIAL}" ]; then
|
|
echo -n "0" > "${CERTSERIAL}"
|
|
fi
|
|
serial=$(cat "${CERTSERIAL}")
|
|
if ! [[ "$serial" =~ ^[0-9]+$ ]]; then
|
|
serial=1
|
|
else
|
|
serial=$((serial+1))
|
|
fi
|
|
echo -n $serial > "${CERTSERIAL}"
|
|
if [ $? -ne 0 ]; then
|
|
logerr "Could not write cert serial number file"
|
|
return 1
|
|
fi
|
|
echo $serial
|
|
) 100>"${LOCK}"
|
|
|
|
return 0
|
|
}
|
|
|
|
create_cert() {
|
|
local flags="$1"
|
|
local typ="$2"
|
|
local dir="$3"
|
|
local ek="$4"
|
|
local vmid="$5"
|
|
local tpm_spec_params="$6"
|
|
local tpm_attr_params="$7"
|
|
|
|
local options="" rc=0 keyparms="" serial tmp subj
|
|
|
|
serial=$(get_next_cert_serial)
|
|
if [ -z "$serial" ]; then
|
|
return 1
|
|
fi
|
|
|
|
if [ -r "${LOCALCA_OPTIONS}" ]; then
|
|
options=$(cat "${LOCALCA_OPTIONS}")
|
|
fi
|
|
|
|
if [ -n "$vmid" ]; then
|
|
subj="CN=$vmid"
|
|
else
|
|
subj="CN=unknown"
|
|
fi
|
|
|
|
if [ $((flags & SETUP_TPM2_F)) -ne 0 ]; then
|
|
options="$options --tpm2"
|
|
else
|
|
# TPM 1.2 cert needs a header
|
|
options="$options --add-header"
|
|
fi
|
|
|
|
if [ "$typ" == "ek" ]; then
|
|
if [ $((flags & ALLOW_SIGNING_F)) -ne 0 ]; then
|
|
options="$options --allow-signing"
|
|
fi
|
|
if [ $((flags & DECRYPTION_F)) -ne 0 ]; then
|
|
options="$options --decryption"
|
|
fi
|
|
fi
|
|
|
|
# if ek contains x=..,y=... it's an ECC key
|
|
if [[ "$ek" =~ x=.*,y=.* ]]; then
|
|
keyparms="--ecc-x $(echo "$ek" | \
|
|
sed -n 's/x=\([[:xdigit:]]*\),.*/\1/p') "
|
|
keyparms+="--ecc-y $(echo "$ek" | \
|
|
sed -n 's/.*y=\([[:xdigit:]]*\).*/\1/p')"
|
|
else
|
|
keyparms="--modulus ${ek}"
|
|
fi
|
|
|
|
case "$typ" in
|
|
ek)
|
|
if [ -z "$(type -p swtpm_cert)" ]; then
|
|
logerr "Missing swtpm_cert tool"
|
|
rc=1
|
|
else
|
|
swtpm_cert \
|
|
--subject "$subj" \
|
|
$options \
|
|
${SIGNKEY_PASSWORD:+--signkey-pwd file:<(echo -en "$SIGNKEY_PASSWORD")} \
|
|
${PARENTKEY_PASSWORD:+--parentkey-pwd file:<(echo -en "$PARENTKEY_PASSWORD")} \
|
|
$tpm_spec_params \
|
|
$tpm_attr_params \
|
|
--signkey "${SIGNKEY}" \
|
|
--issuercert "${ISSUERCERT}" \
|
|
--out-cert "${dir}/ek.cert" \
|
|
$keyparms \
|
|
--days 3650 \
|
|
--serial "$serial"
|
|
if [ $? -eq 0 ]; then
|
|
logit "Successfully created EK certificate locally."
|
|
else
|
|
logerr "Could not create EK certificate locally."
|
|
rc=1
|
|
fi
|
|
fi
|
|
;;
|
|
platform)
|
|
if [ -z "$(type -p swtpm_cert)" ]; then
|
|
logerr "Missing swtpm_cert tool"
|
|
rc=1
|
|
else
|
|
swtpm_cert \
|
|
--subject "$subj" \
|
|
$options \
|
|
${SIGNKEY_PASSWORD:+--signkey-pwd file:<(echo -en "$SIGNKEY_PASSWORD")} \
|
|
${PARENTKEY_PASSWORD:+--parentkey-pwd file:<(echo -en "$PARENTKEY_PASSWORD")} \
|
|
$tpm_attr_params \
|
|
--type platform \
|
|
--signkey "${SIGNKEY}" \
|
|
--issuercert "${ISSUERCERT}" \
|
|
--out-cert "${dir}/platform.cert" \
|
|
$keyparms \
|
|
--days 3650 \
|
|
--serial "$serial"
|
|
if [ $? -eq 0 ]; then
|
|
logit "Successfully created platform certificate locally."
|
|
else
|
|
logerr "Could not create platform certificate locally."
|
|
rc=1
|
|
fi
|
|
fi
|
|
;;
|
|
esac
|
|
|
|
return $rc
|
|
}
|
|
|
|
# Create the local CA's certificate if it doesn't already exist.
|
|
# The local CA will be an intermediate CA with a root CA we create
|
|
# here as well so that we get an Authority Key Id in our EK cert.
|
|
#
|
|
create_localca_cert() {
|
|
touch "${LOCK}"
|
|
(
|
|
# Avoid concurrent creation of keys and certs
|
|
flock_fd 100
|
|
if [ $? -ne 0 ]; then
|
|
logerr "Could not get lock ${LOCK}"
|
|
return 1
|
|
fi
|
|
if [ ! -d "${STATEDIR}" ]; then
|
|
# RPM installation must have created this already ...
|
|
# so user tss can use it (user tss cannot create it)
|
|
mkdir -p "${STATEDIR}"
|
|
fi
|
|
if [ ! -r "${SIGNKEY}" ]; then
|
|
local dir=$(dirname "${SIGNKEY}")
|
|
local cakey=${dir}/swtpm-localca-rootca-privkey.pem
|
|
local cacert=${dir}/swtpm-localca-rootca-cert.pem
|
|
local msg password
|
|
|
|
# create a CA first
|
|
msg=$("${CERTTOOL}" \
|
|
--generate-privkey \
|
|
${SWTPM_ROOTCA_PASSWORD:+--password "${SWTPM_ROOTCA_PASSWORD}"} \
|
|
--outfile "${cakey}" \
|
|
2>&1)
|
|
[ $? -ne 0 ] && {
|
|
logerr "Could not create root-CA key ${cakey}."
|
|
logerr "${msg}"
|
|
return 1
|
|
}
|
|
chmod 640 "${cakey}"
|
|
|
|
local tmp=$(mktemp)
|
|
echo "cn=swtpm-localca-rootca" > "${tmp}"
|
|
echo "ca" >> "${tmp}"
|
|
echo "cert_signing_key" >> "${tmp}"
|
|
echo "expiration_days = 3650" >> "${tmp}"
|
|
|
|
msg=$(GNUTLS_PIN="${SWTPM_ROOTCA_PASSWORD}" "${CERTTOOL}" \
|
|
--generate-self-signed \
|
|
--template "${tmp}" \
|
|
--outfile "${cacert}" \
|
|
--load-privkey "${cakey}" \
|
|
2>&1)
|
|
[ $? -ne 0 ] && {
|
|
logerr "Could not create root CA."
|
|
logerr "${msg}"
|
|
rm -f "${cakey}"
|
|
return 1
|
|
}
|
|
|
|
# now our signing CA
|
|
msg=$("${CERTTOOL}" \
|
|
--generate-privkey \
|
|
${SIGNKEY_PASSWORD:+--password "${SIGNKEY_PASSWORD}"} \
|
|
--outfile "${SIGNKEY}" \
|
|
2>&1)
|
|
[ $? -ne 0 ] && {
|
|
rm -f "${cakey}" "${cacert}"
|
|
logerr "Could not create local-CA key ${SIGNKEY}."
|
|
logerr "${msg}"
|
|
return 1
|
|
}
|
|
chmod 640 "${SIGNKEY}"
|
|
|
|
echo "cn=swtpm-localca" > "${tmp}"
|
|
echo "ca" >> "${tmp}"
|
|
echo "cert_signing_key" >> "${tmp}"
|
|
echo "expiration_days = 3650" >> "${tmp}"
|
|
|
|
if [ -n "${SIGNKEY_PASSWORD}" ] && [ -n "${SWTPM_ROOTCA_PASSWORD}" ]; then
|
|
GNUTLS_PIN="${SIGNKEY_PASSWORD}"
|
|
password="${SWTPM_ROOTCA_PASSWORD}"
|
|
elif [ -n "${SIGNKEY_PASSWORD}" ]; then
|
|
GNUTLS_PIN="${SIGNKEY_PASSWORD}"
|
|
else
|
|
GNUTLS_PIN="${SWTPM_ROOTCA_PASSWORD}"
|
|
fi
|
|
|
|
msg=$(GNUTLS_PIN="${GNUTLS_PIN}" "${CERTTOOL}" \
|
|
--generate-certificate \
|
|
--template "${tmp}" \
|
|
--outfile "${ISSUERCERT}" \
|
|
--load-privkey "${SIGNKEY}" \
|
|
${password:+--password "${password}"} \
|
|
--load-ca-privkey "${cakey}" \
|
|
--load-ca-certificate "${cacert}" \
|
|
2>&1)
|
|
[ $? -ne 0 ] && {
|
|
rm -f "${cakey}" "${cacert}" "${SIGNKEY}"
|
|
logerr "Could not create local CA."
|
|
logerr "${msg}"
|
|
return 1
|
|
}
|
|
rm -f "${tmp}"
|
|
fi
|
|
) 100>"${LOCK}"
|
|
|
|
return 0
|
|
}
|
|
|
|
usage() {
|
|
cat <<_EOF_
|
|
Usage: $(basename "$1") [options]
|
|
|
|
The following options are supported:
|
|
|
|
--type type The type of certificate to create: 'ek' or 'platform'
|
|
--ek key-param The modulus of an RSA key or x=...,y=,... for an EC key
|
|
--dir directory The directory to write the resulting certificate into
|
|
--vmid vmid The ID of the virtual machine
|
|
--optsfile file A file containing options to pass to swtpm_cert
|
|
--configfile file A file containing configuration parameters for directory,
|
|
signing key and password and certificate to use
|
|
--logfile file A file to write a log into
|
|
--tpm-spec-family s The implemented spec family, e.g., '2.0'
|
|
--tpm-spec-revision i The spec revision of the TPM as integer; e.g., 146
|
|
--tpm-spec-level i The spec level of the TPM; must be an integer; e.g. 00
|
|
--tpm-manufacturer s The manufacturer of the TPM; e.g., id:00001014
|
|
--tpm-model s The model of the TPM; e.g., 'swtpm'
|
|
--tpm-version i The (firmware) version of the TPM; e.g., id:20160511
|
|
--tpm2 Generate a certificate for a TPM 2
|
|
--allow-signing The TPM 2's EK can be used for signing
|
|
--decryption The TPM 2's EK can be used for decryption
|
|
--help, -h, -? Display this help screen and exit
|
|
|
|
|
|
The following environment variables are supported:
|
|
|
|
SWTPM_ROOTCA_PASSWORD The root CA's private key password
|
|
|
|
_EOF_
|
|
}
|
|
|
|
main() {
|
|
local typ ek dir vmid tmp
|
|
local tpm_spec_params="" tpm_attr_params=""
|
|
local flags=0
|
|
|
|
while [ $# -ne 0 ]; do
|
|
case "$1" in
|
|
--type)
|
|
shift
|
|
typ="$1"
|
|
;;
|
|
--ek)
|
|
shift
|
|
ek="$1"
|
|
;;
|
|
--dir)
|
|
shift
|
|
dir="$1"
|
|
;;
|
|
--vmid)
|
|
shift
|
|
vmid="$1"
|
|
;;
|
|
--optsfile)
|
|
shift
|
|
LOCALCA_OPTIONS="$1"
|
|
;;
|
|
--configfile)
|
|
shift
|
|
LOCALCA_CONFIG="$1"
|
|
;;
|
|
--logfile)
|
|
shift
|
|
LOGFILE="$1"
|
|
;;
|
|
--tpm-spec-family)
|
|
shift
|
|
tpm_spec_params+="--tpm-spec-family $1 "
|
|
;;
|
|
--tpm-spec-revision)
|
|
shift
|
|
tpm_spec_params+="--tpm-spec-revision $1 "
|
|
;;
|
|
--tpm-spec-level)
|
|
shift
|
|
tpm_spec_params+="--tpm-spec-level $1 "
|
|
;;
|
|
--tpm-manufacturer)
|
|
shift
|
|
tpm_attr_params+="--tpm-manufacturer $1 "
|
|
;;
|
|
--tpm-model)
|
|
shift
|
|
tpm_attr_params+="--tpm-model $1 "
|
|
;;
|
|
--tpm-version)
|
|
# this is the firmware version!
|
|
shift
|
|
tpm_attr_params+="--tpm-version $1 "
|
|
;;
|
|
--tpm2)
|
|
flags=$((flags | SETUP_TPM2_F))
|
|
;;
|
|
--allow-signing)
|
|
flags=$((flags | ALLOW_SIGNING_F))
|
|
;;
|
|
--decryption)
|
|
flags=$((flags | DECRYPTION_F))
|
|
;;
|
|
--help|-h|-?)
|
|
usage "$0"
|
|
exit 0
|
|
;;
|
|
*)
|
|
logerr "Unsupported option $1"
|
|
exit 1
|
|
;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
if [ -n "$LOGFILE" ]; then
|
|
touch "$LOGFILE" &>/dev/null
|
|
if [ ! -w "$LOGFILE" ]; then
|
|
logerr "Cannot write to logfile ${LOGFILE}."
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
if [ ! -r "$LOCALCA_OPTIONS" ]; then
|
|
logerr "Cannot access options file ${LOCALCA_OPTIONS}."
|
|
exit 1
|
|
fi
|
|
|
|
if [ ! -r "$LOCALCA_CONFIG" ]; then
|
|
logerr "Cannot access config file ${LOCALCA_CONFIG}."
|
|
exit 1
|
|
fi
|
|
|
|
tmp=$(get_config_value "$LOCALCA_CONFIG" "statedir")
|
|
if [ -z "$tmp" ]; then
|
|
logerr "Missing 'statedir' config value in config file ${LOCALCA_CONFIG}"
|
|
exit 1
|
|
fi
|
|
STATEDIR="$tmp"
|
|
make_dir "$STATEDIR"
|
|
LOCK="${STATEDIR}/.lock.swtpm-localca"
|
|
if [ ! -w "${LOCK}" ]; then
|
|
touch "$LOCK"
|
|
if [ ! -w "${LOCK}" ]; then
|
|
logerr "Could not create lock file ${LOCK}."
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
SIGNKEY=$(get_config_value "$LOCALCA_CONFIG" "signingkey")
|
|
if [ -z "$SIGNKEY" ]; then
|
|
logerr "Missing signingkey variable in config file $LOCALCA_CONFIG."
|
|
exit 1
|
|
fi
|
|
# SIGNKEY may be a GNUTLS url like tpmkey:file= or tpmkey:uuid=
|
|
if ! [[ "${SIGNKEY}" =~ ^tpmkey:(file|uuid)= ]]; then
|
|
make_dir "$(dirname "$SIGNKEY")"
|
|
fi
|
|
SIGNKEY_PASSWORD=$(get_config_value "$LOCALCA_CONFIG" "signingkey_password")
|
|
PARENTKEY_PASSWORD=$(get_config_value "$LOCALCA_CONFIG" "parentkey_password")
|
|
|
|
ISSUERCERT=$(get_config_value "$LOCALCA_CONFIG" "issuercert")
|
|
if [ -z "$ISSUERCERT" ]; then
|
|
logerr "Missing issuercert variable in config file $LOCALCA_CONFIG."
|
|
exit 1
|
|
fi
|
|
make_dir "$(dirname "$ISSUERCERT")"
|
|
|
|
# set global CERTTOOL to gnutls's certtool
|
|
case "${UNAME_S}" in
|
|
Darwin)
|
|
CERTTOOL="gnutls-certtool";;
|
|
*)
|
|
CERTTOOL="certtool";;
|
|
esac
|
|
|
|
# TPM keys are GNUTLS URLs...
|
|
if [[ "$SIGNKEY" =~ ^tpmkey:(uuid|file)= ]]; then
|
|
export TSS_TCSD_HOSTNAME=$(get_config_value "$LOCALCA_CONFIG" \
|
|
"TSS_TCSD_HOSTNAME" "localhost")
|
|
export TSS_TCSD_PORT=$(get_config_value "$LOCALCA_CONFIG" \
|
|
"TSS_TCSD_PORT" "30003")
|
|
logit "CA uses a GnuTLS TPM key; using TSS_TCSD_HOSTNAME=${TSS_TCSD_HOSTNAME}" \
|
|
"TSS_TCSD_PORT=${TSS_TCSD_PORT}"
|
|
elif [[ "$SIGNKEY" =~ ^pkcs11: ]]; then
|
|
export SWTPM_PKCS11_PIN=$(get_config_value "$LOCALCA_CONFIG" \
|
|
"SWTPM_PKCS11_PIN" "swtpm-tpmca")
|
|
logit "CA uses a PKCS#11 key; using SWTPM_PKCS11_PIN"
|
|
else
|
|
if [ ! -r "$SIGNKEY" ]; then
|
|
if [ -f "$SIGNKEY" ]; then
|
|
logerr "Signing key $SIGNKEY exists but cannot access" \
|
|
"it as $(id -un):$(id -gn)."
|
|
exit 1
|
|
fi
|
|
# Create the signing key and issuer cert since it will be missing
|
|
logit "Creating root CA and a local CA's signing key and issuer cert."
|
|
create_localca_cert
|
|
if [ $? -ne 0 ]; then
|
|
logerr "Error creating local CA's signing key and cert"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
if [ ! -r "$SIGNKEY" ]; then
|
|
logerr "Cannot access signing key ${SIGNKEY}."
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
if [ ! -r "$ISSUERCERT" ]; then
|
|
logerr "Cannot access issuer certificate ${ISSUERCERT}."
|
|
exit 1
|
|
fi
|
|
|
|
CERTSERIAL=$(get_config_value "$LOCALCA_CONFIG" "certserial" \
|
|
"${STATEDIR}/certserial")
|
|
make_dir "$(dirname "$CERTSERIAL")"
|
|
|
|
create_cert "$flags" "$typ" "$dir" "$ek" "$vmid" "$tpm_spec_params" \
|
|
"$tpm_attr_params"
|
|
|
|
exit $?
|
|
}
|
|
|
|
main "$@" # 2>&1 | tee -a /tmp/localca.log
|