Re: [PATCH v10 20/20] tests: Add tpm2_test

2024-04-15 Thread Gary Lin via Grub-devel
On Fri, Apr 12, 2024 at 12:09:36PM -0400, Stefan Berger wrote:
> 
> 
> On 4/9/24 04:30, Gary Lin via Grub-devel wrote:
> > For the tpm2 module, the TCG2 command submission function is the only
> > difference between the a QEMU instance and grub-emu. To test TPM key
> > unsealing with a QEMU instance, it requires an extra OS image to invoke
> > grub-protect to seal the LUKS key, rather than a simple grub-shell rescue
> > CD image. On the other hand, grub-emu can share the emulated TPM device
> > with the host, so that we can seal the LUKS key on host and test key
> > unsealing with grub-emu.
> > 
> > This test script firstly creates a simple LUKS image to be loaded as a
> > loopback device in grub-emu. Then an emulated TPM device is created by
> > swtpm_cuse and PCR 0 and 1 are extended.
> 
> My concern here would be that distros for example don't build swtpm with the
> CUSE interface but build it with the socket and chardev interfaces. If you
> don't want users to have to build their own version of swtpm then I would
> suggest to use either 'swtpm chardev' with the vtpm_proxy module (it is
> quite commonly available on recent distros) or 'swtpm socket'.
> 
> The chardev usage is for example described here and should be least involved
> to convert to:
> 
> https://github.com/stefanberger/swtpm/wiki/Using-the-Intel-TSS-with-swtpm#character-device-using-tpm_vtpm_proxy
> 
> You could start it like this with UnixIO control port (needs adjustment to
> swtpm_ioctl in your code).
> 
> swtpm chardev --vtpm-proxy --tpmstate dir=/tmp/myvtpm --tpm2 --ctrl
> type=unixio,path=/tmp/myvtpm/ctrl --flags startup-clear --daemon > logfile
> 
> No need to run 'swtpm_ioctl -i' and tpm2_startup with the startup-clear
> passed.
> 
> One of my test cases determines the created device (/dev/tpmXYZ) like this:
> 
> for ((i = 0; i < 200; i ++)); do
> if [ -z "${TPM_DEVICE}" ]; then
> TPM_DEVICE=$(sed -n 's,.*\(/dev/tpm[0-9]\+\).*,\1,p'
> "logfile")
> if [ -n "${TPM_DEVICE}" ]; then
> echo "Using ${TPM_DEVICE}."
> fi
> fi
> if [ -n "${TPM_DEVICE}" ]; then
> [ -c "${TPM_DEVICE}" ] && break
> fi
> sleep 0.1
> done
> 
> shutdown: sudo swtpm_ioctl -s --unix /tmp/myvtpm/ctrl
> 
> 
> Otherwise you could use the socket version described here:
> 
> https://github.com/stefanberger/swtpm/wiki/Using-the-Intel-TSS-with-swtpm#socket-interface
> 
> It needs the swtpm tcti as a dependency, though.
> 
Thanks for the suggestion. Using 'swtpm socket' requires additional changes
to grub-emu and grub-protect. To minimize the impact, I'd convert the test
script to use 'swtpm chardev'.

Gary Lin

>Stefan
> 
> > 
> > There are several test cases in the script to test various settings. Each
> > test case uses grub-protect to seal the LUKS password against PCR 0 and
> > PCR 1. Then grub-emu is launched to load the LUKS image, try to mount
> > the image with tpm2_key_protector_init and cryptomount, and verify the
> > result.
> > 
> > Based on the idea from Michael Chang.
> > 
> > Cc: Michael Chang 
> > Signed-off-by: Gary Lin 

___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


Re: [PATCH v10 20/20] tests: Add tpm2_test

2024-04-12 Thread Stefan Berger



On 4/9/24 04:30, Gary Lin via Grub-devel wrote:

For the tpm2 module, the TCG2 command submission function is the only
difference between the a QEMU instance and grub-emu. To test TPM key
unsealing with a QEMU instance, it requires an extra OS image to invoke
grub-protect to seal the LUKS key, rather than a simple grub-shell rescue
CD image. On the other hand, grub-emu can share the emulated TPM device
with the host, so that we can seal the LUKS key on host and test key
unsealing with grub-emu.

This test script firstly creates a simple LUKS image to be loaded as a
loopback device in grub-emu. Then an emulated TPM device is created by
swtpm_cuse and PCR 0 and 1 are extended.


