mirror of
https://github.com/stefanberger/swtpm.git
synced 2026-08-09 03:11:20 +00:00
swtpm_setup: Implement support for ECC keys
Implement support in swtpm_setup.sh so that the TPM's primary key can be an ECC key. Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
This commit is contained in:
parent
276eee02b4
commit
08da93a96f
@ -46,6 +46,9 @@ ek.cert and the platform certificate under the name platform.cert.
|
||||
This parameter indicates the modulus of the public key of the endorsement key
|
||||
(EK). The public key is provided as a sequence of ASCII hex digits.
|
||||
|
||||
In case ECC (elliptic curve crypography) keys are used, the parameter must
|
||||
have the format --ek x=<hex digits>,y=<hex digits>.
|
||||
|
||||
=item B<--vmid ID>
|
||||
|
||||
This parameter indicates the ID of the VM for which to create the certificate.
|
||||
|
||||
@ -49,6 +49,10 @@ Create the EK
|
||||
|
||||
Create an EK that can sign. This option requires --tpm2.
|
||||
|
||||
=item B<--ecc>
|
||||
|
||||
Create elliptic curve crypto (ECC) keys; by default RSA keys are generated.
|
||||
|
||||
=item B<--take-ownership>
|
||||
|
||||
Take ownership; this option implies --createek
|
||||
|
||||
@ -138,7 +138,7 @@ create_cert() {
|
||||
local tpm_attr_params="$7"
|
||||
|
||||
local serial=$(get_next_cert_serial)
|
||||
local options="" rc=0
|
||||
local options="" rc=0 keyparms=""
|
||||
|
||||
if [ -z "$serial" ]; then
|
||||
return 1
|
||||
@ -161,6 +161,16 @@ create_cert() {
|
||||
options="$options --add-header"
|
||||
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
|
||||
@ -174,7 +184,7 @@ create_cert() {
|
||||
--signkey ${SIGNKEY} \
|
||||
--issuercert ${ISSUERCERT} \
|
||||
--out-cert ${dir}/ek.cert \
|
||||
--modulus "${ek}" \
|
||||
$keyparms \
|
||||
--days $((10*365)) \
|
||||
--serial $serial
|
||||
if [ $? -eq 0 ]; then
|
||||
@ -197,7 +207,7 @@ create_cert() {
|
||||
--signkey ${SIGNKEY} \
|
||||
--issuercert ${ISSUERCERT} \
|
||||
--out-cert ${dir}/platform.cert \
|
||||
--modulus "${ek}" \
|
||||
$keyparms \
|
||||
--days $((10*365)) \
|
||||
--serial $serial
|
||||
if [ $? -eq 0 ]; then
|
||||
|
||||
@ -78,6 +78,7 @@ SETUP_STATE_OVERWRITE_F=128
|
||||
SETUP_STATE_NOT_OVERWRITE_F=256
|
||||
SETUP_TPM2_F=512
|
||||
SETUP_ALLOW_SIGNING_F=1024
|
||||
SETUP_TPM2_ECC_F=2048
|
||||
|
||||
SETUP_DISPLAY_RESULTS_F=4096
|
||||
|
||||
@ -119,6 +120,9 @@ NB256=${NB32}${NB32}${NB32}${NB32}${NB32}${NB32}${NB32}${NB32}
|
||||
NONCE_RSA='\x01\x00'${NB256}
|
||||
NONCE_RSA_SIZE=256
|
||||
|
||||
NONCE_ECC='\x00\x20'${NB32}
|
||||
NONCE_ECC_SIZE=32
|
||||
|
||||
trap "cleanup" SIGTERM EXIT
|
||||
|
||||
logit()
|
||||
@ -898,6 +902,112 @@ tpm2_createprimary_rsa()
|
||||
return 0
|
||||
}
|
||||
|
||||
# Create the primary key as an ECC key (EK equivalent)
|
||||
#
|
||||
# @param1: flags
|
||||
tpm2_createprimary_ecc()
|
||||
{
|
||||
local flags="$1"
|
||||
|
||||
local req rsq exp res min_exp
|
||||
local flags="$1"
|
||||
|
||||
local req rsq exp res symkeydata keyflags totlen publen off1 off2
|
||||
|
||||
if [ $((flags & SETUP_ALLOW_SIGNING_F)) -ne 0 ]; then
|
||||
# keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
|
||||
# adminWithPolicy, sign, decrypt
|
||||
keyflags=$((0x000600b2))
|
||||
# symmetric: TPM_ALG_NULL
|
||||
symkeydata='\\x00\\x10'
|
||||
publen=$((0x36 + 2 * NONCE_ECC_SIZE))
|
||||
totlen=$((0x5f + 2 * NONCE_ECC_SIZE))
|
||||
min_exp=930
|
||||
# offset of length indicator for key
|
||||
off1=210
|
||||
off2=312
|
||||
else
|
||||
# keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
|
||||
# adminWithPolicy, restricted, decrypt
|
||||
keyflags=$((0x000300b2))
|
||||
# symmetric: TPM_ALG_AES, 128bit, TPM_ALG_CFB
|
||||
symkeydata='\\x00\\x06\\x00\\x80\\x00\\x43'
|
||||
publen=$((0x3a + 2 * NONCE_ECC_SIZE))
|
||||
totlen=$((0x63 + 2 * NONCE_ECC_SIZE))
|
||||
# some version of TPM2 returns 942, another 990
|
||||
min_exp=942
|
||||
# offset of length indicator for key
|
||||
off1=222
|
||||
off2=324
|
||||
fi
|
||||
|
||||
# Check the TCG EK Credential Profile doc for TPM 2 for
|
||||
# parameters used here
|
||||
|
||||
req='\x80\x02@TOTLEN-4@\x00\x00\x01\x31'
|
||||
# TPM_RH_ENDORSEMENT
|
||||
req+='\x40\x00\x00\x0b'
|
||||
# size of buffer
|
||||
req+='\x00\x00\x00\x09'
|
||||
# TPM_RS_PW
|
||||
req+='\x40\x00\x00\x09\x00\x00\x00\x00\x00'
|
||||
# TPM2B_SENSITIVE_CREATE
|
||||
req+='\x00\x04\x00\x00\x00\x00'
|
||||
# Size of TPM2B_PUBLIC
|
||||
req+='@PUBLEN-2@'
|
||||
# TPM_ALG_ECC, TPM_ALG_SHA256
|
||||
req+='\x00\x23\x00\x0b'
|
||||
# flags: fixedTPM, fixedParent, sensitiveDatOrigin, adminWithPolicy
|
||||
# restricted, decrypt
|
||||
req+='@KEYFLAGS-4@'
|
||||
# authPolicy: size = 32 bytes
|
||||
req+='\x00\x20'
|
||||
req+='\x83\x71\x97\x67\x44\x84\xb3\xf8\x1a\x90\xcc\x8d'
|
||||
req+='\x46\xa5\xd7\x24\xfd\x52\xd7\x6e\x06\x52\x0b\x64'
|
||||
req+='\xf2\xa1\xda\x1b\x33\x14\x69\xaa'
|
||||
req+='@SYMKEYDATA@'
|
||||
# scheme: TPM_ALG_NULL, curveID: TPM_ECC_NIST_P256
|
||||
req+='\x00\x10\x00\x03'
|
||||
# kdf->scheme: TPM_ALG_NULL
|
||||
req+='\x00\x10'
|
||||
# TPM2B_DATA for x and y
|
||||
req+=${NONCE_ECC}
|
||||
req+=${NONCE_ECC}
|
||||
# TPML_PCR_SELECTION
|
||||
req+='\x00\x00\x00\x00\x00\x00'
|
||||
|
||||
req=$(echo $req | \
|
||||
sed -e "s/@KEYFLAGS-4@/$(_format "$keyflags" 4)/" \
|
||||
-e "s/@SYMKEYDATA@/$symkeydata/" \
|
||||
-e "s/@PUBLEN-2@/$(_format "$publen" 2)/" \
|
||||
-e "s/@TOTLEN-4@/$(_format "$totlen" 4)/")
|
||||
|
||||
rsp="$(tpm_transfer "${req}")"
|
||||
if [ ${#rsp} -lt $min_exp ]; then
|
||||
logerr "TPM2_CreatePrimary(ECC) failed"
|
||||
logerr " expected at least $min_exp bytes, got ${#rsp}."
|
||||
logerr " response: $rsp"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Check the x and y length indicators
|
||||
if [ "${rsp:$off1:6}" != " 00 20" ] || \
|
||||
[ "${rsp:$off2:6}" != " 00 20" ]; then
|
||||
logerr "Getting ECC x and y parameter from wrong offset."
|
||||
return 1
|
||||
fi
|
||||
|
||||
let off1=off1+6
|
||||
let off2=off2+6
|
||||
|
||||
# output: handle,ek
|
||||
res="$(echo "0x${rsp:30:12}" | sed -n 's/ //pg'),"
|
||||
res+="$(echo x=${rsp:$off1:96},y=${rsp:$off2:96} | sed -n 's/ //pg')"
|
||||
echo $res
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Make a object permanent
|
||||
#
|
||||
# @param1: the current object handle
|
||||
@ -944,7 +1054,11 @@ tpm2_createprimary()
|
||||
tpm2_changeeps
|
||||
[ $? -ne 0 ] && return 1
|
||||
|
||||
res=$(tpm2_createprimary_rsa "$flags")
|
||||
if [ $((flags & SETUP_TPM2_ECC_F)) -ne 0 ]; then
|
||||
res=$(tpm2_createprimary_ecc "$flags")
|
||||
else
|
||||
res=$(tpm2_createprimary_rsa "$flags")
|
||||
fi
|
||||
[ $? -ne 0 ] && return 1
|
||||
|
||||
handle=$(echo $res | cut -d "," -f1)
|
||||
@ -954,7 +1068,7 @@ tpm2_createprimary()
|
||||
[ $? -ne 0 ] && return 1
|
||||
|
||||
# ek
|
||||
echo $res | cut -d "," -f2
|
||||
echo $res | cut -d "," -f2-
|
||||
|
||||
return 0
|
||||
}
|
||||
@ -1326,6 +1440,8 @@ The following options are supported:
|
||||
--allow-signing : Create an EK that can also be used for signing;
|
||||
this option requires --tpm2.
|
||||
|
||||
--ecc : Create ECC keys rather than RSA keys; this requires --tpm2
|
||||
|
||||
--take-ownership : Take ownership; this option implies --createek
|
||||
--ownerpass <password>
|
||||
: Provide custom owner password; default is $DEFAULT_OWNER_PASSWORD
|
||||
@ -1393,6 +1509,7 @@ main()
|
||||
--tpm) shift; SWTPM="$1";;
|
||||
--swtpm_ioctl) shift; SWTPM_IOCTL="$1";;
|
||||
--tpm2) flags=$((flags | SETUP_TPM2_F));;
|
||||
--ecc) flags=$((flags | SETUP_TPM2_ECC_F));;
|
||||
--createek) flags=$((flags | SETUP_CREATE_EK_F));;
|
||||
--take-ownership) flags=$((flags |
|
||||
SETUP_CREATE_EK_F|SETUP_TAKEOWN_F));;
|
||||
@ -1472,6 +1589,11 @@ main()
|
||||
logerr "Taking ownership is not supported for TPM 2."
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
if [ $((flags & SETUP_TPM2_ECC_F)) -ne 0 ]; then
|
||||
logerr "--ecc requires --tpm2."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
check_state_overwrite "$flags" "$tpm_state_path"
|
||||
|
||||
@ -15,6 +15,14 @@ PARAMETERS=(
|
||||
"--createek --allow-signing --create-ek-cert --create-platform-cert --config ${DIR}/swtpm_setup.conf --vmid test --display"
|
||||
"--createek --allow-signing --create-ek-cert --create-platform-cert --config ${DIR}/swtpm_setup.conf --vmid test --display --keyfile ${DIR}/data/keyfile.txt"
|
||||
"--createek --allow-signing --create-ek-cert --create-platform-cert --config ${DIR}/swtpm_setup.conf --vmid test --display --pwdfile ${DIR}/data/pwdfile.txt"
|
||||
"--ecc --createek"
|
||||
"--ecc --createek --create-ek-cert --create-platform-cert --config ${DIR}/swtpm_setup.conf --vmid test --display"
|
||||
"--ecc --createek --create-ek-cert --create-platform-cert --config ${DIR}/swtpm_setup.conf --vmid test --display --keyfile ${DIR}/data/keyfile.txt"
|
||||
"--ecc --createek --create-ek-cert --create-platform-cert --config ${DIR}/swtpm_setup.conf --vmid test --display --pwdfile ${DIR}/data/pwdfile.txt"
|
||||
"--ecc --createek --allow-signing"
|
||||
"--ecc --createek --allow-signing --create-ek-cert --create-platform-cert --config ${DIR}/swtpm_setup.conf --vmid test --display"
|
||||
"--ecc --createek --allow-signing --create-ek-cert --create-platform-cert --config ${DIR}/swtpm_setup.conf --vmid test --display --keyfile ${DIR}/data/keyfile.txt"
|
||||
"--ecc --createek --allow-signing --create-ek-cert --create-platform-cert --config ${DIR}/swtpm_setup.conf --vmid test --display --pwdfile ${DIR}/data/pwdfile.txt"
|
||||
)
|
||||
|
||||
# produced file size is always the same with TPM2
|
||||
|
||||
@ -93,6 +93,45 @@ if [ ! -r "${CERTSERIAL}" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "OK"
|
||||
echo "Test 1: OK"
|
||||
|
||||
rm -rf ${SIGNINGKEY} ${ISSUERCERT} ${CERTSERIAL}
|
||||
|
||||
# we need to create at least one cert: --create-ek-cert
|
||||
$SWTPM_SETUP \
|
||||
--tpm2 \
|
||||
--ecc \
|
||||
--runas root \
|
||||
--tpm-state ${workdir} \
|
||||
--create-ek-cert \
|
||||
--config ${workdir}/swtpm_setup.conf \
|
||||
--logfile ${workdir}/logfile \
|
||||
--tpm "${SWTPM} socket" \
|
||||
--swtpm_ioctl ${SWTPM_IOCTL} \
|
||||
--overwrite
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Error: Could not run $SWTPM_SETUP."
|
||||
echo "Logfile output:"
|
||||
cat ${workdir}/logfile
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -r "${SIGNINGKEY}" ]; then
|
||||
echo "Error: Signingkey file ${SIGNINGKEY} was not created."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -r "${ISSUERCERT}" ]; then
|
||||
echo "Error: Issuer cert file ${ISSUERCERT} was not created."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -r "${CERTSERIAL}" ]; then
|
||||
echo "Error: Cert serial number file ${CERTSERIAL} was not created."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Test 2: OK"
|
||||
|
||||
exit 0
|
||||
|
||||
Loading…
Reference in New Issue
Block a user