/
githubmirror
/
swtpm
Обзор
Документация
Войти
/
githubmirror
/
swtpm
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
samples/swtpm-create-tpmca
420 строк
10 KB
Stefan Berger
tests+samples: Check for --help support to determine stat/sed tools flavor
20 май 2026, 02:14
20 май 2026, 02:14
895df2c
Код
Авторство
О чём код?
#!/usr/bin/env bash FLAG_OVERWRITE=1 FLAG_TPM2=2 logit() { if [ -z "$LOGFILE" ]; then echo "$@" >&1 else echo "$@" >> "$LOGFILE" fi } logerr() { if [ -z "$LOGFILE" ]; then echo "Error: $*" >&2 else echo "Error: $*" >> "$LOGFILE" fi } # Get the size of a file in bytes # # @1: filename function get_filesize() { if stat --help &>/dev/null; then stat -c%s "$1" else # OpenBSD stat -f%z "$1" fi } # Get the OpenSSL provider path for the given module searching a few well-known # paths. function get_provider_path() { local module="$1" local p for p in \ "/usr/lib64/ossl-modules" \ "/usr/lib/ossl-modules" \ "/usr/lib/$(uname -m)-linux-gnu/ossl-modules"; do if [ -r "${p}/${module}" ]; then echo "${p}" return 0 fi done logerr "Could not find OpenSSL provider path for ${module} module." return 1 } # Create a config value by escaping the proper characters # # @param 1: The string to escape function escape_pkcs11_url() { echo "${1//;/\\;}" } create_localca_cert() { local flags=$1 local dir="$2" local outfile="$3" local owner="$4" local pid="$5" # TPM2 parameter local algorithm="$6" # RSA or EC-key signing local cakey=${dir}/swtpm-localca-rootca-privkey.pem local cacert=${dir}/swtpm-localca-rootca-cert.pem local tpmkey=${dir}/swtpm-localca-tpmca-privkey.pem local tpmpubkey=${dir}/swtpm-localca-tpmca-pubkey.pem local tpmca=${dir}/swtpm-localca-tpmca-cert.pem local pinfile=${dir}/pin local passfile=${dir}/password local tpmkeyurl local msg output providerpath export SWTPM_ROOTCA_PASSWORD if ! [ -r "${cakey}" ] || ! [ -r "${cacert}" ]; then # shellcheck disable=2086 if ! msg=$(openssl \ req \ -x509 \ -keyout "${cakey}" \ -newkey rsa:3072 \ ${SWTPM_ROOTCA_PASSWORD:+-passout "env:SWTPM_ROOTCA_PASSWORD"} \ ${SWTPM_ROOTCA_PASSWORD:--noenc} \ -out "${cacert}" \ -days 36500 \ -sha256 \ -subj "/CN=swtpm-localca-rootca" \ -addext "basicConstraints=critical,CA:TRUE" \ -addext "keyUsage=critical,keyCertSign" \ 2>&1); then logerr "Could not create root CA." logerr "${msg}" rm -f "${cakey}" "${passfile}" return 1 fi chmod 640 "${cakey}" rm -f "${passfile}" else logit "Reusing existing root CA" fi rm -f "${tpmkey}" "${tpmpubkey}" "${tpmca}" if [ $((flags & FLAG_TPM2)) -ne 0 ]; then local tokenurl tpmkeyurl local token="swtpm-tpmca-${pid}" local label="${token}" # must be same local keylabel="swtpm-tpmca-key" local userpin="${SWTPM_PKCS11_PIN:-swtpm-tpmca}" tokenurl=$(p11tool --list-tokens 2>&1 | \ grep -E ";token=${token}\$" | \ sed -n "s/.*URL: //p") if [ -z "${tokenurl}" ]; then if [ -z "${SWTPM_PKCS11_SO_PIN}" ]; then logerr "The env. variable SWTPM_PKCS11_SO_PIN must be set to create token ${label}." return 1 fi if ! msg=$(tpm2_ptool addtoken \ --pid "${pid}" \ --sopin "${SWTPM_PKCS11_SO_PIN}" \ --userpin "${userpin}" \ --label "${label}" 2>&1); then logerr "Error: Could not create pkcs11 token" logerr "${msg}" return 1 fi tokenurl=$(p11tool --list-tokens 2>&1 | \ grep -E ";token=${token}\$" | \ sed -n "s/.*URL: //p") if [ -z "${tokenurl}" ]; then logerr "Error: Could not get token URL for token '${token}'" logerr "${msg}" return 1 fi if ! msg=$(tpm2_ptool config \ --key tcti \ --value tabrmd \ --label "${label}"); then logerr "Error: Could not set config value for tcti key" logerr "${msg}" return 1 fi fi export GNUTLS_PIN="${userpin}" # GNUTLS_SO_PIN not needed at this point if msg="$(p11tool --login --list-keys "${tokenurl}" 2>&1)"; then tpmkeyurl=$(echo "${msg}" | \ grep ";object=${keylabel}" | \ sed -n "s/.*URL: //p") fi if [ -z "${tpmkeyurl}" ]; then if ! msg=$(tpm2_ptool addkey \ "--label=${label}" \ "--userpin=${userpin}" \ "--algorithm=${algorithm}" \ "--key-label=${keylabel}" \ --id 1 2>&1); then logerr "Error: Could not create create key under pkcs11 token ${token}" logerr "${msg}" return 1 fi if ! msg="$(p11tool --login --list-keys "${tokenurl}" 2>&1)"; then logerr "Error: Could not get TPM key URL for ${tokenurl}" logerr "${msg}" return 1 fi tpmkeyurl=$(echo "${msg}" | \ grep ";object=${keylabel}" | \ sed -n "s/.*URL: //p") if [ -z "${tpmkeyurl}" ]; then logerr "Error: Could not get TPM key URL for ${tokenurl}" logerr "${msg}" return 1 fi fi rm -f "${tpmpubkey}" if ! msg=$(p11tool --export-pubkey "${tpmkeyurl}" --login --outfile "${tpmpubkey}" 2>&1) || \ [ ! -r "${tpmpubkey}" ] || [ "$(get_filesize "${tpmpubkey}")" -eq 0 ]; then logerr "Error: Could not get TPM public key" logerr "${msg}" rm -f "${tpmkey}" "${tpmpubkey}" return 1 fi else logerr "TPM1.2 is not supported anymore." return 1 fi if ! providerpath=$(get_provider_path "pkcs11.so"); then return 1 fi # Write any PIN into a PIN file echo "${SWTPM_PKCS11_PIN}" > "${pinfile}" if ! msg=$(openssl \ req \ -provider-path "${providerpath}" \ -provider pkcs11 \ -x509 \ -key "${tpmkeyurl//%00/}${SWTPM_PKCS11_PIN:+?pin-source=${pinfile}}" \ -out "${tpmca}" \ -days 36500 \ -sha256 \ -CA "${cacert}" \ -CAkey "${cakey}" \ ${SWTPM_ROOTCA_PASSWORD:+-passin "env:SWTPM_ROOTCA_PASSWORD"} \ -subj "/CN=swtpm-localca" \ -addext "basicConstraints=critical,CA:TRUE" \ -addext "keyUsage=critical,keyCertSign" \ 2>&1); then logerr "Could not create TPM CA" logerr "${msg}" rm -f "${pinfile}" return 1 fi rm -f "${pinfile}" output="statedir = ${dir} signingkey = $(escape_pkcs11_url "${tpmkeyurl//%00/}") issuercert = ${tpmca} certserial = ${dir}/certserial" output+="$(echo -e "\nSWTPM_PKCS11_PIN = ${SWTPM_PKCS11_PIN}")" # output+="$(echo -e "\nSWTPM_PKCS11_SO_PIN = ${SWTPM_PKCS11_SO_PIN}")" if [ -n "${TPM_KEY_PASSWORD}" ]; then output+="$(echo -e "\nsigningkey_password = ${TPM_KEY_PASSWORD}")" fi if [ -n "${outfile}" ]; then echo "${output}" > "${outfile}" chmod 640 "${outfile}" fi echo "${output}" if [ "$(id -u)" -eq 0 ]; then chown "${owner}:${group}" "${dir}" if pushd "${dir}" &>/dev/null; then chown "${owner}:${group}" ./* popd &>/dev/null || return 1 fi if [ -n "${outfile}" ]; then chown "${owner}:${group}" "${outfile}" fi fi return 0 } #create_localca_cert usage() { local flags=$2 cat << _EOF_ Create a TPM-based CA for signing EK and platform certificates. Usage: $(basename "$1") [options] THIS SCRIPT IS EXPERIMENTAL The following options are supported: --dir directory Directory where to write the CA files into; must not exist unless --overwrite is passed --overwrite Overwrite any data in an existing directory; tries to reuse a root CA if one is found there --key-password s Password for the newly created TPM key --outfile file File to write the configuration to; if not passed it will be written to stdout only --owner owner The owner of the directory and the files; only set if this script is run as root; recommended to be 'tss' --group group The group owning the directory and the files; recommended to be 'tss' --tpm2 Setup a CA that uses a TPM 2.0 --algorithm <alg> Key algorithm for created TPM 2 CA. Default is rsa2048. Possible values are: rsa2048, rsa3072, ecc256 or secp256r1, ecc384 or secp384r1 --pid <pid> Pimary object Id used by tpm2_ptool; only valid if --tpm2 is used --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_ } #usage main() { local flags=0 local dir outfile owner group msg pid local algorithm="rsa2048" while [ $# -ne 0 ]; do case "$1" in --dir) shift dir="$1" ;; --overwrite) flags=$((flags | FLAG_OVERWRITE)) ;; --key-password) shift TPM_KEY_PASSWORD="$1" ;; --outfile) shift outfile="$1" ;; --owner) shift owner="$1" ;; --group) shift group="$1" ;; --tpm2) flags=$((flags | FLAG_TPM2)) ;; --algorithm) shift algorithm="$1" ;; --pid) shift pid="$1" ;; --help|-h|-?) usage "$0" "${flags}" exit 0 ;; *) logerr "Unsupported option $1" exit 1 ;; esac shift done if [ -z "${dir}" ]; then logerr "Missing --dir option." return 1 fi # strip trailing '/' from dir dir="$(echo "${dir}" | sed -n 's|[/]*$||p')" if [ -d "${dir}" ] && [ $((flags & FLAG_OVERWRITE)) -eq 0 ]; then logerr "Refusing to overwrite existing directory ${dir}." return 1 fi if [ $((flags & FLAG_TPM2)) -ne 0 ] && [ -z "${pid}" ]; then logerr "--pid is required for TPM 2" return 1 fi if [ "$(id -u)" -eq 0 ]; then if [ -n "${owner}" ]; then if ! msg="$(id -u "${owner}" 2>&1)"; then logerr "User ${owner} cannot be used: ${msg}" return 1 fi else owner="root" fi if [ -n "${group}" ]; then if ! msg="$(id -g "${group}" 2>&1)"; then logerr "Group ${group} cannot be used: ${msg}" return 1 fi else group="root" fi fi if ! mkdir -p "${dir}"; then logerr "Could not create directory ${dir}." return 1 fi if ! [[ "${algorithm}" =~ ^(rsa2048|rsa3072|ecc256|ecc384|secp256r1|secp384r1)$ ]]; then logerr "Unsupported key algorithm for TPM CA '${algorithm}'. See --help." return 1 else case "${algorithm}" in secp256r1) algorithm=ecc256;; secp384r1) algorithm=ecc384;; esac fi create_localca_cert "${flags}" "${dir}" "${outfile}" "${owner}" "${pid}" "${algorithm}" return $? } #main main "$@" exit $?