My concern here would be that distros for example don't build swtpm with 
the CUSE interface but build it with the socket and chardev interfaces. 
If you don't want users to have to build their own version of swtpm then 
I would suggest to use either 'swtpm chardev' with the vtpm_proxy module 
(it is quite commonly available on recent distros) or 'swtpm socket'.


The chardev usage is for example described here and should be least 
involved to convert to:


https://github.com/stefanberger/swtpm/wiki/Using-the-Intel-TSS-with-swtpm#character-device-using-tpm_vtpm_proxy

You could start it like this with UnixIO control port (needs adjustment 
to swtpm_ioctl in your code).


swtpm chardev --vtpm-proxy --tpmstate dir=/tmp/myvtpm --tpm2 --ctrl 
type=unixio,path=/tmp/myvtpm/ctrl --flags startup-clear --daemon > logfile


No need to run 'swtpm_ioctl -i' and tpm2_startup with the startup-clear 
passed.


One of my test cases determines the created device (/dev/tpmXYZ) like this:

for ((i = 0; i < 200; i ++)); do
if [ -z "${TPM_DEVICE}" ]; then
TPM_DEVICE=$(sed -n 's,.*\(/dev/tpm[0-9]\+\).*,\1,p' 
"logfile")

if [ -n "${TPM_DEVICE}" ]; then
echo "Using ${TPM_DEVICE}."
fi
fi
if [ -n "${TPM_DEVICE}" ]; then
[ -c "${TPM_DEVICE}" ] && break
fi
sleep 0.1
done

shutdown: sudo swtpm_ioctl -s --unix /tmp/myvtpm/ctrl


Otherwise you could use the socket version described here:

https://github.com/stefanberger/swtpm/wiki/Using-the-Intel-TSS-with-swtpm#socket-interface

It needs the swtpm tcti as a dependency, though.

   Stefan



There are several test cases in the script to test various settings. Each
test case uses grub-protect to seal the LUKS password against PCR 0 and
PCR 1. Then grub-emu is launched to load the LUKS image, try to mount
the image with tpm2_key_protector_init and cryptomount, and verify the
result.

Based on the idea from Michael Chang.

Cc: Michael Chang 
Signed-off-by: Gary Lin 
---
  Makefile.util.def|   6 +
  tests/tpm2_test.in   | 284 +++
  tests/util/grub-shell.in |   6 +-
  3 files changed, 295 insertions(+), 1 deletion(-)
  create mode 100644 tests/tpm2_test.in

diff --git a/Makefile.util.def b/Makefile.util.def
index a0a3e2cd5..77bbdd453 100644
--- a/Makefile.util.def
+++ b/Makefile.util.def
@@ -1279,6 +1279,12 @@ script = {
common = tests/asn1_test.in;
  };
  
+script = {

+  testcase = native;
+  name = tpm2_test;
+  common = tests/tpm2_test.in;
+};
+
  program = {
testcase = native;
name = example_unit_test;
diff --git a/tests/tpm2_test.in b/tests/tpm2_test.in
new file mode 100644
index 0..8d4e96f47
--- /dev/null
+++ b/tests/tpm2_test.in
@@ -0,0 +1,284 @@
+#! @BUILD_SHEBANG@ -e
+
+# Test GRUBs ability to unseal a LUKS key with TPM 2.0
+# Copyright (C) 2024  Free Software Foundation, Inc.
+#
+# GRUB is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# GRUB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GRUB.  If not, see .
+
+grubshell=@builddir@/grub-shell
+
+. "@builddir@/grub-core/modinfo.sh"
+
+if [ x$grub_modinfo_platform != xemu ]; then
+  exit 77
+fi
+
+builddir="@builddir@"
+
+# Force build directory components
+PATH="${builddir}:$PATH"
+export PATH
+
+if [ "x$EUID" = "x" ] ; then
+  EUID=`id -u`
+fi
+
+if [ "$EUID" != 0 ] ; then
+   echo "not root; cannot test tpm2."
+   exit 99
+fi
+
+if ! which cryptsetup >/dev/null 2>&1; then
+   echo "cryptsetup not installed; cannot test tpm2."
+   exit 99
+fi
+
+if ! which swtpm >/dev/null 2>&1; then
+   echo "swtpm not installed; cannot test tpm2."
+   exit 99
+fi
+
+if ! which tpm2_startup >/dev/null 2>&1; then
+   echo "tpm2-tools not installed; cannot test tpm2."
+   exit 99
+fi
+