Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replacing nvram key with computed pcr fails with policy check error #15

Open
Yannik opened this issue Jun 2, 2023 · 2 comments
Open

Comments

@Yannik
Copy link
Contributor

Yannik commented Jun 2, 2023

I am trying to replace a tpm key stored in nvram with a computed pcr as described in the README:

luks-tpm2 -x 0x1410001 -c "~/tpm_futurepcr/bin/tpm_futurepcr -L '::pcr::' -o '::output::'" compute

For some reason, this fails with a tpm2_nvwrite policy check failed error.

Here is the script running with -x set:

+ main -x 0x1410001 -c '~/tpm_futurepcr/bin/tpm_futurepcr -L '\''::pcr::'\'' -o '\''::output::'\''' compute
+ load_defaults
+ TMPFS_MOUNT=/root/keyfs
+ SEALED_KEY_PUBLIC=/boot/keyfile.pub
+ SEALED_KEY_PRIVATE=/boot/keyfile.priv
+ PARENT_HANDLE=0x81000001
+ PARENT_KEY_PROMPT=
+ PARENT_KEY_PATH=
+ NVRAM_INDEX=
+ KEY_SIZE=32
+ TPM_KEY_SLOT=1
+ RESET_KEY_SLOT=2
+ PCRS=sha256:0,2,4,7
+ UNSEAL_PCRS=
+ TPM2TOOLS_TCTI=device:/dev/tpmrm0
+ COMPUTE_COMMAND=
+ CONFFILE=/etc/default/luks-tpm2
+ '[' -r /etc/default/luks-tpm2 ']'
+ parse_args -x 0x1410001 -c '~/tpm_futurepcr/bin/tpm_futurepcr -L '\''::pcr::'\'' -o '\''::output::'\''' compute
+ ORIGINAL_ARGS='-x 0x1410001 -c ~/tpm_futurepcr/bin/tpm_futurepcr -L '\''::pcr::'\'' -o '\''::output::'\'' compute'
+ getopts :hvm:p:H:Kk:x:s:t:r:L:l:T:c: opt
+ case $opt in
+ NVRAM_INDEX=0x1410001
+ getopts :hvm:p:H:Kk:x:s:t:r:L:l:T:c: opt
+ case $opt in
+ COMPUTE_COMMAND='~/tpm_futurepcr/bin/tpm_futurepcr -L '\''::pcr::'\'' -o '\''::output::'\'''
+ getopts :hvm:p:H:Kk:x:s:t:r:L:l:T:c: opt
+ '[' -n '' ']'
+ shift 4
+ '[' -n '' ']'
+ '[' -n compute ']'
+ ACTION=compute
+ init_globals
+ '[' -z ']'
++ find_luks_device
++ lsblk -pfln -o NAME,FSTYPE
++ grep crypto_LUKS
++ head -1
++ cut -f1 '-d '
+ ROOT_DEVICE=/dev/nvme0n1p3
+ '[' -z /dev/nvme0n1p3 ']'
+ case "$ACTION" in
+ ACTION=compute_tpm_key
+ '[' -z '' ']'
+ UNSEAL_PCRS=sha256:0,2,4,7
+ KEYFILE=/root/keyfs/keyfile
+ POLICY_DIGEST=/root/keyfs/policy.digest
+ OBJECT_CONTEXT=/root/keyfs/object.context
+ PCR_VALUES=/root/keyfs/pcr.bin
+ RETURN_CODE=0
+ '[' -z '~/tpm_futurepcr/bin/tpm_futurepcr -L '\''::pcr::'\'' -o '\''::output::'\''' ']'
+ COMPUTE_COMMAND='~/tpm_futurepcr/bin/tpm_futurepcr -L '\''sha256:0,2,4,7'\'' -o '\''::output::'\'''
+ COMPUTE_COMMAND='~/tpm_futurepcr/bin/tpm_futurepcr -L '\''sha256:0,2,4,7'\'' -o '\''/root/keyfs/pcr.bin'\'''
+ IFS=:
+ read TPM2TOOLS_TCTI_NAME TPM2TOOLS_DEVICE_FILE
+ unset IFS
+ export TPM2TOOLS_TCTI
+ export TPM2TOOLS_TCTI_NAME
+ '[' -n /dev/tpmrm0 ']'
+ export TPM2TOOLS_DEVICE_FILE
+ '[' 0 -ne 0 ']'
+ create_ramfs
+ mkdir -p /root/keyfs
+ mount ramfs /root/keyfs -t ramfs -o size=1m
+ chmod 700 /root/keyfs
+ compute_tpm_key
+ echo 'Precomputing PCR values...'
Precomputing PCR values...
+ PCR_LIST=sha256:0,2,4,7
+ OUTPUT_PATH=/root/keyfs/pcr.bin
+ sh -c '~/tpm_futurepcr/bin/tpm_futurepcr -L '\''sha256:0,2,4,7'\'' -o '\''/root/keyfs/pcr.bin'\'''
+ '[' 0 -ne 0 ']'
+ replace_tpm_key
+ original_keyfile=/root/keyfs/keyfile.orig
+ unseal_key
+ use_nvram
+ '[' -n 0x1410001 ']'
+ echo 'Reading key from TPM NVRAM...'
Reading key from TPM NVRAM...
+ tpm2_nvread -P pcr:sha256:0,2,4,7 -o /root/keyfs/keyfile 0x1410001
WARN: Reading full size of the NV index
+ mv /root/keyfs/keyfile /root/keyfs/keyfile.orig
+ generate_keyfile
+ dd bs=32 count=1 if=/dev/urandom of=/root/keyfs/keyfile
+ echo 'Replacing LUKS key in slot 1 on /dev/nvme0n1p3...'
Replacing LUKS key in slot 1 on /dev/nvme0n1p3...
+ cryptsetup luksChangeKey /dev/nvme0n1p3 /root/keyfs/keyfile --key-slot 1 --key-file /root/keyfs/keyfile.orig
+ seal_key
+ '[' '!' -f /root/keyfs/pcr.bin ']'
+ tpm2_createpolicy --policy-pcr -l sha256:0,2,4,7 -f /root/keyfs/pcr.bin -L /root/keyfs/policy.digest
+ use_nvram
+ '[' -n 0x1410001 ']'
+ echo 'Storing key in TPM NVRAM...'
Storing key in TPM NVRAM...
+ tpm2_getcap properties-variable
+ grep ownerAuthSet
+ grep -sq 0
+ tpm2_nvundefine 0x1410001
+ tpm2_nvdefine -L /root/keyfs/policy.digest -s 32 -a 'policyread|policywrite' 0x1410001
+ tpm2_nvwrite -P pcr:sha256:0,2,4,7 -i /root/keyfs/keyfile 0x1410001
WARNING:esys:src/tss2-esys/api/Esys_NV_Write.c:310:Esys_NV_Write_Finish() Received TPM Error 
ERROR:esys:src/tss2-esys/api/Esys_NV_Write.c:110:Esys_NV_Write() Esys Finish ErrorCode (0x0000099d) 
ERROR: Failed to write NV area at index 0x1410001
ERROR: Tss2_Sys_NV_Write(0x99D) - tpm:session(1):a policy check failed
ERROR: Unable to run tpm2_nvwrite
+ retval=1
+ rm -f /root/keyfs/policy.digest
+ return 1
+ echo 'There was an error sealing the new keyfile!'
There was an error sealing the new keyfile!
+ RETURN_CODE=7
+ destroy_ramfs
+ '[' -f /root/keyfs/keyfile ']'
++ stat --printf=%s /root/keyfs/keyfile
+ dd if=/dev/urandom of=/root/keyfs/keyfile bs=32 count=1 conv=notrunc
+ rm -f /root/keyfs/keyfile
+ umount /root/keyfs
+ exit 7

This error occurs even if the computed pcrs are identical to the current pcrs. Luks unlock after writing to nvram with luks-tpm2 init works without a problem.

I'd be grateful about advice on how to fix this.

@Yannik
Copy link
Contributor Author

Yannik commented Jun 2, 2023

I worked around grawity/tpm_futurepcr#18 by simply re-using PCR0 from tpm2_pcrread:

/luks-tpm2 -x "$nv_index" -c "~/tpm_futurepcr/bin/tpm_futurepcr -L '::pcr::' -o '::output::'; tpm2_pcrread -o pcrread0.bin 'sha256:0'; dd if=pcrread0.bin of='::output::' bs=32 count=1 conv=notrunc; rm pcrread0.bin" compute

Now it works when the PCR has not changed, but any change e.g. to PCR4 results in the error I posted in my OP.

@electrickite
Copy link
Owner

I don't use this particular workflow on my system so it is difficult for me to reproduce this issue. I'm curious, though - if you change line 228 in luks-tpm2 from:

    tpm2_nvdefine $tpm_auth_pass -L "$POLICY_DIGEST" -s $KEY_SIZE -a "policyread|policywrite" "$NVRAM_INDEX" >/dev/null

to:

    tpm2_nvdefine $tpm_auth_pass -L "$POLICY_DIGEST" -s $KEY_SIZE -a "policyread|policywrite|ownerwrite" "$NVRAM_INDEX" >/dev/null

By adding |ownerwrite to the -a option, does that resolve the issue? Reading through the program flow, it looks like we are setting a policy that will not allow writes unless the new PCR values are already in place.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants