grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH v10 00/20] Automatic Disk Unlock with TPM2


From: Gary Lin
Subject: [PATCH v10 00/20] Automatic Disk Unlock with TPM2
Date: Tue, 9 Apr 2024 16:30:32 +0800

GIT repo for v10: https://github.com/lcp/grub2/tree/tpm2-unlock-v10

This patch series is based on "Automatic TPM Disk Unlock"(*1) posted by
Hernan Gatta to introduce the key protector framework and TPM2 stack
to GRUB2, and this could be a useful feature for the systems to
implement full disk encryption.

To support TPM 2.0 Key File format(*2), patch 1~5,7 are grabbed from
Daniel Axtens's "appended signature secure boot support" (*3) to import
libtasn1 into grub2. Besides, the libtasn1 version is upgraded to
4.19.0 instead of 4.16.0 in the original patch.

Patch 6 fixes a potential buffer overrun in libtasn1.
(https://gitlab.com/gnutls/libtasn1/-/issues/49)

Patch 8 adds the document for libtasn1 and the steps to upgrade the
library.

Patch 9~13 are Hernan Gatta's patches with the follow-up fixes and
improvements:
- Converting 8 spaces into 1 tab
- Merging the minor build fix from Michael Chang
  - Replacing "lu" with "PRIuGRUB_SIZE" for grub_dprintf
  - Adding "enable = efi" to the tpm2 module in grub-core/Makefile.core.def
- Rebasing "cryptodisk: Support key protectors" to the git master
- Removing the measurement on the sealed key
  - Based on the patch from Olaf Kirch <OKir@suse.com>
- Adjusting the input parameters of TPM2_EvictControl to match the order
  in "TCG TPM2 Part3 Commands"
- Declaring the input arguments of TPM2 functions as const
- Resending TPM2 commands on TPM_RC_RETRY
- Adding checks for the parameters of TPM2 commands
- Packing the missing authorization command for TPM2_PCR_Read
- Tweaking the TPM2 command functions to allow some parameters to be
  NULL so that we don't have to declare empty variables
- Only enabling grub-protect for "efi" since the TPM2 stack currently
  relies on the EFI TCG2 protocol to send TPM2 commands
- Using grub_cpu_to_be*() in the TPM2 stack instead of grub_swap_bytes*()
  which may cause problems in big-indian machines
- Changing the short name of "--protector" of "cryptomount" from "-k" to
  "-P" to avoid the conflict with "--key-file"
- Supporting TPM 2.0 Key File Format besides the raw sealed key
- Adding the external libtasn1 dependency to grub-protect to write the
  TPM 2.0 Key files
- Extending the TPM2 TSS stack to support authorized policy

Patch 14 implements the authorized policy support.

Patch 15 implements the missing NV index mode. (Thanks to Patrick Colp)

Patch 16 improves the 'cryptomount' command to fall back to the
passphrase mode when the key protector fails to unlock the encrypted
partition. (Another patch from Patrick Colp)

Patch 17 and 18 fix the potential security issues spotted by Fabian Vogt.

Patch 19 and 20 implement the TPM key unsealing testcases.

To utilize the TPM2 key protector to unlock the encrypted partition
(sdb1), here are the sample steps:

1. Add an extra random key for LUKS (luks-key)
   $ dd if=/dev/urandom of=luks-key bs=1 count=32
   $ sudo cryptsetup luksAddKey /dev/sdb1 luks-key --pbkdf=pbkdf2

2. Seal the key
   $ sudo grub-protect --action=add \
                       --protector=tpm2 \
                       --tpm2key \
                       --tpm2-keyfile=luks-key \
                       --tpm2-outfile=/boot/efi/boot/grub2/sealed.tpm

3. Unseal the key with the proper commands in grub.cfg:
   tpm2_key_protector_init --tpm2key=(hd0,gpt1)/boot/grub2/sealed.tpm
   cryptomount -u <SDB1_UUID> -P tpm2

(*1) https://lists.gnu.org/archive/html/grub-devel/2022-02/msg00006.html
(*2) https://www.hansenpartnership.com/draft-bottomley-tpm2-keys.html
(*3) https://lists.gnu.org/archive/html/grub-devel/2021-06/msg00044.html

v10:
- Fixing the coverity issues: CID 435775, CID 435771, CID 435770, CID
  435769, CID 435767, CID 435761
  https://lists.gnu.org/archive/html/grub-devel/2024-02/txtKIuUb5lf3O.txt
  - Fixing the potential memory leak (CID 435775)
  - Removing the unnecessary grub_protect_get_grub_drive_for_file() from
    util/grub-protect.c (CID 435771)
  - Using the grub_tpm2_mu_TPM2B_*_Unmarshal functions to unmarshal the
    TPM2B structs instead of a generic grub_tpm2_mu_TPM2B_Unmarshal
    (CID 435770)
  - Fixing Null pointer dereference (CID 435769)
  - Adding bound checks to grub_tpm2_mu_TPML_DIGEST_Unmarshal()
    (CID 435767)
  - Improving the check for the return value of ftell() (CID 435761)
- Adding a quick fix for CID 435762
- Removing the empty ending line in tests/asn1_test.in
- Fixing docs/grub-dev.texi and updating the libtasn1 patches in
  grub-core/lib/libtasn1-patches/
- Merging all the TPM2 TSS stack patches into one to reduce the total
  patch number
- Switching the default asymmetric algorithm from RSA2048 to
  TPM_ECC_NIST_P256 for the faster key generation
- Adding the fallback SRK templates to try a few more SRK types in case
  grub2 failed to associate the sealed key with the SRK in the persistent
  handle or the default SRK
- Improving the test script to add tests for the persistent handle and
  the fallback SRKs

v9:
- https://github.com/lcp/grub2/tree/tpm2-unlock-v9
- Introducing c-ctype.h to posix_wrap and implementing strncat
- Adding the descriptive comments to the disabled code in libtasn1
- Replacing strcat with the bound-checked _asn1_str_cat in libtasn1 and
  including c-ctype.h directly
- Integrating the asn1 testcases into "functional_test"
- Updating the libtasn1 patches mentioned in the documentation 
- Moving the key protector to a module
- Amending configure.ac to enable/disable grub-protect
- Fixing an timeout issue in the tpm2_test script by feeding the config
  through stdin

v8:
- https://lists.gnu.org/archive/html/grub-devel/2024-01/msg00013.html
- GIT repo: https://github.com/lcp/grub2/tree/tpm2-unlock-v8
- Introducing TPM device support to grub-emu and adding the TPM key
  unsealing testcase

v7:
- https://lists.gnu.org/archive/html/grub-devel/2023-11/msg00127.html
- GIT repo: https://github.com/lcp/grub2/tree/tpm2-unlock-v7
- Stopping reading SRK from the well-known persistent handle (TPM2_SRK_HANDLE,
  i.e. 0x81000001) by default since the persistent handle may be created
  by other OS and causes unsealing failure due to SRK mismatching
  - The user now has to specify the persistent handle with "--srk"
    explicitly.
- Utilizing grub_error() to print more error messages 
- Unifying the format of the error messages from TPM2 commands

v6:
- https://lists.gnu.org/archive/html/grub-devel/2023-10/msg00026.html
- GIT repo: https://github.com/lcp/grub2/tree/tpm2-unlock-v6
- Supporting more SRK types than RSA2048 and ECC_NIST_P256
- Documenting SHA512 as the supported PCR bank type in the tpm2
  protector
- Removing the redundant error message for grub_tpm2_protector_srk_get()
  since it may overwrite the real error message.
- Updating the supported SRK types and PCR bank types in grub-protect 
- Removing the unused type: TPM2_ECC_CURVE

v5:
- https://lists.gnu.org/archive/html/grub-devel/2023-08/msg00113.html
- GIT repo: https://github.com/lcp/grub2/tree/tpm2-unlock-v5
- Rebasing to the latest git HEAD and improving the commit messages
- Implementing authorized poilcy support
- Implementing NV index mode
- Improving the 'cryptomount' command to fall back to the passphrase
  mode when the key protector fails to unlock the encrypted partition
- Fixing the potential security issues

v4:
- https://lists.gnu.org/archive/html/grub-devel/2023-04/msg00104.html
- GIT repo: https://github.com/lcp/grub2/tree/tpm2-unlock-v4
- Improving the error condition checks in cryptodisk.c
- Moving the code to unseal with the standalone policy sequence below
  the code for authpolicy sequence
  - The standalone policy sequence was mistakenly prepended to to the
    authpolicy sequence with grub_list_push() while it should be
    appended.
- Pushing the error messages from the authpolicy sequence into the
  grub_error stack so that we can list all errors from the sequence
- Improving the error messages in the TPM2 protector
- Amending the calculation of the max string lengths of 'Policy',
  'CommandCode' and 'CommandPolicy'
- Skipping the error path in grub_tpm2key_get_authpolicy_seq() on
  success to avoid freeing the authpolicy sequence

v3:
- https://lists.gnu.org/archive/html/grub-devel/2023-04/msg00055.html
- GIT repo: https://github.com/lcp/grub2/tree/tpm2-unlock-v3
- Adding the document for libtasn1
- Improving the error condition checks
  ex: "if (!ptr)" ==> "if (ptr == NULL)"
      "if (err)" ==> "if (err != GRUB_ERR_NONE)"
      "if (rc)" ==> "if (rc != TPM_RC_SUCCESS)"
- Supporting the "TPMPolicy" and "TPMAuthPolicy" sequence in the TPM 2.0
  key File
- Refactoring the key recover function to support "TPMPolicy" and
  "TPMAuthPolicy" sequence
- Using TPMS_PCR_SELECTION_SelectPCR() to set the PCR bit mask
  - Also dropping TPM2_PCR_TO_SELECT() and TPM2_PCR_TO_BIT() which are
    not necessary anymore
- Removing the redundant variable, 'crd', from
  grub_cryptodisk_scan_device_real()
- Fixing the spaces/tabs in cryptodisk.c
- Fixing the comment format in cryptodisk.h
- Adding the defensive check for "cargs->protectors" in
  grub_cryptodisk_scan_device()
- Improving 'grub-protect' for the better support of TPM 2.0 Key File
- Adding more comments
v2:
- https://lists.gnu.org/archive/html/grub-devel/2023-03/msg00094.html
- GIT repo: https://github.com/lcp/grub2/tree/tpm2-unlock-v2
v1:
- https://lists.gnu.org/archive/html/grub-devel/2023-02/msg00130.html
- GIT repo: https://github.com/lcp/grub2/tree/tpm2-unlock

Daniel Axtens (6):
  posix_wrap: tweaks in preparation for libtasn1
  libtasn1: import libtasn1-4.19.0
  libtasn1: disable code not needed in grub
  libtasn1: changes for grub compatibility
  libtasn1: compile into asn1 module
  asn1_test: test module for libtasn1

Gary Lin (7):
  libtasn1: fix the potential buffer overrun
  libtasn1: Add the documentation
  tpm2: Support authorized policy
  cryptodisk: wipe out the cached keys from protectors
  diskfilter: look up cryptodisk devices first
  tpm2: Enable tpm2 module for grub-emu
  tests: Add tpm2_test

Hernan Gatta (5):
  key_protector: Add key protectors framework
  tpm2: Add TPM Software Stack (TSS)
  key_protector: Add TPM2 Key Protector
  cryptodisk: Support key protectors
  util/grub-protect: Add new tool

Patrick Colp (2):
  tpm2: Implement NV index
  cryptodisk: Fallback to passphrase

 .gitignore                                    |    2 +
 Makefile.util.def                             |   35 +
 configure.ac                                  |   30 +
 docs/grub-dev.texi                            |   28 +
 grub-core/Makefile.am                         |    1 +
 grub-core/Makefile.core.def                   |   48 +
 grub-core/disk/cryptodisk.c                   |  183 +-
 grub-core/disk/diskfilter.c                   |   35 +-
 grub-core/disk/key_protector.c                |   78 +
 grub-core/kern/emu/main.c                     |   11 +-
 grub-core/kern/emu/misc.c                     |   51 +
 ...asn1-disable-code-not-needed-in-grub.patch |  320 +++
 ...tasn1-changes-for-grub-compatibility.patch |  135 +
 ...sn1-fix-the-potential-buffer-overrun.patch |   35 +
 grub-core/lib/libtasn1/COPYING                |   16 +
 grub-core/lib/libtasn1/README.md              |   98 +
 grub-core/lib/libtasn1/lib/coding.c           | 1433 ++++++++++
 grub-core/lib/libtasn1/lib/decoding.c         | 2503 +++++++++++++++++
 grub-core/lib/libtasn1/lib/element.c          | 1109 ++++++++
 grub-core/lib/libtasn1/lib/element.h          |   42 +
 grub-core/lib/libtasn1/lib/errors.c           |  103 +
 grub-core/lib/libtasn1/lib/gstr.c             |   74 +
 grub-core/lib/libtasn1/lib/gstr.h             |   50 +
 grub-core/lib/libtasn1/lib/int.h              |  220 ++
 grub-core/lib/libtasn1/lib/parser_aux.c       | 1178 ++++++++
 grub-core/lib/libtasn1/lib/parser_aux.h       |  172 ++
 grub-core/lib/libtasn1/lib/structure.c        | 1227 ++++++++
 grub-core/lib/libtasn1/lib/structure.h        |   46 +
 grub-core/lib/libtasn1_wrap/wrap.c            |   26 +
 grub-core/lib/posix_wrap/c-ctype.h            |  114 +
 grub-core/lib/posix_wrap/limits.h             |    1 +
 grub-core/lib/posix_wrap/stdlib.h             |    8 +
 grub-core/lib/posix_wrap/string.h             |   21 +
 grub-core/lib/posix_wrap/sys/types.h          |    1 +
 .../tests/asn1/CVE-2018-1000654-1_asn1_tab.h  |   32 +
 .../tests/asn1/CVE-2018-1000654-2_asn1_tab.h  |   36 +
 grub-core/tests/asn1/CVE-2018-1000654.c       |   58 +
 grub-core/tests/asn1/Test_overflow.c          |  134 +
 grub-core/tests/asn1/Test_simple.c            |  205 ++
 grub-core/tests/asn1/Test_strings.c           |  142 +
 grub-core/tests/asn1/asn1_test.c              |   49 +
 grub-core/tests/asn1/asn1_test.h              |   44 +
 grub-core/tests/asn1/object-id-decoding.c     |  109 +
 grub-core/tests/asn1/object-id-encoding.c     |  114 +
 grub-core/tests/asn1/octet-string.c           |  199 ++
 grub-core/tests/asn1/reproducers.c            |   80 +
 grub-core/tests/lib/functional_test.c         |    1 +
 grub-core/tpm2/args.c                         |  175 ++
 grub-core/tpm2/buffer.c                       |  145 +
 grub-core/tpm2/module.c                       | 1313 +++++++++
 grub-core/tpm2/mu.c                           | 1150 ++++++++
 grub-core/tpm2/tcg2-emu.c                     |   52 +
 grub-core/tpm2/tcg2.c                         |  143 +
 grub-core/tpm2/tpm2.c                         | 1221 ++++++++
 grub-core/tpm2/tpm2key.asn                    |   31 +
 grub-core/tpm2/tpm2key.c                      |  447 +++
 grub-core/tpm2/tpm2key_asn1_tab.c             |   41 +
 include/grub/cryptodisk.h                     |   16 +
 include/grub/emu/misc.h                       |    5 +
 include/grub/key_protector.h                  |   46 +
 include/grub/libtasn1.h                       |  657 +++++
 include/grub/tpm2/buffer.h                    |   65 +
 include/grub/tpm2/internal/args.h             |   49 +
 include/grub/tpm2/internal/functions.h        |  178 ++
 include/grub/tpm2/internal/structs.h          |  768 +++++
 include/grub/tpm2/internal/types.h            |  406 +++
 include/grub/tpm2/mu.h                        |  396 +++
 include/grub/tpm2/tcg2.h                      |   34 +
 include/grub/tpm2/tpm2.h                      |   34 +
 include/grub/tpm2/tpm2key.h                   |   83 +
 tests/asn1_test.in                            |   11 +
 tests/tpm2_test.in                            |  284 ++
 tests/util/grub-shell.in                      |    6 +-
 util/grub-protect.c                           | 1396 +++++++++
 74 files changed, 19746 insertions(+), 43 deletions(-)
 create mode 100644 grub-core/disk/key_protector.c
 create mode 100644 
grub-core/lib/libtasn1-patches/0001-libtasn1-disable-code-not-needed-in-grub.patch
 create mode 100644 
grub-core/lib/libtasn1-patches/0002-libtasn1-changes-for-grub-compatibility.patch
 create mode 100644 
grub-core/lib/libtasn1-patches/0003-libtasn1-fix-the-potential-buffer-overrun.patch
 create mode 100644 grub-core/lib/libtasn1/COPYING
 create mode 100644 grub-core/lib/libtasn1/README.md
 create mode 100644 grub-core/lib/libtasn1/lib/coding.c
 create mode 100644 grub-core/lib/libtasn1/lib/decoding.c
 create mode 100644 grub-core/lib/libtasn1/lib/element.c
 create mode 100644 grub-core/lib/libtasn1/lib/element.h
 create mode 100644 grub-core/lib/libtasn1/lib/errors.c
 create mode 100644 grub-core/lib/libtasn1/lib/gstr.c
 create mode 100644 grub-core/lib/libtasn1/lib/gstr.h
 create mode 100644 grub-core/lib/libtasn1/lib/int.h
 create mode 100644 grub-core/lib/libtasn1/lib/parser_aux.c
 create mode 100644 grub-core/lib/libtasn1/lib/parser_aux.h
 create mode 100644 grub-core/lib/libtasn1/lib/structure.c
 create mode 100644 grub-core/lib/libtasn1/lib/structure.h
 create mode 100644 grub-core/lib/libtasn1_wrap/wrap.c
 create mode 100644 grub-core/lib/posix_wrap/c-ctype.h
 create mode 100644 grub-core/tests/asn1/CVE-2018-1000654-1_asn1_tab.h
 create mode 100644 grub-core/tests/asn1/CVE-2018-1000654-2_asn1_tab.h
 create mode 100644 grub-core/tests/asn1/CVE-2018-1000654.c
 create mode 100644 grub-core/tests/asn1/Test_overflow.c
 create mode 100644 grub-core/tests/asn1/Test_simple.c
 create mode 100644 grub-core/tests/asn1/Test_strings.c
 create mode 100644 grub-core/tests/asn1/asn1_test.c
 create mode 100644 grub-core/tests/asn1/asn1_test.h
 create mode 100644 grub-core/tests/asn1/object-id-decoding.c
 create mode 100644 grub-core/tests/asn1/object-id-encoding.c
 create mode 100644 grub-core/tests/asn1/octet-string.c
 create mode 100644 grub-core/tests/asn1/reproducers.c
 create mode 100644 grub-core/tpm2/args.c
 create mode 100644 grub-core/tpm2/buffer.c
 create mode 100644 grub-core/tpm2/module.c
 create mode 100644 grub-core/tpm2/mu.c
 create mode 100644 grub-core/tpm2/tcg2-emu.c
 create mode 100644 grub-core/tpm2/tcg2.c
 create mode 100644 grub-core/tpm2/tpm2.c
 create mode 100644 grub-core/tpm2/tpm2key.asn
 create mode 100644 grub-core/tpm2/tpm2key.c
 create mode 100644 grub-core/tpm2/tpm2key_asn1_tab.c
 create mode 100644 include/grub/key_protector.h
 create mode 100644 include/grub/libtasn1.h
 create mode 100644 include/grub/tpm2/buffer.h
 create mode 100644 include/grub/tpm2/internal/args.h
 create mode 100644 include/grub/tpm2/internal/functions.h
 create mode 100644 include/grub/tpm2/internal/structs.h
 create mode 100644 include/grub/tpm2/internal/types.h
 create mode 100644 include/grub/tpm2/mu.h
 create mode 100644 include/grub/tpm2/tcg2.h
 create mode 100644 include/grub/tpm2/tpm2.h
 create mode 100644 include/grub/tpm2/tpm2key.h
 create mode 100644 tests/asn1_test.in
 create mode 100644 tests/tpm2_test.in
 create mode 100644 util/grub-protect.c

Range-diff against v9:
 1:  e1b4dca2d =  1:  c1343113c posix_wrap: tweaks in preparation for libtasn1
 2:  89dc7ef87 =  2:  1c60bdbbe libtasn1: import libtasn1-4.19.0
 3:  07f7ff212 =  3:  715f65934 libtasn1: disable code not needed in grub
 4:  0113d1c12 =  4:  d13793c21 libtasn1: changes for grub compatibility
 -:  --------- >  5:  8f7c3c3b2 libtasn1: fix the potential buffer overrun
 5:  e5e4db9fc =  6:  8515ccc24 libtasn1: compile into asn1 module
 6:  a43b4a45e !  7:  24c129e64 asn1_test: test module for libtasn1
    @@ tests/asn1_test.in (new)
     +  echo "ASN.1 test failure: $out"
     +  exit 1
     +fi
    -+
 7:  3f1368c63 !  8:  7a1aced55 libtasn1: Add the documentation
    @@ Commit message
         Reviewed-by: Vladimir Serbinenko <phcoder@gmail.com>
     
      ## docs/grub-dev.texi ##
    +@@ docs/grub-dev.texi: to update it.
    + * Gnulib::
    + * jsmn::
    + * minilzo::
    ++* libtasn1::
    + @end menu
    + 
    + @node Gnulib
     @@ docs/grub-dev.texi: cp minilzo-2.10/*.[hc] grub-core/lib/minilzo
      rm -r minilzo-2.10*
      @end example
    @@ docs/grub-dev.texi: cp minilzo-2.10/*.[hc] grub-core/lib/minilzo
     +rm -r grub-core/lib/libtasn1/
     +mkdir libtasn1/lib
     +mkdir -p grub-core/lib/libtasn1/lib/
    -+cp libtasn1-4.19.0/{README.md,COPYING} grub-core/lib/libtasn1/
    -+cp 
libtasn1-4.19.0/lib/{coding.c,decoding.c,element.c,element.h,errors.c,gstr.c,gstr.h,int.h,parser_aux.c,parser_aux.h,structure.c,structure.h}
 grub-core/lib/libtasn1/lib/
    ++cp libtasn1-4.19.0/@lbracechar{}README.md,COPYING@rbracechar{} 
grub-core/lib/libtasn1/
    ++cp 
libtasn1-4.19.0/lib/@lbracechar{}coding.c,decoding.c,element.c,element.h,errors.c,gstr.c,gstr.h,int.h,parser_aux.c,parser_aux.h,structure.c,structure.h@rbracechar{}
 grub-core/lib/libtasn1/lib/
     +cp libtasn1-4.19.0/lib/includes/libtasn1.h include/grub/
     +rm -rf libtasn1-4.19.0
     +@end example
    @@ docs/grub-dev.texi: cp minilzo-2.10/*.[hc] grub-core/lib/minilzo
     
      ## 
grub-core/lib/libtasn1-patches/0001-libtasn1-disable-code-not-needed-in-grub.patch
 (new) ##
     @@
    -+From 210923227f4b366afa1104f62e82836587a8a753 Mon Sep 17 00:00:00 2001
    ++From 715f65934a120730316751536194ec5ed86aed9c Mon Sep 17 00:00:00 2001
     +From: Daniel Axtens <dja@axtens.net>
     +Date: Fri, 1 May 2020 17:12:23 +1000
    -+Subject: [PATCH 1/2] libtasn1: disable code not needed in grub
    ++Subject: [PATCH 1/3] libtasn1: disable code not needed in grub
     +
     +We don't expect to be able to write ASN.1, only read it,
     +so we can disable some code.
    @@ 
grub-core/lib/libtasn1-patches/0001-libtasn1-disable-code-not-needed-in-grub.pat
     +which is convenient because it means we don't have to
     +import it from gnulib.
     +
    ++Cc: Vladimir Serbinenko <phcoder@gmail.com>
     +Signed-off-by: Daniel Axtens <dja@axtens.net>
     +Signed-off-by: Gary Lin <glin@suse.com>
     +---
    @@ -411,12 +422,16 @@ extern "C"
     
      ## 
grub-core/lib/libtasn1-patches/0002-libtasn1-changes-for-grub-compatibility.patch
 (new) ##
     @@
    -+From 6ace81543a3c716a15ac92e825e90a5f949b9faf Mon Sep 17 00:00:00 2001
    ++From d13793c210999b256b46970b5f76d41a57e5c8fc Mon Sep 17 00:00:00 2001
     +From: Daniel Axtens <dja@axtens.net>
     +Date: Fri, 1 May 2020 20:44:29 +1000
    -+Subject: [PATCH 2/2] libtasn1: changes for grub compatibility
    ++Subject: [PATCH 2/3] libtasn1: changes for grub compatibility
     +
     +Do a few things to make libtasn1 compile as part of grub:
     +
    @@ 
grub-core/lib/libtasn1-patches/0002-libtasn1-changes-for-grub-compatibility.patc
     + - replace a 64 bit division with a call to grub_divmod64, preventing
     +   creation of __udivdi3 calls on 32 bit platforms.
     +
    ++Cc: Vladimir Serbinenko <phcoder@gmail.com>
     +Signed-off-by: Daniel Axtens <dja@axtens.net>
     +Signed-off-by: Gary Lin <glin@suse.com>
    -+
    -+libtasn1: get rid of strcat
    -+
    -+- Replace strcat and memcpy in _asn1_str_cat with strcpy and strncat
    -+- Replace strcat with the bound-checking _asn1_str_cat
    -+- Remove _asn1_strcat
    -+
    -+Signed-off-by: Gary Lin <glin@suse.com>
     +---
     + grub-core/lib/libtasn1/lib/decoding.c   | 8 ++++----
     + grub-core/lib/libtasn1/lib/element.c    | 2 +-
    @@ -54,9 +54,8 @@
     +-- 
     +2.35.3
     +
    +
    + ## 
grub-core/lib/libtasn1-patches/0003-libtasn1-fix-the-potential-buffer-overrun.patch
 (new) ##
    +@@
    ++From 8f7c3c3b28a312f77499159c52f313487fba0d08 Mon Sep 17 00:00:00 2001
    ++From: Gary Lin <glin@suse.com>
    ++Date: Mon, 8 Apr 2024 14:57:21 +0800
    ++Subject: [PATCH 3/3] libtasn1: fix the potential buffer overrun
    ++
    ++In _asn1_tag_der(), the first while loop for the long form may end up
    ++with a 'k' value with 'ASN1_MAX_TAG_SIZE' and cause the buffer overrun
    ++in the second while loop. This commit tweaks the conditional check to
    ++avoid producing a too large 'k'.
    ++
    ++This is a quick fix and may differ from the official upstream fix.
    ++
    ++libtasn1 issue: https://gitlab.com/gnutls/libtasn1/-/issues/49
    ++
    ++Signed-off-by: Gary Lin <glin@suse.com>
    ++---
    ++ grub-core/lib/libtasn1/lib/coding.c | 2 +-
    ++ 1 file changed, 1 insertion(+), 1 deletion(-)
    ++
    ++diff --git a/grub-core/lib/libtasn1/lib/coding.c 
b/grub-core/lib/libtasn1/lib/coding.c
    ++index 5d03bca9d..0458829a5 100644
    ++--- a/grub-core/lib/libtasn1/lib/coding.c
    +++++ b/grub-core/lib/libtasn1/lib/coding.c
    ++@@ -143,7 +143,7 @@ _asn1_tag_der (unsigned char class, unsigned int 
tag_value,
    ++    temp[k++] = tag_value & 0x7F;
    ++    tag_value >>= 7;
    ++ 
    ++-   if (k > ASN1_MAX_TAG_SIZE - 1)
    +++   if (k >= ASN1_MAX_TAG_SIZE - 1)
    ++      break;              /* will not encode larger tags */
    ++  }
    ++       *ans_len = k + 1;
    ++-- 
    ++2.35.3
    ++
 8:  b9282e8db =  9:  957b048f2 key_protector: Add key protectors framework
 9:  ad404454c ! 10:  ca024f496 tpm2: Add TPM Software Stack (TSS)
    @@ Commit message
     
         Functions: TPM2_Create, TPM2_CreatePrimary, TPM2_EvictControl,
         TPM2_FlushContext, TPM2_Load, TPM2_PCR_Read, TPM2_PolicyGetDigest,
    -    TPM2_PolicyPCR, TPM2_ReadPublic, TPM2_StartAuthSession, TPM2_Unseal.
    +    TPM2_PolicyPCR, TPM2_ReadPublic, TPM2_StartAuthSession, TPM2_Unseal,
    +    TPM2_LoadExternal, TPM2_HashSequenceStart, TPM2_SequenceUpdate,
    +    TPM2_SequenceComplete, TPM2_Hash, TPM2_VerifySignature,
    +    TPM2_PolicyAuthorize, TPM2_TestParms
     
         Signed-off-by: Hernan Gatta <hegatta@linux.microsoft.com>
         Signed-off-by: Gary Lin <glin@suse.com>
    @@ grub-core/tpm2/mu.c (new)
     +}
     +
     +void
    ++grub_tpm2_mu_TPMT_PUBLIC_PARMS_Marshal (grub_tpm2_buffer_t buffer,
    ++                                  const TPMT_PUBLIC_PARMS *p)
    ++{
    ++  grub_tpm2_buffer_pack_u16 (buffer, p->type);
    ++  grub_tpm2_mu_TPMU_PUBLIC_PARMS_Marshal (buffer, p->type, 
&p->parameters);
    ++}
    ++
    ++void
     +grub_tpm2_mu_TPMT_PUBLIC_Marshal (grub_tpm2_buffer_t buffer,
     +                            const TPMT_PUBLIC *p)
     +{
    @@ grub-core/tpm2/mu.c (new)
     +}
     +
     +void
    ++grub_tpm2_mu_TPMU_SENSITIVE_COMPOSITE_Marshal (grub_tpm2_buffer_t buffer,
    ++                                               const TPMI_ALG_PUBLIC type,
    ++                                               const 
TPMU_SENSITIVE_COMPOSITE *p)
    ++{
    ++  switch(type)
    ++    {
    ++    case TPM_ALG_RSA:
    ++      grub_tpm2_mu_TPM2B_Marshal (buffer, p->rsa.size, p->rsa.buffer);
    ++      break;
    ++    case TPM_ALG_ECC:
    ++      grub_tpm2_mu_TPM2B_Marshal (buffer, p->ecc.size, p->ecc.buffer);
    ++      break;
    ++    case TPM_ALG_KEYEDHASH:
    ++      grub_tpm2_mu_TPM2B_Marshal (buffer, p->bits.size, p->bits.buffer);
    ++      break;
    ++    case TPM_ALG_SYMCIPHER:
    ++      grub_tpm2_mu_TPM2B_Marshal (buffer, p->sym.size, p->sym.buffer);
    ++      break;
    ++    default:
    ++      buffer->error = 1;
    ++    }
    ++}
    ++
    ++void
    ++grub_tpm2_mu_TPMT_SENSITIVE_Marshal (grub_tpm2_buffer_t buffer,
    ++                                     const TPMT_SENSITIVE *p)
    ++{
    ++  grub_tpm2_buffer_pack_u16 (buffer, p->sensitiveType);
    ++  grub_tpm2_mu_TPM2B_Marshal (buffer, p->authValue.size, 
p->authValue.buffer);
    ++  grub_tpm2_mu_TPM2B_Marshal (buffer, p->seedValue.size, 
p->seedValue.buffer);
    ++  grub_tpm2_mu_TPMU_SENSITIVE_COMPOSITE_Marshal (buffer, p->sensitiveType,
    ++                                                 &p->sensitive);
    ++}
    ++
    ++void
    ++grub_tpm2_mu_TPM2B_SENSITIVE_Marshal (grub_tpm2_buffer_t buffer,
    ++                                      const TPM2B_SENSITIVE *p)
    ++{
    ++  grub_tpm2_buffer_pack_u16 (buffer, p->size);
    ++  grub_tpm2_mu_TPMT_SENSITIVE_Marshal (buffer, &p->sensitiveArea);
    ++}
    ++
    ++void
     +grub_tpm2_mu_TPM2B_SENSITIVE_CREATE_Marshal (grub_tpm2_buffer_t buffer,
     +                                       const TPM2B_SENSITIVE_CREATE 
*sensitiveCreate)
     +{
    @@ grub-core/tpm2/mu.c (new)
     +}
     +
     +void
    -+grub_tpm2_mu_TPM2B_Unmarshal (grub_tpm2_buffer_t buffer,
    -+                        TPM2B* p)
    ++grub_tpm2_mu_TPMS_SIGNATURE_RSA_Marshal (grub_tpm2_buffer_t buffer,
    ++                                         const TPMS_SIGNATURE_RSA *p)
    ++{
    ++  grub_tpm2_buffer_pack_u16 (buffer, p->hash);
    ++  grub_tpm2_mu_TPM2B_Marshal (buffer, p->sig.size, p->sig.buffer);
    ++}
    ++
    ++void
    ++grub_tpm2_mu_TPMS_SIGNATURE_ECC_Marshal (grub_tpm2_buffer_t buffer,
    ++                                         const TPMS_SIGNATURE_ECC *p)
    ++{
    ++  grub_tpm2_buffer_pack_u16 (buffer, p->hash);
    ++  grub_tpm2_mu_TPM2B_Marshal (buffer, p->signatureR.size, 
p->signatureR.buffer);
    ++  grub_tpm2_mu_TPM2B_Marshal (buffer, p->signatureS.size, 
p->signatureS.buffer);
    ++}
    ++
    ++void
    ++grub_tpm2_mu_TPMU_HA_Marshal (grub_tpm2_buffer_t buffer,
    ++                              const TPMI_ALG_HASH hashAlg,
    ++                              const TPMU_HA *p)
    ++{
    ++  switch (hashAlg)
    ++    {
    ++    case TPM_ALG_SHA1:
    ++      for (grub_uint16_t i = 0; i < TPM_SHA1_DIGEST_SIZE; i++)
    ++        grub_tpm2_buffer_pack_u8 (buffer, p->sha1[i]);
    ++      break;
    ++    case TPM_ALG_SHA256:
    ++      for (grub_uint16_t i = 0; i < TPM_SHA256_DIGEST_SIZE; i++)
    ++        grub_tpm2_buffer_pack_u8 (buffer, p->sha256[i]);
    ++      break;
    ++    case TPM_ALG_SHA384:
    ++      for (grub_uint16_t i = 0; i < TPM_SHA384_DIGEST_SIZE; i++)
    ++        grub_tpm2_buffer_pack_u8 (buffer, p->sha384[i]);
    ++      break;
    ++    case TPM_ALG_SHA512:
    ++      for (grub_uint16_t i = 0; i < TPM_SHA512_DIGEST_SIZE; i++)
    ++        grub_tpm2_buffer_pack_u8 (buffer, p->sha512[i]);
    ++      break;
    ++    default:
    ++      buffer->error = 1;
    ++      break;
    ++    }
    ++}
    ++
    ++void
    ++grub_tpm2_mu_TPMT_HA_Marshal (grub_tpm2_buffer_t buffer,
    ++                              const TPMT_HA *p)
    ++{
    ++  grub_tpm2_buffer_pack_u16 (buffer, p->hashAlg);
    ++  grub_tpm2_mu_TPMU_HA_Marshal (buffer, p->hashAlg, &p->digest);
    ++}
    ++
    ++void
    ++grub_tpm2_mu_TPMU_SIGNATURE_Marshal (grub_tpm2_buffer_t buffer,
    ++                                     const TPMI_ALG_SIG_SCHEME sigAlg,
    ++                                     const TPMU_SIGNATURE *p)
    ++{
    ++  switch (sigAlg)
    ++    {
    ++    case TPM_ALG_RSASSA:
    ++      grub_tpm2_mu_TPMS_SIGNATURE_RSA_Marshal (buffer, 
(TPMS_SIGNATURE_RSA *)&p->rsassa);
    ++      break;
    ++    case TPM_ALG_RSAPSS:
    ++      grub_tpm2_mu_TPMS_SIGNATURE_RSA_Marshal (buffer, 
(TPMS_SIGNATURE_RSA *)&p->rsapss);
    ++      break;
    ++    case TPM_ALG_ECDSA:
    ++      grub_tpm2_mu_TPMS_SIGNATURE_ECC_Marshal (buffer, 
(TPMS_SIGNATURE_ECC *)&p->ecdsa);
    ++      break;
    ++    case TPM_ALG_ECDAA:
    ++      grub_tpm2_mu_TPMS_SIGNATURE_ECC_Marshal (buffer, 
(TPMS_SIGNATURE_ECC *)&p->ecdaa);
    ++      break;
    ++    case TPM_ALG_SM2:
    ++      grub_tpm2_mu_TPMS_SIGNATURE_ECC_Marshal (buffer, 
(TPMS_SIGNATURE_ECC *)&p->sm2);
    ++      break;
    ++    case TPM_ALG_ECSCHNORR:
    ++      grub_tpm2_mu_TPMS_SIGNATURE_ECC_Marshal (buffer, 
(TPMS_SIGNATURE_ECC *)&p->ecschnorr);
    ++      break;
    ++    case TPM_ALG_HMAC:
    ++      grub_tpm2_mu_TPMT_HA_Marshal (buffer, &p->hmac);
    ++      break;
    ++    case TPM_ALG_NULL:
    ++      break;
    ++    default:
    ++      buffer->error = 1;
    ++      break;
    ++    }
    ++}
    ++
    ++void
    ++grub_tpm2_mu_TPMT_SIGNATURE_Marshal (grub_tpm2_buffer_t buffer,
    ++                                     const TPMT_SIGNATURE *p)
    ++{
    ++  grub_tpm2_buffer_pack_u16 (buffer, p->sigAlg);
    ++  grub_tpm2_mu_TPMU_SIGNATURE_Marshal (buffer, p->sigAlg, &p->signature);
    ++}
    ++
    ++void
    ++grub_tpm2_mu_TPMT_TK_VERIFIED_Marshal (grub_tpm2_buffer_t buffer,
    ++                                       const TPMT_TK_VERIFIED *p)
    ++{
    ++  grub_tpm2_buffer_pack_u16 (buffer, p->tag);
    ++  grub_tpm2_buffer_pack_u32 (buffer, p->hierarchy);
    ++  grub_tpm2_mu_TPM2B_Marshal (buffer, p->digest.size, p->digest.buffer);
    ++}
    ++
    ++static void
    ++__tpm2_mu_TPM2B_BUFFER_Unmarshal (grub_tpm2_buffer_t buffer,
    ++                            TPM2B* p, grub_uint16_t bound)
     +{
     +  grub_tpm2_buffer_unpack_u16 (buffer, &p->size);
     +
    -+  for (grub_uint16_t i = 0; i < p->size; i++)
    -+    grub_tpm2_buffer_unpack_u8 (buffer, &p->buffer[i]);
    ++  if (p->size > bound)
    ++    {
    ++      buffer->error = 1;
    ++      return;
    ++    }
    ++
    ++  grub_tpm2_buffer_unpack (buffer, &p->buffer, p->size);
     +}
     +
    ++#define TPM2B_BUFFER_UNMARSHAL(buffer, type, data) \
    ++  __tpm2_mu_TPM2B_BUFFER_Unmarshal(buffer, (TPM2B *)data, sizeof(type) - 
sizeof(grub_uint16_t))
    ++
     +void
     +grub_tpm2_mu_TPMS_AUTH_RESPONSE_Unmarshal (grub_tpm2_buffer_t buffer,
     +                                     TPMS_AUTH_RESPONSE* p)
    @@ grub-core/tpm2/mu.c (new)
     +grub_tpm2_mu_TPM2B_DIGEST_Unmarshal (grub_tpm2_buffer_t buffer,
     +                               TPM2B_DIGEST* digest)
     +{
    -+  grub_tpm2_mu_TPM2B_Unmarshal (buffer, (TPM2B*)digest);
    ++  TPM2B_BUFFER_UNMARSHAL (buffer, TPM2B_DIGEST, digest);
    ++}
    ++
    ++void
    ++grub_tpm2_mu_TPM2B_NONCE_Unmarshal (grub_tpm2_buffer_t buffer,
    ++                              TPM2B_NONCE* nonce)
    ++{
    ++  TPM2B_BUFFER_UNMARSHAL (buffer, TPM2B_NONCE, nonce);
    ++}
    ++
    ++void
    ++grub_tpm2_mu_TPM2B_DATA_Unmarshal (grub_tpm2_buffer_t buffer,
    ++                             TPM2B_DATA* data)
    ++{
    ++  TPM2B_BUFFER_UNMARSHAL (buffer, TPM2B_DATA, data);
    ++}
    ++
    ++void
    ++grub_tpm2_mu_TPMS_CREATION_DATA_Unmarshal (grub_tpm2_buffer_t buffer,
    ++                                     TPMS_CREATION_DATA *data)
    ++{
    ++  grub_tpm2_mu_TPML_PCR_SELECTION_Unmarshal (buffer, &data->pcrSelect);
    ++  grub_tpm2_mu_TPM2B_DIGEST_Unmarshal (buffer, &data->pcrDigest);
    ++  grub_tpm2_buffer_unpack_u8 (buffer, (grub_uint8_t *)&data->locality);
    ++  grub_tpm2_buffer_unpack_u16 (buffer, &data->parentNameAlg);
    ++  grub_tpm2_mu_TPM2B_NAME_Unmarshal (buffer, &data->parentName);
    ++  grub_tpm2_mu_TPM2B_NAME_Unmarshal (buffer, &data->parentQualifiedName);
    ++  grub_tpm2_mu_TPM2B_DATA_Unmarshal (buffer, &data->outsideInfo);
    ++}
    ++
    ++void
    ++grub_tpm2_mu_TPM2B_CREATION_DATA_Unmarshal (grub_tpm2_buffer_t buffer,
    ++                                      TPM2B_CREATION_DATA *data)
    ++{
    ++  grub_tpm2_buffer_unpack_u16 (buffer, &data->size);
    ++  grub_tpm2_mu_TPMS_CREATION_DATA_Unmarshal (buffer, &data->creationData);
    ++}
    ++
    ++void
    ++grub_tpm2_mu_TPM2B_PRIVATE_Unmarshal (grub_tpm2_buffer_t buffer,
    ++                                TPM2B_PRIVATE *private)
    ++{
    ++  TPM2B_BUFFER_UNMARSHAL (buffer, TPM2B_PRIVATE, private);
    ++}
    ++
    ++void
    ++grub_tpm2_mu_TPM2B_SENSITIVE_DATA_Unmarshal (grub_tpm2_buffer_t buffer,
    ++                                       TPM2B_SENSITIVE_DATA *data)
    ++{
    ++  TPM2B_BUFFER_UNMARSHAL (buffer, TPM2B_SENSITIVE_DATA, data);
    ++}
    ++
    ++void
    ++grub_tpm2_mu_TPM2B_PUBLIC_KEY_RSA_Unmarshal (grub_tpm2_buffer_t buffer,
    ++                                       TPM2B_PUBLIC_KEY_RSA *rsa)
    ++{
    ++  TPM2B_BUFFER_UNMARSHAL (buffer, TPM2B_PUBLIC_KEY_RSA, rsa);
    ++}
    ++
    ++void
    ++grub_tpm2_mu_TPM2B_ECC_PARAMETER_Unmarshal (grub_tpm2_buffer_t buffer,
    ++                                      TPM2B_ECC_PARAMETER *param)
    ++{
    ++  TPM2B_BUFFER_UNMARSHAL (buffer, TPM2B_ECC_PARAMETER, param);
     +}
     +
     +void
    @@ grub-core/tpm2/mu.c (new)
     +grub_tpm2_mu_TPMS_ECC_POINT_Unmarshal (grub_tpm2_buffer_t buffer,
     +                                 TPMS_ECC_POINT *p)
     +{
    -+  grub_tpm2_mu_TPM2B_Unmarshal (buffer, (TPM2B*) &p->x);
    -+  grub_tpm2_mu_TPM2B_Unmarshal (buffer, (TPM2B*) &p->y);
    ++  grub_tpm2_mu_TPM2B_ECC_PARAMETER_Unmarshal (buffer, &p->x);
    ++  grub_tpm2_mu_TPM2B_ECC_PARAMETER_Unmarshal (buffer, &p->y);
     +}
     +
     +void
    @@ grub-core/tpm2/mu.c (new)
     +  switch(type)
     +    {
     +    case TPM_ALG_KEYEDHASH:
    -+      grub_tpm2_mu_TPM2B_Unmarshal (buffer, (TPM2B*) &p->keyedHash);
    ++      grub_tpm2_mu_TPM2B_DIGEST_Unmarshal (buffer, &p->keyedHash);
     +      break;
     +    case TPM_ALG_SYMCIPHER:
    -+      grub_tpm2_mu_TPM2B_Unmarshal (buffer, (TPM2B*) &p->sym);
    ++      grub_tpm2_mu_TPM2B_DIGEST_Unmarshal (buffer, &p->sym);
     +      break;
     +    case TPM_ALG_RSA:
    -+      grub_tpm2_mu_TPM2B_Unmarshal (buffer, (TPM2B*) &p->rsa);
    ++      grub_tpm2_mu_TPM2B_PUBLIC_KEY_RSA_Unmarshal (buffer, &p->rsa);
     +      break;
     +    case TPM_ALG_ECC:
     +      grub_tpm2_mu_TPMS_ECC_POINT_Unmarshal (buffer, &p->ecc);
    @@ grub-core/tpm2/mu.c (new)
     +  grub_tpm2_buffer_unpack_u16 (buffer, &p->type);
     +  grub_tpm2_buffer_unpack_u16 (buffer, &p->nameAlg);
     +  grub_tpm2_mu_TPMA_OBJECT_Unmarshal (buffer, &p->objectAttributes);
    -+  grub_tpm2_mu_TPM2B_Unmarshal (buffer, (TPM2B*) &p->authPolicy);
    ++  grub_tpm2_mu_TPM2B_DIGEST_Unmarshal (buffer, &p->authPolicy);
     +  grub_tpm2_mu_TPMU_PUBLIC_PARMS_Unmarshal (buffer, p->type, 
&p->parameters);
     +  grub_tpm2_mu_TPMU_PUBLIC_ID_Unmarshal (buffer, p->type, &p->unique);
     +}
    @@ grub-core/tpm2/mu.c (new)
     +grub_tpm2_mu_TPM2B_NAME_Unmarshal (grub_tpm2_buffer_t buffer,
     +                             TPM2B_NAME *n)
     +{
    -+  grub_tpm2_buffer_unpack_u16 (buffer, &n->size);
    -+  grub_tpm2_buffer_unpack (buffer, n->name, n->size);
    ++  TPM2B_BUFFER_UNMARSHAL (buffer, TPM2B_NAME, n);
     +}
     +
     +void
    @@ grub-core/tpm2/mu.c (new)
     +}
     +
     +void
    -+grub_tpm2_mu_TPMS_CAPABILITY_DATA_tpmProperties_Unmarshal 
(grub_tpm2_buffer_t buffer,
    -+                                                     
TPMS_CAPABILITY_DATA* capabilityData)
    ++grub_tpm2_mu_TPMT_TK_CREATION_Unmarshal (grub_tpm2_buffer_t buffer,
    ++                                   TPMT_TK_CREATION *p)
     +{
    -+  grub_tpm2_buffer_unpack_u32 (buffer,
    -+                         &capabilityData->data.tpmProperties.count);
    -+
    -+  if (buffer->error)
    -+    return;
    ++  grub_tpm2_buffer_unpack_u16 (buffer, &p->tag);
    ++  grub_tpm2_buffer_unpack_u32 (buffer, &p->hierarchy);
    ++  grub_tpm2_mu_TPM2B_DIGEST_Unmarshal (buffer, &p->digest);
    ++}
     +
    -+  for (grub_uint32_t i = 0; i < capabilityData->data.tpmProperties.count; 
i++)
    -+    grub_tpm2_mu_TPMS_TAGGED_PROPERTY_Unmarshal (buffer,
    -+                                           
&capabilityData->data.tpmProperties.tpmProperty[i]);
    ++void
    ++grub_tpm2_mu_TPMT_TK_HASHCHECK_Unmarshal (grub_tpm2_buffer_t buffer,
    ++                                          TPMT_TK_HASHCHECK *p)
    ++{
    ++  grub_tpm2_buffer_unpack_u16 (buffer, &p->tag);
    ++  grub_tpm2_buffer_unpack_u32 (buffer, &p->hierarchy);
    ++  grub_tpm2_mu_TPM2B_DIGEST_Unmarshal (buffer, &p->digest);
     +}
     +
     +void
    -+grub_tpm2_mu_TPMT_TK_CREATION_Unmarshal (grub_tpm2_buffer_t buffer,
    -+                                   TPMT_TK_CREATION *p)
    ++grub_tpm2_mu_TPMT_TK_VERIFIED_Unmarshal (grub_tpm2_buffer_t buffer,
    ++                                         TPMT_TK_VERIFIED *p)
     +{
     +  grub_tpm2_buffer_unpack_u16 (buffer, &p->tag);
     +  grub_tpm2_buffer_unpack_u32 (buffer, &p->hierarchy);
    -+  grub_tpm2_mu_TPM2B_Unmarshal (buffer, (TPM2B*) &p->digest);
    ++  grub_tpm2_mu_TPM2B_DIGEST_Unmarshal (buffer, &p->digest);
     +}
     +
     +void
    -+grub_tpm2_mu_TPMS_PCR_SELECTION_Unmarshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMS_PCR_SELECTION_Unmarshal (grub_tpm2_buffer_t buffer,
     +                                     TPMS_PCR_SELECTION* pcrSelection)
     +{
    -+  grub_tpm2_buffer_unpack_u16 (buf, &pcrSelection->hash);
    -+  grub_tpm2_buffer_unpack_u8 (buf, &pcrSelection->sizeOfSelect);
    ++  grub_tpm2_buffer_unpack_u16 (buffer, &pcrSelection->hash);
    ++  grub_tpm2_buffer_unpack_u8 (buffer, &pcrSelection->sizeOfSelect);
    ++
    ++  if (pcrSelection->sizeOfSelect > TPM_PCR_SELECT_MAX)
    ++    {
    ++      buffer->error = 1;
    ++      return;
    ++    }
     +
     +  for (grub_uint32_t i = 0; i < pcrSelection->sizeOfSelect; i++)
    -+    grub_tpm2_buffer_unpack_u8 (buf, &pcrSelection->pcrSelect[i]);
    ++    grub_tpm2_buffer_unpack_u8 (buffer, &pcrSelection->pcrSelect[i]);
     +}
     +
     +void
    -+grub_tpm2_mu_TPML_PCR_SELECTION_Unmarshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPML_PCR_SELECTION_Unmarshal (grub_tpm2_buffer_t buffer,
     +                                     TPML_PCR_SELECTION* pcrSelection)
     +{
    -+  grub_tpm2_buffer_unpack_u32 (buf, &pcrSelection->count);
    ++  grub_tpm2_buffer_unpack_u32 (buffer, &pcrSelection->count);
    ++
    ++  if (pcrSelection->count > TPM_NUM_PCR_BANKS)
    ++    {
    ++      buffer->error = 1;
    ++      return;
    ++    }
     +
     +  for (grub_uint32_t i = 0; i < pcrSelection->count; i++)
    -+    grub_tpm2_mu_TPMS_PCR_SELECTION_Unmarshal (buf, 
&pcrSelection->pcrSelections[i]);
    ++    grub_tpm2_mu_TPMS_PCR_SELECTION_Unmarshal (buffer, 
&pcrSelection->pcrSelections[i]);
     +}
     +
     +void
    -+grub_tpm2_mu_TPML_DIGEST_Unmarshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPML_DIGEST_Unmarshal (grub_tpm2_buffer_t buffer,
     +                              TPML_DIGEST* digest)
     +{
    -+  grub_tpm2_buffer_unpack_u32 (buf, &digest->count);
    ++  grub_tpm2_buffer_unpack_u32 (buffer, &digest->count);
    ++
    ++  if (digest->count > 8)
    ++    {
    ++      buffer->error = 1;
    ++      return;
    ++    }
     +
     +  for (grub_uint32_t i = 0; i < digest->count; i++)
    -+    grub_tpm2_mu_TPM2B_DIGEST_Unmarshal (buf, &digest->digests[i]);
    ++    grub_tpm2_mu_TPM2B_DIGEST_Unmarshal (buffer, &digest->digests[i]);
    ++}
    ++
    ++void
    ++grub_tpm2_mu_TPMS_SIGNATURE_RSA_Unmarshal (grub_tpm2_buffer_t buffer,
    ++                                           TPMS_SIGNATURE_RSA *rsa)
    ++{
    ++  grub_tpm2_buffer_unpack_u16 (buffer, &rsa->hash);
    ++  grub_tpm2_mu_TPM2B_PUBLIC_KEY_RSA_Unmarshal (buffer, &rsa->sig);
    ++}
    ++
    ++void
    ++grub_tpm2_mu_TPMS_SIGNATURE_ECC_Unmarshal (grub_tpm2_buffer_t buffer,
    ++                                           TPMS_SIGNATURE_ECC *ecc)
    ++{
    ++  grub_tpm2_buffer_unpack_u16 (buffer, &ecc->hash);
    ++  grub_tpm2_mu_TPM2B_ECC_PARAMETER_Unmarshal (buffer, &ecc->signatureR);
    ++  grub_tpm2_mu_TPM2B_ECC_PARAMETER_Unmarshal (buffer, &ecc->signatureS);
    ++}
    ++
    ++void
    ++grub_tpm2_mu_TPMU_HA_Unmarshal (grub_tpm2_buffer_t buffer,
    ++                                TPMI_ALG_HASH hashAlg,
    ++                                TPMU_HA *p)
    ++{
    ++  switch (hashAlg)
    ++    {
    ++    case TPM_ALG_SHA1:
    ++      grub_tpm2_buffer_unpack (buffer, &p->sha1, TPM_SHA1_DIGEST_SIZE);
    ++      break;
    ++    case TPM_ALG_SHA256:
    ++      grub_tpm2_buffer_unpack (buffer, &p->sha256, 
TPM_SHA256_DIGEST_SIZE);
    ++      break;
    ++    case TPM_ALG_SHA384:
    ++      grub_tpm2_buffer_unpack (buffer, &p->sha384, 
TPM_SHA384_DIGEST_SIZE);
    ++      break;
    ++    case TPM_ALG_SHA512:
    ++      grub_tpm2_buffer_unpack (buffer, &p->sha512, 
TPM_SHA512_DIGEST_SIZE);
    ++      break;
    ++    default:
    ++      buffer->error = 1;
    ++      break;
    ++    }
    ++}
    ++
    ++void
    ++grub_tpm2_mu_TPMT_HA_Unmarshal (grub_tpm2_buffer_t buffer,
    ++                                TPMT_HA *p)
    ++{
    ++  grub_tpm2_buffer_unpack_u16 (buffer, &p->hashAlg);
    ++  grub_tpm2_mu_TPMU_HA_Unmarshal (buffer, p->hashAlg, &p->digest);
    ++}
    ++
    ++void
    ++grub_tpm2_mu_TPMU_SIGNATURE_Unmarshal (grub_tpm2_buffer_t buffer,
    ++                                       TPMI_ALG_SIG_SCHEME sigAlg,
    ++                                       TPMU_SIGNATURE *p)
    ++{
    ++  switch (sigAlg)
    ++    {
    ++    case TPM_ALG_RSASSA:
    ++      grub_tpm2_mu_TPMS_SIGNATURE_RSA_Unmarshal (buffer, 
(TPMS_SIGNATURE_RSA *)&p->rsassa);
    ++      break;
    ++    case TPM_ALG_RSAPSS:
    ++      grub_tpm2_mu_TPMS_SIGNATURE_RSA_Unmarshal (buffer, 
(TPMS_SIGNATURE_RSA *)&p->rsapss);
    ++      break;
    ++    case TPM_ALG_ECDSA:
    ++      grub_tpm2_mu_TPMS_SIGNATURE_ECC_Unmarshal (buffer, 
(TPMS_SIGNATURE_ECC *)&p->ecdsa);
    ++      break;
    ++    case TPM_ALG_ECDAA:
    ++      grub_tpm2_mu_TPMS_SIGNATURE_ECC_Unmarshal (buffer, 
(TPMS_SIGNATURE_ECC *)&p->ecdaa);
    ++      break;
    ++    case TPM_ALG_SM2:
    ++      grub_tpm2_mu_TPMS_SIGNATURE_ECC_Unmarshal (buffer, 
(TPMS_SIGNATURE_ECC *)&p->sm2);
    ++      break;
    ++    case TPM_ALG_ECSCHNORR:
    ++      grub_tpm2_mu_TPMS_SIGNATURE_ECC_Unmarshal (buffer, 
(TPMS_SIGNATURE_ECC *)&p->ecschnorr);
    ++      break;
    ++    case TPM_ALG_HMAC:
    ++      grub_tpm2_mu_TPMT_HA_Unmarshal (buffer, &p->hmac);
    ++      break;
    ++    case TPM_ALG_NULL:
    ++      break;
    ++    default:
    ++      buffer->error = 1;
    ++      break;
    ++    }
    ++}
    ++
    ++void
    ++grub_tpm2_mu_TPMT_SIGNATURE_Unmarshal (grub_tpm2_buffer_t buffer,
    ++                                       TPMT_SIGNATURE *p)
    ++{
    ++  grub_tpm2_buffer_unpack_u16 (buffer, &p->sigAlg);
    ++  grub_tpm2_mu_TPMU_SIGNATURE_Unmarshal (buffer, p->sigAlg, 
&p->signature);
     +}
     
      ## grub-core/tpm2/tcg2.c (new) ##
    @@ grub-core/tpm2/tpm2.c (new)
     +  if (err)
     +    return TPM_RC_FAILURE;
     +
    -+  /* Unmarshal*/
    ++  /* Unmarshal */
     +  out->size = sizeof (grub_uint16_t) + sizeof (grub_uint32_t) +
     +        sizeof (grub_uint32_t);
     +  grub_tpm2_buffer_unpack_u16 (out, &tag_out);
    @@ grub-core/tpm2/tpm2.c (new)
     +  if (responseCode != TPM_RC_SUCCESS)
     +    return responseCode;
     +
    -+  /* Unmarshal*/
    ++  /* Unmarshal */
     +  grub_tpm2_buffer_unpack_u32 (&out, objectHandle);
     +  if (tag == TPM_ST_SESSIONS)
     +    grub_tpm2_buffer_unpack_u32 (&out, &parameterSize);
     +  grub_tpm2_mu_TPM2B_PUBLIC_Unmarshal (&out, outPublic);
    -+  grub_tpm2_mu_TPM2B_Unmarshal (&out, (TPM2B*)creationData);
    -+  grub_tpm2_mu_TPM2B_Unmarshal (&out, (TPM2B*)creationHash);
    ++  grub_tpm2_mu_TPM2B_CREATION_DATA_Unmarshal (&out, creationData);
    ++  grub_tpm2_mu_TPM2B_DIGEST_Unmarshal (&out, creationHash);
     +  grub_tpm2_mu_TPMT_TK_CREATION_Unmarshal (&out, creationTicket);
    -+  grub_tpm2_mu_TPM2B_Unmarshal (&out, (TPM2B*)name);
    ++  grub_tpm2_mu_TPM2B_NAME_Unmarshal (&out, name);
     +  if (tag == TPM_ST_SESSIONS)
     +    grub_tpm2_mu_TPMS_AUTH_RESPONSE_Unmarshal (&out, authResponse);
     +  if (out.error)
    @@ grub-core/tpm2/tpm2.c (new)
     +  if (responseCode != TPM_RC_SUCCESS)
     +    return responseCode;
     +
    -+  /* Unmarshal*/
    ++  /* Unmarshal */
     +  grub_tpm2_buffer_unpack_u32 (&out, sessionHandle);
     +  if (tag == TPM_ST_SESSIONS)
     +    grub_tpm2_buffer_unpack_u32 (&out, &param_size);
    -+  grub_tpm2_mu_TPM2B_Unmarshal (&out, (TPM2B*)nonceTpm);
    ++  grub_tpm2_mu_TPM2B_NONCE_Unmarshal (&out, nonceTpm);
     +  if (tag == TPM_ST_SESSIONS)
     +    grub_tpm2_mu_TPMS_AUTH_RESPONSE_Unmarshal (&out, authResponse);
     +  if (out.error)
    @@ grub-core/tpm2/tpm2.c (new)
     +  if (responseCode != TPM_RC_SUCCESS)
     +    return responseCode;
     +
    -+  /* Unmarshal*/
    ++  /* Unmarshal */
     +  if (tag == TPM_ST_SESSIONS)
     +    grub_tpm2_buffer_unpack_u32 (&out, &parameterSize);
     +  grub_tpm2_mu_TPM2B_PUBLIC_Unmarshal (&out, outPublic);
    @@ grub-core/tpm2/tpm2.c (new)
     +  if (responseCode != TPM_RC_SUCCESS)
     +    return responseCode;
     +
    -+  /* Unmarshal*/
    ++  /* Unmarshal */
     +  grub_tpm2_buffer_unpack_u32 (&out, objectHandle);
     +  if (tag == TPM_ST_SESSIONS)
     +    grub_tpm2_buffer_unpack_u32 (&out, &param_size);
    -+  grub_tpm2_mu_TPM2B_Unmarshal (&out, (TPM2B*)name);
    ++  grub_tpm2_mu_TPM2B_NAME_Unmarshal (&out, name);
     +  if (tag == TPM_ST_SESSIONS)
     +    grub_tpm2_mu_TPMS_AUTH_RESPONSE_Unmarshal (&out, authResponse);
     +  if (out.error)
    @@ grub-core/tpm2/tpm2.c (new)
     +}
     +
     +TPM_RC
    -+TPM2_Unseal (const TPMI_DH_OBJECT itemHandle,
    -+       const TPMS_AUTH_COMMAND *authCommand,
    -+       TPM2B_SENSITIVE_DATA *outData,
    -+       TPMS_AUTH_RESPONSE *authResponse)
    ++TPM2_LoadExternal (const TPMS_AUTH_COMMAND *authCommand,
    ++                   const TPM2B_SENSITIVE *inPrivate,
    ++                   const TPM2B_PUBLIC *inPublic,
    ++                   const TPMI_RH_HIERARCHY hierarchy,
    ++                   TPM_HANDLE *objectHandle,
    ++                   TPM2B_NAME *name,
    ++                   TPMS_AUTH_RESPONSE *authResponse)
     +{
     +  TPM_RC rc;
     +  struct grub_tpm2_buffer in;
     +  struct grub_tpm2_buffer out;
    -+  TPM2B_SENSITIVE_DATA outDataTmp;
    ++  TPM_HANDLE objectHandleTmp;
    ++  TPM2B_NAME nameTmp;
     +  TPMS_AUTH_RESPONSE authResponseTmp;
     +  TPMI_ST_COMMAND_TAG tag = authCommand ? TPM_ST_SESSIONS : 
TPM_ST_NO_SESSIONS;
     +  TPM_RC responseCode;
     +  grub_uint32_t param_size;
     +
    -+  if (!outData)
    -+    outData = &outDataTmp;
    ++  if (!inPublic)
    ++    return TPM_RC_VALUE;
    ++
    ++  if (!objectHandle)
    ++    objectHandle = &objectHandleTmp;
    ++  if (!name)
    ++    name = &nameTmp;
     +  if (!authResponse)
     +    authResponse = &authResponseTmp;
     +
    -+  grub_memset (outData, 0, sizeof (*outData));
    ++  grub_memset (objectHandle, 0, sizeof (*objectHandle));
    ++  grub_memset (name, 0, sizeof (*name));
     +  grub_memset (authResponse, 0, sizeof (*authResponse));
     +
     +  /* Marshal */
     +  grub_tpm2_buffer_init (&in);
    -+  grub_tpm2_buffer_pack_u32 (&in, itemHandle);
     +  if (authCommand)
     +    grub_tpm2_mu_TPMS_AUTH_COMMAND_Marshal (&in, authCommand);
    ++  if (inPrivate)
    ++    grub_tpm2_mu_TPM2B_SENSITIVE_Marshal (&in, inPrivate);
    ++  else
    ++    grub_tpm2_buffer_pack_u16 (&in, 0);
    ++  grub_tpm2_mu_TPM2B_PUBLIC_Marshal (&in, inPublic);
    ++  grub_tpm2_buffer_pack_u32 (&in, hierarchy);
     +  if (in.error)
     +    return TPM_RC_FAILURE;
     +
     +  /* Submit */
     +  grub_tpm2_buffer_init (&out);
    -+  rc = grub_tpm2_submit_command (tag, TPM_CC_Unseal, &responseCode, &in, 
&out);
    ++  rc = grub_tpm2_submit_command (tag, TPM_CC_LoadExternal, &responseCode, 
&in, &out);
     +  if (rc != TPM_RC_SUCCESS)
     +    return rc;
     +  if (responseCode != TPM_RC_SUCCESS)
     +    return responseCode;
     +
    -+  // Unmarhsal
    ++  /* Unmarshal */
    ++  grub_tpm2_buffer_unpack_u32 (&out, objectHandle);
     +  if (tag == TPM_ST_SESSIONS)
     +    grub_tpm2_buffer_unpack_u32 (&out, &param_size);
    -+  grub_tpm2_mu_TPM2B_Unmarshal (&out, (TPM2B*)outData);
    ++  grub_tpm2_mu_TPM2B_NAME_Unmarshal (&out, name);
     +  if (tag == TPM_ST_SESSIONS)
     +    grub_tpm2_mu_TPMS_AUTH_RESPONSE_Unmarshal (&out, authResponse);
     +  if (out.error)
    @@ grub-core/tpm2/tpm2.c (new)
     +}
     +
     +TPM_RC
    -+TPM2_FlushContext (const TPMI_DH_CONTEXT handle)
    ++TPM2_Unseal (const TPMI_DH_OBJECT itemHandle,
    ++       const TPMS_AUTH_COMMAND *authCommand,
    ++       TPM2B_SENSITIVE_DATA *outData,
    ++       TPMS_AUTH_RESPONSE *authResponse)
     +{
     +  TPM_RC rc;
     +  struct grub_tpm2_buffer in;
     +  struct grub_tpm2_buffer out;
    ++  TPM2B_SENSITIVE_DATA outDataTmp;
    ++  TPMS_AUTH_RESPONSE authResponseTmp;
    ++  TPMI_ST_COMMAND_TAG tag = authCommand ? TPM_ST_SESSIONS : 
TPM_ST_NO_SESSIONS;
     +  TPM_RC responseCode;
    ++  grub_uint32_t param_size;
    ++
    ++  if (!outData)
    ++    outData = &outDataTmp;
    ++  if (!authResponse)
    ++    authResponse = &authResponseTmp;
    ++
    ++  grub_memset (outData, 0, sizeof (*outData));
    ++  grub_memset (authResponse, 0, sizeof (*authResponse));
     +
     +  /* Marshal */
     +  grub_tpm2_buffer_init (&in);
    -+  grub_tpm2_buffer_pack_u32 (&in, handle);
    ++  grub_tpm2_buffer_pack_u32 (&in, itemHandle);
    ++  if (authCommand)
    ++    grub_tpm2_mu_TPMS_AUTH_COMMAND_Marshal (&in, authCommand);
     +  if (in.error)
     +    return TPM_RC_FAILURE;
     +
     +  /* Submit */
     +  grub_tpm2_buffer_init (&out);
    -+  rc = grub_tpm2_submit_command (TPM_ST_NO_SESSIONS, TPM_CC_FlushContext,
    -+                           &responseCode, &in, &out);
    ++  rc = grub_tpm2_submit_command (tag, TPM_CC_Unseal, &responseCode, &in, 
&out);
     +  if (rc != TPM_RC_SUCCESS)
     +    return rc;
     +  if (responseCode != TPM_RC_SUCCESS)
     +    return responseCode;
     +
    -+  /* Unmarshal*/
    ++  /* Unmarshal */
    ++  if (tag == TPM_ST_SESSIONS)
    ++    grub_tpm2_buffer_unpack_u32 (&out, &param_size);
    ++  grub_tpm2_mu_TPM2B_SENSITIVE_DATA_Unmarshal (&out, outData);
    ++  if (tag == TPM_ST_SESSIONS)
    ++    grub_tpm2_mu_TPMS_AUTH_RESPONSE_Unmarshal (&out, authResponse);
    ++  if (out.error)
    ++    return TPM_RC_FAILURE;
    ++
    ++  return TPM_RC_SUCCESS;
    ++}
    ++
    ++TPM_RC
    ++TPM2_FlushContext (const TPMI_DH_CONTEXT handle)
    ++{
    ++  TPM_RC rc;
    ++  struct grub_tpm2_buffer in;
    ++  struct grub_tpm2_buffer out;
    ++  TPM_RC responseCode;
    ++
    ++  /* Marshal */
    ++  grub_tpm2_buffer_init (&in);
    ++  grub_tpm2_buffer_pack_u32 (&in, handle);
    ++  if (in.error)
    ++    return TPM_RC_FAILURE;
    ++
    ++  /* Submit */
    ++  grub_tpm2_buffer_init (&out);
    ++  rc = grub_tpm2_submit_command (TPM_ST_NO_SESSIONS, TPM_CC_FlushContext,
    ++                           &responseCode, &in, &out);
    ++  if (rc != TPM_RC_SUCCESS)
    ++    return rc;
    ++  if (responseCode != TPM_RC_SUCCESS)
    ++    return responseCode;
    ++
    ++  /* Unmarshal */
     +  if (out.error)
     +    return TPM_RC_FAILURE;
     +
    @@ grub-core/tpm2/tpm2.c (new)
     +  if (responseCode != TPM_RC_SUCCESS)
     +    return responseCode;
     +
    -+  /* Unmarshal*/
    ++  /* Unmarshal */
     +  if (tag == TPM_ST_SESSIONS)
     +    grub_tpm2_buffer_unpack_u32 (&out, &parameterSize);
     +  grub_tpm2_buffer_unpack_u32 (&out, pcrUpdateCounter);
    @@ grub-core/tpm2/tpm2.c (new)
     +  struct grub_tpm2_buffer in;
     +  struct grub_tpm2_buffer out;
     +  TPMS_AUTH_RESPONSE authResponseTmp;
    -+  TPM2B_DIGEST policyDigestTmp;
    ++  TPM2B_DIGEST policyDigestTmp;
    ++  TPMI_ST_COMMAND_TAG tag = authCommand ? TPM_ST_SESSIONS : 
TPM_ST_NO_SESSIONS;
    ++  TPM_RC responseCode;
    ++  grub_uint32_t parameterSize;
    ++
    ++  if (!authResponse)
    ++    authResponse = &authResponseTmp;
    ++  if (!policyDigest)
    ++    policyDigest = &policyDigestTmp;
    ++
    ++  grub_memset (authResponse, 0, sizeof (*authResponse));
    ++  grub_memset (policyDigest, 0, sizeof (*policyDigest));
    ++
    ++  /* Submit */
    ++  grub_tpm2_buffer_init (&in);
    ++  grub_tpm2_buffer_pack_u32 (&in, policySession);
    ++  if (tag == TPM_ST_SESSIONS)
    ++    grub_tpm2_mu_TPMS_AUTH_COMMAND_Marshal (&in, authCommand);
    ++  if (in.error)
    ++    return TPM_RC_FAILURE;
    ++
    ++  /* Submit */
    ++  grub_tpm2_buffer_init (&out);
    ++  rc = grub_tpm2_submit_command (tag, TPM_CC_PolicyGetDigest, 
&responseCode,
    ++                           &in, &out);
    ++  if (rc != TPM_RC_SUCCESS)
    ++    return rc;
    ++  if (responseCode != TPM_RC_SUCCESS)
    ++    return responseCode;
    ++
    ++  /* Unmarshal */
    ++  if (tag == TPM_ST_SESSIONS)
    ++    grub_tpm2_buffer_unpack_u32 (&out, &parameterSize);
    ++  grub_tpm2_mu_TPM2B_DIGEST_Unmarshal (&out, policyDigest);
    ++  if (tag == TPM_ST_SESSIONS)
    ++    grub_tpm2_mu_TPMS_AUTH_RESPONSE_Unmarshal (&out, authResponse);
    ++  if (out.error)
    ++    return TPM_RC_FAILURE;
    ++
    ++  return TPM_RC_SUCCESS;
    ++}
    ++
    ++TPM_RC
    ++TPM2_Create (const TPMI_DH_OBJECT parentHandle,
    ++       const TPMS_AUTH_COMMAND *authCommand,
    ++       const TPM2B_SENSITIVE_CREATE *inSensitive,
    ++       const TPM2B_PUBLIC *inPublic,
    ++       const TPM2B_DATA *outsideInfo,
    ++       const TPML_PCR_SELECTION *creationPCR,
    ++       TPM2B_PRIVATE *outPrivate,
    ++       TPM2B_PUBLIC *outPublic,
    ++       TPM2B_CREATION_DATA *creationData,
    ++       TPM2B_DIGEST *creationHash,
    ++       TPMT_TK_CREATION *creationTicket,
    ++       TPMS_AUTH_RESPONSE *authResponse)
    ++{
    ++  struct grub_tpm2_buffer in;
    ++  struct grub_tpm2_buffer out;
    ++  TPM2B_PUBLIC outPublicTmp;
    ++  TPM2B_PRIVATE outPrivateTmp;
    ++  TPM2B_CREATION_DATA creationDataTmp;
    ++  TPM2B_DIGEST creationHashTmp;
    ++  TPMT_TK_CREATION creationTicketTmp;
    ++  TPMS_AUTH_RESPONSE authResponseTmp;
    ++  TPMI_ST_COMMAND_TAG tag = authCommand ? 
TPM_ST_SESSIONS:TPM_ST_NO_SESSIONS;
    ++  TPM_RC responseCode;
    ++  TPM_RC rc;
    ++  grub_uint32_t parameterSize;
    ++
    ++  if (!inSensitive || !inPublic || !outsideInfo || !creationPCR)
    ++    return TPM_RC_VALUE;
    ++
    ++  if (!outPrivate)
    ++    outPrivate = &outPrivateTmp;
    ++  if (!outPublic)
    ++    outPublic = &outPublicTmp;
    ++  if (!creationData)
    ++    creationData = &creationDataTmp;
    ++  if (!creationHash)
    ++    creationHash = &creationHashTmp;
    ++  if (!creationTicket)
    ++    creationTicket = &creationTicketTmp;
    ++  if (!authResponse)
    ++    authResponse = &authResponseTmp;
    ++
    ++  grub_memset (outPrivate, 0, sizeof (*outPrivate));
    ++  grub_memset (outPublic, 0, sizeof (*outPublic));
    ++  grub_memset (creationData, 0, sizeof (*creationData));
    ++  grub_memset (creationHash, 0, sizeof (*creationHash));
    ++  grub_memset (creationTicket, 0, sizeof (*creationTicket));
    ++  grub_memset (authResponse, 0, sizeof (*authResponse));
    ++
    ++  /* Marshal */
    ++  grub_tpm2_buffer_init (&in);
    ++  grub_tpm2_buffer_pack_u32 (&in, parentHandle);
    ++  if (authCommand)
    ++    grub_tpm2_mu_TPMS_AUTH_COMMAND_Marshal (&in, authCommand);
    ++  grub_tpm2_mu_TPM2B_SENSITIVE_CREATE_Marshal (&in, inSensitive);
    ++  grub_tpm2_mu_TPM2B_PUBLIC_Marshal (&in, inPublic);
    ++  grub_tpm2_mu_TPM2B_Marshal (&in, outsideInfo->size, 
outsideInfo->buffer);
    ++  grub_tpm2_mu_TPML_PCR_SELECTION_Marshal (&in, creationPCR);
    ++  if (in.error)
    ++    return TPM_RC_FAILURE;
    ++
    ++  /* Submit */
    ++  grub_tpm2_buffer_init (&out);
    ++  rc = grub_tpm2_submit_command (tag, TPM_CC_Create, &responseCode, &in,
    ++                           &out);
    ++  if (rc != TPM_RC_SUCCESS)
    ++    return rc;
    ++  if (responseCode != TPM_RC_SUCCESS)
    ++    return responseCode;
    ++
    ++  /* Unmarshal */
    ++  if (tag == TPM_ST_SESSIONS)
    ++   grub_tpm2_buffer_unpack_u32 (&out, &parameterSize);
    ++  grub_tpm2_mu_TPM2B_PRIVATE_Unmarshal (&out, outPrivate);
    ++  grub_tpm2_mu_TPM2B_PUBLIC_Unmarshal (&out, outPublic);
    ++  grub_tpm2_mu_TPM2B_CREATION_DATA_Unmarshal (&out, creationData);
    ++  grub_tpm2_mu_TPM2B_DIGEST_Unmarshal (&out, creationHash);
    ++  grub_tpm2_mu_TPMT_TK_CREATION_Unmarshal (&out, creationTicket);
    ++  if (tag == TPM_ST_SESSIONS)
    ++    grub_tpm2_mu_TPMS_AUTH_RESPONSE_Unmarshal(&out, authResponse);
    ++  if (out.error)
    ++    return TPM_RC_FAILURE;
    ++
    ++  return TPM_RC_SUCCESS;
    ++}
    ++
    ++TPM_RC
    ++TPM2_EvictControl (const TPMI_RH_PROVISION auth,
    ++             const TPMI_DH_OBJECT objectHandle,
    ++             const TPMS_AUTH_COMMAND *authCommand,
    ++             const TPMI_DH_PERSISTENT persistentHandle,
    ++             TPMS_AUTH_RESPONSE *authResponse)
    ++{
    ++  struct grub_tpm2_buffer in;
    ++  struct grub_tpm2_buffer out;
    ++  TPMS_AUTH_RESPONSE authResponseTmp;
    ++  TPMI_ST_COMMAND_TAG tag = authCommand ? TPM_ST_SESSIONS : 
TPM_ST_NO_SESSIONS;
    ++  TPM_RC responseCode;
    ++  TPM_RC rc;
    ++  grub_uint32_t parameterSize;
    ++
    ++  if (!authResponse)
    ++    authResponse = &authResponseTmp;
    ++
    ++  grub_memset (authResponse, 0, sizeof (*authResponse));
    ++
    ++  /* Marshal */
    ++  grub_tpm2_buffer_init (&in);
    ++  grub_tpm2_buffer_pack_u32 (&in, auth);
    ++  grub_tpm2_buffer_pack_u32 (&in, objectHandle);
    ++  if (authCommand)
    ++    grub_tpm2_mu_TPMS_AUTH_COMMAND_Marshal (&in, authCommand);
    ++  grub_tpm2_buffer_pack_u32 (&in, persistentHandle);
    ++  if (in.error)
    ++    return TPM_RC_FAILURE;
    ++
    ++  /* Submit */
    ++  grub_tpm2_buffer_init (&out);
    ++  rc = grub_tpm2_submit_command (tag, TPM_CC_EvictControl, &responseCode, 
&in,
    ++                           &out);
    ++  if (rc != TPM_RC_SUCCESS)
    ++    return rc;
    ++  if (responseCode != TPM_RC_SUCCESS)
    ++    return responseCode;
    ++
    ++  /* Unmarshal */
    ++  if (tag == TPM_ST_SESSIONS)
    ++    {
    ++      grub_tpm2_buffer_unpack_u32 (&out, &parameterSize);
    ++      grub_tpm2_mu_TPMS_AUTH_RESPONSE_Unmarshal(&out, authResponse);
    ++    }
    ++  if (out.error)
    ++    return TPM_RC_FAILURE;
    ++
    ++  return TPM_RC_SUCCESS;
    ++}
    ++
    ++TPM_RC
    ++TPM2_HashSequenceStart (const TPMS_AUTH_COMMAND *authCommand,
    ++                        const TPM2B_AUTH *auth,
    ++                        const TPMI_ALG_HASH hashAlg,
    ++                        TPMI_DH_OBJECT *sequenceHandle,
    ++                        TPMS_AUTH_RESPONSE *authResponse)
    ++{
    ++  struct grub_tpm2_buffer in;
    ++  struct grub_tpm2_buffer out;
    ++  TPMI_DH_OBJECT sequenceHandleTmp;
    ++  TPMS_AUTH_RESPONSE authResponseTmp;
    ++  TPMI_ST_COMMAND_TAG tag = authCommand ? TPM_ST_SESSIONS : 
TPM_ST_NO_SESSIONS;
    ++  TPM_RC responseCode;
    ++  TPM_RC rc;
    ++  grub_uint32_t parameterSize;
    ++
    ++  if (!auth)
    ++    return TPM_RC_VALUE;
    ++
    ++  if (!sequenceHandle)
    ++    sequenceHandle = &sequenceHandleTmp;
    ++  if (!authResponse)
    ++    authResponse = &authResponseTmp;
    ++
    ++  grub_memset (sequenceHandle, 0, sizeof (*sequenceHandle));
    ++  grub_memset (authResponse, 0, sizeof (*authResponse));
    ++
    ++  /* Marshal */
    ++  grub_tpm2_buffer_init (&in);
    ++  if (authCommand)
    ++    grub_tpm2_mu_TPMS_AUTH_COMMAND_Marshal (&in, authCommand);
    ++  grub_tpm2_mu_TPM2B_Marshal (&in, auth->size, auth->buffer);
    ++  grub_tpm2_buffer_pack_u16 (&in, hashAlg);
    ++  if (in.error)
    ++    return TPM_RC_FAILURE;
    ++
    ++  /* Submit */
    ++  grub_tpm2_buffer_init (&out);
    ++  rc = grub_tpm2_submit_command (tag, TPM_CC_HashSequenceStart, 
&responseCode, &in,
    ++                                 &out);
    ++  if (rc != TPM_RC_SUCCESS)
    ++    return rc;
    ++  if (responseCode != TPM_RC_SUCCESS)
    ++    return responseCode;
    ++
    ++  /* Unmarshal */
    ++  grub_tpm2_buffer_unpack_u32 (&out, sequenceHandle);
    ++  if (tag == TPM_ST_SESSIONS)
    ++    {
    ++      grub_tpm2_buffer_unpack_u32 (&out, &parameterSize);
    ++      grub_tpm2_mu_TPMS_AUTH_RESPONSE_Unmarshal(&out, authResponse);
    ++    }
    ++  if (out.error)
    ++    return TPM_RC_FAILURE;
    ++
    ++  return TPM_RC_SUCCESS;
    ++}
    ++
    ++TPM_RC
    ++TPM2_SequenceUpdate (const TPMI_DH_OBJECT sequenceHandle,
    ++                     const TPMS_AUTH_COMMAND *authCommand,
    ++                     const TPM2B_MAX_BUFFER *buffer,
    ++                     TPMS_AUTH_RESPONSE *authResponse)
    ++{
    ++  struct grub_tpm2_buffer in;
    ++  struct grub_tpm2_buffer out;
    ++  TPMS_AUTH_RESPONSE authResponseTmp;
    ++  TPM_RC responseCode;
    ++  TPM_RC rc;
    ++  grub_uint32_t parameterSize;
    ++
    ++  if (!authCommand)
    ++    return TPM_RC_VALUE;
    ++
    ++  if (!authResponse)
    ++    authResponse = &authResponseTmp;
    ++
    ++  grub_memset (authResponse, 0, sizeof (*authResponse));
    ++
    ++  /* Marshal */
    ++  grub_tpm2_buffer_init (&in);
    ++  grub_tpm2_buffer_pack_u32 (&in, sequenceHandle);
    ++  grub_tpm2_mu_TPMS_AUTH_COMMAND_Marshal (&in, authCommand);
    ++  if (buffer)
    ++    grub_tpm2_mu_TPM2B_Marshal (&in, buffer->size, buffer->buffer);
    ++  else
    ++    grub_tpm2_buffer_pack_u16 (&in, 0);
    ++  if (in.error)
    ++    return TPM_RC_FAILURE;
    ++
    ++  /* Submit */
    ++  grub_tpm2_buffer_init (&out);
    ++  rc = grub_tpm2_submit_command (TPM_ST_SESSIONS, TPM_CC_SequenceUpdate,
    ++                                 &responseCode, &in, &out);
    ++  if (rc != TPM_RC_SUCCESS)
    ++    return rc;
    ++  if (responseCode != TPM_RC_SUCCESS)
    ++    return responseCode;
    ++
    ++  /* Unmarshal */
    ++  grub_tpm2_buffer_unpack_u32 (&out, &parameterSize);
    ++  grub_tpm2_mu_TPMS_AUTH_RESPONSE_Unmarshal(&out, authResponse);
    ++  if (out.error)
    ++    return TPM_RC_FAILURE;
    ++
    ++  return TPM_RC_SUCCESS;
    ++}
    ++
    ++TPM_RC
    ++TPM2_SequenceComplete (const TPMI_DH_OBJECT sequenceHandle,
    ++                       const TPMS_AUTH_COMMAND *authCommand,
    ++                       const TPM2B_MAX_BUFFER *buffer,
    ++                       const TPMI_RH_HIERARCHY hierarchy,
    ++                       TPM2B_DIGEST *result,
    ++                       TPMT_TK_HASHCHECK *validation,
    ++                       TPMS_AUTH_RESPONSE *authResponse)
    ++{
    ++  struct grub_tpm2_buffer in;
    ++  struct grub_tpm2_buffer out;
    ++  TPM2B_DIGEST resultTmp;
    ++  TPMT_TK_HASHCHECK validationTmp;
    ++  TPMS_AUTH_RESPONSE authResponseTmp;
    ++  TPM_RC responseCode;
    ++  TPM_RC rc;
    ++  grub_uint32_t parameterSize;
    ++
    ++  if (!authCommand)
    ++    return TPM_RC_VALUE;
    ++
    ++  if (!result)
    ++    result = &resultTmp;
    ++  if (!validation)
    ++    validation = &validationTmp;
    ++  if (!authResponse)
    ++    authResponse = &authResponseTmp;
    ++
    ++  grub_memset (result, 0, sizeof (*result));
    ++  grub_memset (validation, 0, sizeof (*validation));
    ++  grub_memset (authResponse, 0, sizeof (*authResponse));
    ++
    ++  /* Marshal */
    ++  grub_tpm2_buffer_init (&in);
    ++  grub_tpm2_buffer_pack_u32 (&in, sequenceHandle);
    ++  grub_tpm2_mu_TPMS_AUTH_COMMAND_Marshal (&in, authCommand);
    ++  if (buffer)
    ++    grub_tpm2_mu_TPM2B_Marshal (&in, buffer->size, buffer->buffer);
    ++  else
    ++    grub_tpm2_buffer_pack_u16 (&in, 0);
    ++  grub_tpm2_buffer_pack_u32 (&in, hierarchy);
    ++
    ++  if (in.error)
    ++    return TPM_RC_FAILURE;
    ++
    ++  /* Submit */
    ++  grub_tpm2_buffer_init (&out);
    ++  rc = grub_tpm2_submit_command (TPM_ST_SESSIONS, TPM_CC_SequenceComplete,
    ++                                 &responseCode, &in, &out);
    ++  if (rc != TPM_RC_SUCCESS)
    ++    return rc;
    ++  if (responseCode != TPM_RC_SUCCESS)
    ++    return responseCode;
    ++
    ++  /* Unmarshal */
    ++  grub_tpm2_buffer_unpack_u32 (&out, &parameterSize);
    ++  grub_tpm2_mu_TPM2B_DIGEST_Unmarshal (&out, result);
    ++  grub_tpm2_mu_TPMT_TK_HASHCHECK_Unmarshal (&out, validation);
    ++  grub_tpm2_mu_TPMS_AUTH_RESPONSE_Unmarshal(&out, authResponse);
    ++  if (out.error)
    ++    return TPM_RC_FAILURE;
    ++
    ++  return TPM_RC_SUCCESS;
    ++}
    ++
    ++TPM_RC
    ++TPM2_Hash (const TPMS_AUTH_COMMAND *authCommand,
    ++           const TPM2B_MAX_BUFFER *data,
    ++           const TPMI_ALG_HASH hashAlg,
    ++           const TPMI_RH_HIERARCHY hierarchy,
    ++           TPM2B_DIGEST *outHash,
    ++           TPMT_TK_HASHCHECK *validation,
    ++           TPMS_AUTH_RESPONSE *authResponse)
    ++{
    ++  TPM_RC rc;
    ++  struct grub_tpm2_buffer in;
    ++  struct grub_tpm2_buffer out;
    ++  TPMS_AUTH_RESPONSE authResponseTmp;
    ++  TPM2B_DIGEST outHashTmp;
    ++  TPMT_TK_HASHCHECK validationTmp;
    ++  TPMI_ST_COMMAND_TAG tag = authCommand ? TPM_ST_SESSIONS : 
TPM_ST_NO_SESSIONS;
    ++  TPM_RC responseCode;
    ++  grub_uint32_t param_size;
    ++
    ++  if (hashAlg == TPM_ALG_NULL)
    ++    return TPM_RC_VALUE;
    ++
    ++  if (!outHash)
    ++    outHash = &outHashTmp;
    ++  if (!validation)
    ++    validation = &validationTmp;
    ++  if (!authResponse)
    ++    authResponse = &authResponseTmp;
    ++
    ++  grub_memset (outHash, 0, sizeof (*outHash));
    ++  grub_memset (validation, 0, sizeof (*validation));
    ++  grub_memset (authResponse, 0, sizeof (*authResponse));
    ++
    ++  /* Marshal */
    ++  grub_tpm2_buffer_init (&in);
    ++  if (authCommand)
    ++    grub_tpm2_mu_TPMS_AUTH_COMMAND_Marshal (&in, authCommand);
    ++  if (data)
    ++    grub_tpm2_mu_TPM2B_Marshal (&in, data->size, data->buffer);
    ++  else
    ++    grub_tpm2_buffer_pack_u16 (&in, 0);
    ++  grub_tpm2_buffer_pack_u16 (&in, hashAlg);
    ++  grub_tpm2_buffer_pack_u32 (&in, hierarchy);
    ++  if (in.error)
    ++    return TPM_RC_FAILURE;
    ++
    ++  /* Submit */
    ++  grub_tpm2_buffer_init (&out);
    ++  rc = grub_tpm2_submit_command (tag, TPM_CC_Hash, &responseCode, &in, 
&out);
    ++  if (rc != TPM_RC_SUCCESS)
    ++    return rc;
    ++  if (responseCode != TPM_RC_SUCCESS)
    ++    return responseCode;
    ++
    ++  /* Unmarshal */
    ++  if (tag == TPM_ST_SESSIONS)
    ++    grub_tpm2_buffer_unpack_u32 (&out, &param_size);
    ++  grub_tpm2_mu_TPM2B_DIGEST_Unmarshal (&out, outHash);
    ++  grub_tpm2_mu_TPMT_TK_HASHCHECK_Unmarshal (&out, validation);
    ++  if (tag == TPM_ST_SESSIONS)
    ++    grub_tpm2_mu_TPMS_AUTH_RESPONSE_Unmarshal (&out, authResponse);
    ++  if (out.error)
    ++    return TPM_RC_FAILURE;
    ++
    ++  return TPM_RC_SUCCESS;
    ++}
    ++
    ++TPM_RC
    ++TPM2_VerifySignature (const TPMI_DH_OBJECT keyHandle,
    ++                      const TPMS_AUTH_COMMAND *authCommand,
    ++                      const TPM2B_DIGEST *digest,
    ++                      const TPMT_SIGNATURE *signature,
    ++                      TPMT_TK_VERIFIED *validation,
    ++                      TPMS_AUTH_RESPONSE *authResponse)
    ++{
    ++  TPM_RC rc;
    ++  struct grub_tpm2_buffer in;
    ++  struct grub_tpm2_buffer out;
    ++  TPMS_AUTH_RESPONSE authResponseTmp;
     +  TPMI_ST_COMMAND_TAG tag = authCommand ? TPM_ST_SESSIONS : 
TPM_ST_NO_SESSIONS;
    ++  TPMT_TK_VERIFIED validationTmp;
     +  TPM_RC responseCode;
    -+  grub_uint32_t parameterSize;
    ++  grub_uint32_t param_size;
    ++
    ++  if (!digest || !signature)
    ++    return TPM_RC_VALUE;
     +
    ++  if (!validation)
    ++    validation = &validationTmp;
     +  if (!authResponse)
     +    authResponse = &authResponseTmp;
    -+  if (!policyDigest)
    -+    policyDigest = &policyDigestTmp;
     +
    ++  grub_memset (validation, 0, sizeof (*validation));
     +  grub_memset (authResponse, 0, sizeof (*authResponse));
    -+  grub_memset (policyDigest, 0, sizeof (*policyDigest));
     +
    -+  /* Submit */
    ++  /* Marshal */
     +  grub_tpm2_buffer_init (&in);
    -+  grub_tpm2_buffer_pack_u32 (&in, policySession);
    -+  if (tag == TPM_ST_SESSIONS)
    ++  if (authCommand)
     +    grub_tpm2_mu_TPMS_AUTH_COMMAND_Marshal (&in, authCommand);
    ++  grub_tpm2_buffer_pack_u32 (&in, keyHandle);
    ++  grub_tpm2_mu_TPM2B_Marshal (&in, digest->size, digest->buffer);
    ++  grub_tpm2_mu_TPMT_SIGNATURE_Marshal (&in, signature);
     +  if (in.error)
     +    return TPM_RC_FAILURE;
     +
     +  /* Submit */
     +  grub_tpm2_buffer_init (&out);
    -+  rc = grub_tpm2_submit_command (tag, TPM_CC_PolicyGetDigest, 
&responseCode,
    -+                           &in, &out);
    ++  rc = grub_tpm2_submit_command (tag, TPM_CC_VerifySignature, 
&responseCode, &in, &out);
     +  if (rc != TPM_RC_SUCCESS)
     +    return rc;
     +  if (responseCode != TPM_RC_SUCCESS)
     +    return responseCode;
     +
    -+  /* Unmarshal*/
    ++  /* Unmarshal */
     +  if (tag == TPM_ST_SESSIONS)
    -+    grub_tpm2_buffer_unpack_u32 (&out, &parameterSize);
    -+  grub_tpm2_mu_TPM2B_Unmarshal (&out, (TPM2B*)policyDigest);
    ++    grub_tpm2_buffer_unpack_u32 (&out, &param_size);
    ++  grub_tpm2_mu_TPMT_TK_VERIFIED_Unmarshal (&out, validation);
     +  if (tag == TPM_ST_SESSIONS)
     +    grub_tpm2_mu_TPMS_AUTH_RESPONSE_Unmarshal (&out, authResponse);
     +  if (out.error)
    @@ grub-core/tpm2/tpm2.c (new)
     +}
     +
     +TPM_RC
    -+TPM2_Create (const TPMI_DH_OBJECT parentHandle,
    -+       const TPMS_AUTH_COMMAND *authCommand,
    -+       const TPM2B_SENSITIVE_CREATE *inSensitive,
    -+       const TPM2B_PUBLIC *inPublic,
    -+       const TPM2B_DATA *outsideInfo,
    -+       const TPML_PCR_SELECTION *creationPCR,
    -+       TPM2B_PRIVATE *outPrivate,
    -+       TPM2B_PUBLIC *outPublic,
    -+       TPM2B_CREATION_DATA *creationData,
    -+       TPM2B_DIGEST *creationHash,
    -+       TPMT_TK_CREATION *creationTicket,
    -+       TPMS_AUTH_RESPONSE *authResponse)
    ++TPM2_PolicyAuthorize (const TPMI_SH_POLICY policySession,
    ++                      const TPMS_AUTH_COMMAND *authCommand,
    ++                      const TPM2B_DIGEST *approvedPolicy,
    ++                      const TPM2B_NONCE *policyRef,
    ++                      const TPM2B_NAME *keySign,
    ++                      const TPMT_TK_VERIFIED *checkTicket,
    ++                      TPMS_AUTH_RESPONSE *authResponse)
     +{
    ++  TPM_RC rc;
     +  struct grub_tpm2_buffer in;
     +  struct grub_tpm2_buffer out;
    -+  TPM2B_PUBLIC outPublicTmp;
    -+  TPM2B_PRIVATE outPrivateTmp;
    -+  TPM2B_CREATION_DATA creationDataTmp;
    -+  TPM2B_DIGEST creationHashTmp;
    -+  TPMT_TK_CREATION creationTicketTmp;
     +  TPMS_AUTH_RESPONSE authResponseTmp;
    -+  TPMI_ST_COMMAND_TAG tag = authCommand ? 
TPM_ST_SESSIONS:TPM_ST_NO_SESSIONS;
    ++  TPMI_ST_COMMAND_TAG tag = authCommand ? TPM_ST_SESSIONS : 
TPM_ST_NO_SESSIONS;
     +  TPM_RC responseCode;
    -+  TPM_RC rc;
    -+  grub_uint32_t parameterSize;
    ++  grub_uint32_t param_size;
     +
    -+  if (!inSensitive || !inPublic || !outsideInfo || !creationPCR)
    ++  if (!approvedPolicy || !keySign || !checkTicket)
     +    return TPM_RC_VALUE;
     +
    -+  if (!outPrivate)
    -+    outPrivate = &outPrivateTmp;
    -+  if (!outPublic)
    -+    outPublic = &outPublicTmp;
    -+  if (!creationData)
    -+    creationData = &creationDataTmp;
    -+  if (!creationHash)
    -+    creationHash = &creationHashTmp;
    -+  if (!creationTicket)
    -+    creationTicket = &creationTicketTmp;
     +  if (!authResponse)
     +    authResponse = &authResponseTmp;
     +
    -+  grub_memset (outPrivate, 0, sizeof (*outPrivate));
    -+  grub_memset (outPublic, 0, sizeof (*outPublic));
    -+  grub_memset (creationData, 0, sizeof (*creationData));
    -+  grub_memset (creationHash, 0, sizeof (*creationHash));
    -+  grub_memset (creationTicket, 0, sizeof (*creationTicket));
     +  grub_memset (authResponse, 0, sizeof (*authResponse));
     +
     +  /* Marshal */
     +  grub_tpm2_buffer_init (&in);
    -+  grub_tpm2_buffer_pack_u32 (&in, parentHandle);
    ++  grub_tpm2_buffer_pack_u32 (&in, policySession);
     +  if (authCommand)
     +    grub_tpm2_mu_TPMS_AUTH_COMMAND_Marshal (&in, authCommand);
    -+  grub_tpm2_mu_TPM2B_SENSITIVE_CREATE_Marshal (&in, inSensitive);
    -+  grub_tpm2_mu_TPM2B_PUBLIC_Marshal (&in, inPublic);
    -+  grub_tpm2_mu_TPM2B_Marshal (&in, outsideInfo->size, 
outsideInfo->buffer);
    -+  grub_tpm2_mu_TPML_PCR_SELECTION_Marshal (&in, creationPCR);
    ++  grub_tpm2_mu_TPM2B_Marshal (&in, approvedPolicy->size, 
approvedPolicy->buffer);
    ++  if (policyRef)
    ++    grub_tpm2_mu_TPM2B_Marshal (&in, policyRef->size, policyRef->buffer);
    ++  else
    ++    grub_tpm2_buffer_pack_u16 (&in, 0);
    ++  grub_tpm2_mu_TPM2B_Marshal (&in, keySign->size, keySign->name);
    ++  grub_tpm2_mu_TPMT_TK_VERIFIED_Marshal (&in, checkTicket);
     +  if (in.error)
     +    return TPM_RC_FAILURE;
     +
     +  /* Submit */
     +  grub_tpm2_buffer_init (&out);
    -+  rc = grub_tpm2_submit_command (tag, TPM_CC_Create, &responseCode, &in,
    -+                           &out);
    ++  rc = grub_tpm2_submit_command (tag, TPM_CC_PolicyAuthorize, 
&responseCode, &in, &out);
     +  if (rc != TPM_RC_SUCCESS)
     +    return rc;
     +  if (responseCode != TPM_RC_SUCCESS)
     +    return responseCode;
     +
    -+  /* Unmarshal*/
    -+  if (tag == TPM_ST_SESSIONS)
    -+   grub_tpm2_buffer_unpack_u32 (&out, &parameterSize);
    -+  grub_tpm2_mu_TPM2B_Unmarshal (&out, (TPM2B*)outPrivate);
    -+  grub_tpm2_mu_TPM2B_PUBLIC_Unmarshal (&out, outPublic);
    -+  grub_tpm2_mu_TPM2B_Unmarshal (&out, (TPM2B*)creationData);
    -+  grub_tpm2_mu_TPM2B_Unmarshal (&out, (TPM2B*)creationHash);
    -+  grub_tpm2_mu_TPMT_TK_CREATION_Unmarshal (&out, creationTicket);
    ++  /* Unmarshal */
     +  if (tag == TPM_ST_SESSIONS)
    -+    grub_tpm2_mu_TPMS_AUTH_RESPONSE_Unmarshal(&out, authResponse);
    ++    {
    ++      grub_tpm2_buffer_unpack_u32 (&out, &param_size);
    ++      grub_tpm2_mu_TPMS_AUTH_RESPONSE_Unmarshal (&out, authResponse);
    ++    }
     +  if (out.error)
     +    return TPM_RC_FAILURE;
     +
    @@ grub-core/tpm2/tpm2.c (new)
     +}
     +
     +TPM_RC
    -+TPM2_EvictControl (const TPMI_RH_PROVISION auth,
    -+             const TPMI_DH_OBJECT objectHandle,
    -+             const TPMS_AUTH_COMMAND *authCommand,
    -+             const TPMI_DH_PERSISTENT persistentHandle,
    -+             TPMS_AUTH_RESPONSE *authResponse)
    ++TPM2_TestParms (const TPMT_PUBLIC_PARMS *parms,
    ++          const TPMS_AUTH_COMMAND* authCommand)
     +{
    ++  TPM_RC rc;
     +  struct grub_tpm2_buffer in;
     +  struct grub_tpm2_buffer out;
    -+  TPMS_AUTH_RESPONSE authResponseTmp;
     +  TPMI_ST_COMMAND_TAG tag = authCommand ? TPM_ST_SESSIONS : 
TPM_ST_NO_SESSIONS;
     +  TPM_RC responseCode;
    -+  TPM_RC rc;
    -+  grub_uint32_t parameterSize;
     +
    -+  if (!authResponse)
    -+    authResponse = &authResponseTmp;
    -+
    -+  grub_memset (authResponse, 0, sizeof (*authResponse));
    ++  if (!parms)
    ++    return TPM_RC_VALUE;
     +
     +  /* Marshal */
     +  grub_tpm2_buffer_init (&in);
    -+  grub_tpm2_buffer_pack_u32 (&in, auth);
    -+  grub_tpm2_buffer_pack_u32 (&in, objectHandle);
    -+  if (authCommand)
    -+    grub_tpm2_mu_TPMS_AUTH_COMMAND_Marshal (&in, authCommand);
    -+  grub_tpm2_buffer_pack_u32 (&in, persistentHandle);
    ++  grub_tpm2_mu_TPMT_PUBLIC_PARMS_Marshal (&in, parms);
     +  if (in.error)
     +    return TPM_RC_FAILURE;
     +
     +  /* Submit */
     +  grub_tpm2_buffer_init (&out);
    -+  rc = grub_tpm2_submit_command (tag, TPM_CC_EvictControl, &responseCode, 
&in,
    ++  rc = grub_tpm2_submit_command (tag, TPM_CC_TestParms, &responseCode, 
&in,
     +                           &out);
     +  if (rc != TPM_RC_SUCCESS)
     +    return rc;
     +  if (responseCode != TPM_RC_SUCCESS)
     +    return responseCode;
     +
    -+  /* Unmarshal*/
    -+  if (tag == TPM_ST_SESSIONS)
    -+    {
    -+      grub_tpm2_buffer_unpack_u32 (&out, &parameterSize);
    -+      grub_tpm2_mu_TPMS_AUTH_RESPONSE_Unmarshal(&out, authResponse);
    -+    }
    ++  /* Unmarshal */
     +  if (out.error)
     +    return TPM_RC_FAILURE;
     +
    @@ include/grub/tpm2/internal/functions.h (new)
     +     TPMS_AUTH_RESPONSE *authResponse);
     +
     +TPM_RC
    ++TPM2_LoadExternal (const TPMS_AUTH_COMMAND *authCommand,
    ++                   const TPM2B_SENSITIVE *inPrivate,
    ++                   const TPM2B_PUBLIC *inPublic,
    ++                   const TPMI_RH_HIERARCHY hierarchy,
    ++                   TPM_HANDLE *objectHandle,
    ++                   TPM2B_NAME *name,
    ++                   TPMS_AUTH_RESPONSE *authResponse);
    ++
    ++TPM_RC
     +TPM2_Unseal (const TPMI_DH_OBJECT item_handle,
     +       const TPMS_AUTH_COMMAND *authCommand,
     +       TPM2B_SENSITIVE_DATA *outData,
    @@ include/grub/tpm2/internal/functions.h (new)
     +             const TPMI_DH_PERSISTENT persistentHandle,
     +             TPMS_AUTH_RESPONSE *authResponse);
     +
    ++TPM_RC
    ++TPM2_HashSequenceStart (const TPMS_AUTH_COMMAND *authCommand,
    ++                        const TPM2B_AUTH *auth,
    ++                        const TPMI_ALG_HASH hashAlg,
    ++                        TPMI_DH_OBJECT *sequenceHandle,
    ++                        TPMS_AUTH_RESPONSE *authResponse);
    ++
    ++TPM_RC
    ++TPM2_SequenceUpdate (const TPMI_DH_OBJECT sequenceHandle,
    ++                     const TPMS_AUTH_COMMAND *authCommand,
    ++                     const TPM2B_MAX_BUFFER *buffer,
    ++                     TPMS_AUTH_RESPONSE *authResponse);
    ++
    ++TPM_RC
    ++TPM2_SequenceComplete (const TPMI_DH_OBJECT sequenceHandle,
    ++                       const TPMS_AUTH_COMMAND *authCommand,
    ++                       const TPM2B_MAX_BUFFER *buffer,
    ++                       const TPMI_RH_HIERARCHY hierarchy,
    ++                       TPM2B_DIGEST *result,
    ++                       TPMT_TK_HASHCHECK *validation,
    ++                       TPMS_AUTH_RESPONSE *authResponse);
    ++
    ++TPM_RC
    ++TPM2_Hash (const TPMS_AUTH_COMMAND *authCommand,
    ++           const TPM2B_MAX_BUFFER *data,
    ++           const TPMI_ALG_HASH hashAlg,
    ++           const TPMI_RH_HIERARCHY hierarchy,
    ++           TPM2B_DIGEST *outHash,
    ++           TPMT_TK_HASHCHECK *validation,
    ++           TPMS_AUTH_RESPONSE *authResponse);
    ++
    ++TPM_RC
    ++TPM2_VerifySignature (const TPMI_DH_OBJECT keyHandle,
    ++                      const TPMS_AUTH_COMMAND *authCommand,
    ++                      const TPM2B_DIGEST *digest,
    ++                      const TPMT_SIGNATURE *signature,
    ++                      TPMT_TK_VERIFIED *validation,
    ++                      TPMS_AUTH_RESPONSE *authResponse);
    ++
    ++TPM_RC
    ++TPM2_PolicyAuthorize (const TPMI_SH_POLICY policySession,
    ++                      const TPMS_AUTH_COMMAND *authCommand,
    ++                      const TPM2B_DIGEST *approvedPolicy,
    ++                      const TPM2B_NONCE *policyRef,
    ++                      const TPM2B_NAME *keySign,
    ++                      const TPMT_TK_VERIFIED *checkTicket,
    ++                      TPMS_AUTH_RESPONSE *authResponse);
    ++
    ++TPM_RC
    ++TPM2_TestParms (const TPMT_PUBLIC_PARMS *parms,
    ++          const TPMS_AUTH_COMMAND* authCommand);
    ++
     +#endif /* ! GRUB_TPM2_INTERNAL_FUNCTIONS_HEADER */
     
      ## include/grub/tpm2/internal/structs.h (new) ##
    @@ include/grub/tpm2/internal/structs.h (new)
     +};
     +typedef union TPMU_PUBLIC_PARMS TPMU_PUBLIC_PARMS;
     +
    ++/* TPMT_PUBLIC_PARMS Structure */
    ++struct TPMT_PUBLIC_PARMS {
    ++    TPMI_ALG_PUBLIC type;
    ++    TPMU_PUBLIC_PARMS parameters;
    ++};
    ++typedef struct TPMT_PUBLIC_PARMS TPMT_PUBLIC_PARMS;
    ++
     +/* TPM2B_PUBLIC_KEY_RSA Structure */
     +struct TPM2B_PUBLIC_KEY_RSA
     +{
    @@ include/grub/tpm2/internal/structs.h (new)
     +};
     +typedef struct TPMT_TK_CREATION TPMT_TK_CREATION;
     +
    ++/* TPMS_EMPTY Structure */
    ++struct TPMS_EMPTY {
    ++  grub_uint8_t empty[1]; /* a structure with no member */
    ++};
    ++typedef struct TPMS_EMPTY TPMS_EMPTY;
    ++
    ++/* TPMS_SIGNATURE_RSA Structure */
    ++struct TPMS_SIGNATURE_RSA {
    ++  TPMI_ALG_HASH hash;
    ++  TPM2B_PUBLIC_KEY_RSA sig;
    ++};
    ++typedef struct TPMS_SIGNATURE_RSA TPMS_SIGNATURE_RSA;
    ++
    ++/* Definition of Types for RSA Signature */
    ++typedef TPMS_SIGNATURE_RSA TPMS_SIGNATURE_RSASSA;
    ++typedef TPMS_SIGNATURE_RSA TPMS_SIGNATURE_RSAPSS;
    ++
    ++/* TPMS_SIGNATURE_ECC Structure */
    ++struct TPMS_SIGNATURE_ECC {
    ++  TPMI_ALG_HASH hash;
    ++  TPM2B_ECC_PARAMETER signatureR;
    ++  TPM2B_ECC_PARAMETER signatureS;
    ++};
    ++typedef struct TPMS_SIGNATURE_ECC TPMS_SIGNATURE_ECC;
    ++
    ++/* Definition of Types for ECC TPMS_SIGNATURE_ECC */
    ++typedef TPMS_SIGNATURE_ECC TPMS_SIGNATURE_ECDSA;
    ++typedef TPMS_SIGNATURE_ECC TPMS_SIGNATURE_ECDAA;
    ++typedef TPMS_SIGNATURE_ECC TPMS_SIGNATURE_SM2;
    ++typedef TPMS_SIGNATURE_ECC TPMS_SIGNATURE_ECSCHNORR;
    ++
    ++/* TPMU_SIGNATURE Structure */
    ++union TPMU_SIGNATURE {
    ++  TPMS_SIGNATURE_RSASSA rsassa;
    ++  TPMS_SIGNATURE_RSAPSS rsapss;
    ++  TPMS_SIGNATURE_ECDSA ecdsa;
    ++  TPMS_SIGNATURE_ECDAA ecdaa;
    ++  TPMS_SIGNATURE_SM2 sm2;
    ++  TPMS_SIGNATURE_ECSCHNORR ecschnorr;
    ++  TPMT_HA hmac;
    ++  TPMS_SCHEME_HASH any;
    ++  TPMS_EMPTY null;
    ++};
    ++typedef union TPMU_SIGNATURE TPMU_SIGNATURE;
    ++
    ++/* TPMT_SIGNATURE Structure */
    ++struct TPMT_SIGNATURE {
    ++  TPMI_ALG_SIG_SCHEME sigAlg;
    ++  TPMU_SIGNATURE signature;
    ++};
    ++typedef struct TPMT_SIGNATURE TPMT_SIGNATURE;
    ++
    ++static inline TPMI_ALG_HASH
    ++TPMT_SIGNATURE_get_hash_alg (TPMT_SIGNATURE *sig)
    ++{
    ++  switch (sig->sigAlg)
    ++    {
    ++    case TPM_ALG_RSASSA:
    ++      return sig->signature.rsassa.hash;
    ++    case TPM_ALG_RSAPSS:
    ++      return sig->signature.rsapss.hash;
    ++    case TPM_ALG_ECDSA:
    ++      return sig->signature.ecdsa.hash;
    ++    case TPM_ALG_ECDAA:
    ++      return sig->signature.ecdaa.hash;
    ++    case TPM_ALG_SM2:
    ++      return sig->signature.sm2.hash;
    ++    case TPM_ALG_ECSCHNORR:
    ++      return sig->signature.ecschnorr.hash;
    ++    case TPM_ALG_HMAC:
    ++      return sig->signature.hmac.hashAlg;
    ++    default:
    ++      break;
    ++    }
    ++
    ++  return TPM_ALG_NULL;
    ++}
    ++
    ++/* TPMT_TK_VERIFIED Structure */
    ++struct TPMT_TK_VERIFIED {
    ++  TPM_ST tag;
    ++  TPMI_RH_HIERARCHY hierarchy;
    ++  TPM2B_DIGEST digest;
    ++};
    ++typedef struct TPMT_TK_VERIFIED TPMT_TK_VERIFIED;
    ++
     +#endif /* ! GRUB_TPM2_INTERNAL_STRUCTS_HEADER */
     
      ## include/grub/tpm2/internal/types.h (new) ##
    @@ include/grub/tpm2/internal/types.h (new)
     +#define TPM_ALG_CFB            ((TPM_ALG_ID) 0x0043)
     +#define TPM_ALG_ECB            ((TPM_ALG_ID) 0x0044)
     +#define TPM_ALG_ECC            ((TPM_ALG_ID) 0x0023)
    ++#define TPM_ALG_ECDAA          ((TPM_ALG_ID) 0x001A)
    ++#define TPM_ALG_ECDSA          ((TPM_ALG_ID) 0x0018)
    ++#define TPM_ALG_ECSCHNORR      ((TPM_ALG_ID) 0x001C)
     +#define TPM_ALG_HMAC           ((TPM_ALG_ID) 0x0005)
     +#define TPM_ALG_KDF1_SP800_108 ((TPM_ALG_ID) 0x0022)
     +#define TPM_ALG_KDF1_SP800_56A ((TPM_ALG_ID) 0x0020)
    @@ include/grub/tpm2/internal/types.h (new)
     +#define TPM_ALG_MGF1           ((TPM_ALG_ID) 0x0007)
     +#define TPM_ALG_NULL           ((TPM_ALG_ID) 0x0010)
     +#define TPM_ALG_RSA            ((TPM_ALG_ID) 0x0001)
    ++#define TPM_ALG_RSASSA         ((TPM_ALG_ID) 0x0014)
    ++#define TPM_ALG_RSAPSS         ((TPM_ALG_ID) 0x0016)
     +#define TPM_ALG_SHA1           ((TPM_ALG_ID) 0x0004)
     +#define TPM_ALG_SHA256         ((TPM_ALG_ID) 0x000B)
     +#define TPM_ALG_SHA384         ((TPM_ALG_ID) 0x000C)
     +#define TPM_ALG_SHA512         ((TPM_ALG_ID) 0x000D)
    ++#define TPM_ALG_SM2            ((TPM_ALG_ID) 0x001B)
     +#define TPM_ALG_SM3_256        ((TPM_ALG_ID) 0x0012)
     +#define TPM_ALG_SM4            ((TPM_ALG_ID) 0x0013)
     +#define TPM_ALG_SYMCIPHER      ((TPM_ALG_ID) 0x0025)
    @@ include/grub/tpm2/internal/types.h (new)
     +typedef TPM_HANDLE TPMI_RH_NV_AUTH;
     +typedef TPM_HANDLE TPMI_RH_NV_INDEX;
     +
    ++/* TPM_HT Constants */
    ++typedef grub_uint8_t TPM_HT;
    ++#define TPM_HT_PERMANENT  ((TPM_HT) 0x40)
    ++#define TPM_HT_PERSISTENT ((TPM_HT) 0x81)
    ++
     +/* TPM_RH Constants */
     +typedef TPM_HANDLE TPM_RH;
     +
    @@ include/grub/tpm2/internal/types.h (new)
     +#define TPM_RH_AUTH_FF     ((TPM_RH) 0x4000010F)
     +#define TPM_RH_LAST        ((TPM_RH) 0x4000010F)
     +
    ++/* TPM_HC Constants */
    ++typedef TPM_HANDLE TPM_HC;
    ++#define TPM_HR_HANDLE_MASK   ((TPM_HC) 0x00FFFFFF)
    ++#define TPM_HR_RANGE_MASK    ((TPM_HC) 0xFF000000)
    ++#define TPM_HR_SHIFT         ((TPM_HC) 24)
    ++#define TPM_HR_PERSISTENT    ((TPM_HC) (TPM_HT_PERSISTENT << 
TPM_HR_SHIFT))
    ++#define TPM_HR_PERMANENT     ((TPM_HC) (TPM_HT_PERMANENT << TPM_HR_SHIFT))
    ++#define TPM_PERSISTENT_FIRST ((TPM_HC) (TPM_HR_PERSISTENT + 0))
    ++#define TPM_PERSISTENT_LAST  ((TPM_HC) (TPM_PERSISTENT_FIRST + 
0x00FFFFFF))
    ++#define TPM_PERMANENT_FIRST  ((TPM_HC) TPM_RH_FIRST)
    ++#define TPM_PERMANENT_LAST   ((TPM_HC) TPM_RH_LAST)
    ++
    ++/* TPM Handle Type Checks */
    ++#define TPM_HT_IS_PERMANENT(HANDLE) (((HANDLE) >> TPM_HR_SHIFT) == 
TPM_HT_PERMANENT)
    ++#define TPM_HT_IS_PERSISTENT(HANDLE) (((HANDLE) >> TPM_HR_SHIFT) == 
TPM_HT_PERSISTENT)
    ++
     +/* TPM_ECC_CURVE Constants */
     +typedef grub_uint16_t TPM_ECC_CURVE;
     +
    @@ include/grub/tpm2/internal/types.h (new)
     +/* TPM_CC Constants */
     +typedef grub_uint32_t TPM_CC;
     +
    -+#define TPM_CC_EvictControl     ((TPM_CC) 0x00000120)
    -+#define TPM_CC_CreatePrimary    ((TPM_CC) 0x00000131)
    -+#define TPM_CC_Create           ((TPM_CC) 0x00000153)
    -+#define TPM_CC_FlushContext     ((TPM_CC) 0x00000165)
    -+#define TPM_CC_ReadPublic       ((TPM_CC) 0x00000173)
    -+#define TPM_CC_StartAuthSession ((TPM_CC) 0x00000176)
    -+#define TPM_CC_PolicyPCR        ((TPM_CC) 0x0000017f)
    -+#define TPM_CC_NV_Read          ((TPM_CC) 0x0000014e)
    -+#define TPM_CC_NV_ReadPublic    ((TPM_CC) 0x00000169)
    -+#define TPM_CC_GetCapability    ((TPM_CC) 0x0000017a)
    -+#define TPM_CC_PCR_Read         ((TPM_CC) 0x0000017e)
    -+#define TPM_CC_Load             ((TPM_CC) 0x00000157)
    -+#define TPM_CC_Unseal           ((TPM_CC) 0x0000015e)
    -+#define TPM_CC_PolicyGetDigest  ((TPM_CC) 0x00000189)
    ++#define TPM_CC_EvictControl      ((TPM_CC) 0x00000120)
    ++#define TPM_CC_CreatePrimary     ((TPM_CC) 0x00000131)
    ++#define TPM_CC_Create            ((TPM_CC) 0x00000153)
    ++#define TPM_CC_FlushContext      ((TPM_CC) 0x00000165)
    ++#define TPM_CC_ReadPublic        ((TPM_CC) 0x00000173)
    ++#define TPM_CC_StartAuthSession  ((TPM_CC) 0x00000176)
    ++#define TPM_CC_PolicyPCR         ((TPM_CC) 0x0000017f)
    ++#define TPM_CC_NV_Read           ((TPM_CC) 0x0000014e)
    ++#define TPM_CC_NV_ReadPublic     ((TPM_CC) 0x00000169)
    ++#define TPM_CC_GetCapability     ((TPM_CC) 0x0000017a)
    ++#define TPM_CC_PCR_Read          ((TPM_CC) 0x0000017e)
    ++#define TPM_CC_Load              ((TPM_CC) 0x00000157)
    ++#define TPM_CC_LoadExternal      ((TPM_CC) 0x00000167)
    ++#define TPM_CC_Unseal            ((TPM_CC) 0x0000015e)
    ++#define TPM_CC_PolicyGetDigest   ((TPM_CC) 0x00000189)
    ++#define TPM_CC_HashSequenceStart ((TPM_CC) 0x00000186)
    ++#define TPM_CC_SequenceUpdate    ((TPM_CC) 0x0000015c)
    ++#define TPM_CC_SequenceComplete  ((TPM_CC) 0x0000013e)
    ++#define TPM_CC_Hash              ((TPM_CC) 0x0000017d)
    ++#define TPM_CC_VerifySignature   ((TPM_CC) 0x00000177)
    ++#define TPM_CC_PolicyAuthorize   ((TPM_CC) 0x0000016a)
    ++#define TPM_CC_TestParms         ((TPM_CC) 0x0000018a)
     +
     +/* Hash algorithm sizes */
     +#define TPM_SHA1_DIGEST_SIZE    20
    @@ include/grub/tpm2/internal/types.h (new)
     +typedef TPM_ALG_ID TPMI_ALG_ASYM_SCHEME;
     +typedef TPM_ALG_ID TPMI_ALG_RSA_SCHEME;
     +typedef TPM_ALG_ID TPMI_ALG_SYM;
    ++typedef TPM_ALG_ID TPMI_ALG_SIG_SCHEME;
     +
     +/* TPM_KEY_BITS Type */
     +typedef grub_uint16_t TPM_KEY_BITS;
    @@ include/grub/tpm2/mu.h (new)
     +#include <grub/tpm2/tpm2.h>
     +
     +void
    -+grub_tpm2_mu_TPMS_AUTH_COMMAND_Marshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMS_AUTH_COMMAND_Marshal (grub_tpm2_buffer_t buffer,
     +                                  const TPMS_AUTH_COMMAND* authCommand);
     +
     +void
    -+grub_tpm2_mu_TPM2B_Marshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPM2B_Marshal (grub_tpm2_buffer_t buffer,
     +                      const grub_uint16_t size,
    -+                      const grub_uint8_t* buffer);
    ++                      const grub_uint8_t* b);
     +
     +void
    -+grub_tpm2_mu_TPMU_SYM_KEY_BITS_Marshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMU_SYM_KEY_BITS_Marshal (grub_tpm2_buffer_t buffer,
     +                                  const TPMI_ALG_SYM_OBJECT algorithm,
     +                                  const TPMU_SYM_KEY_BITS *p);
     +
     +void
    -+grub_tpm2_mu_TPMU_SYM_MODE_Marshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMU_SYM_MODE_Marshal (grub_tpm2_buffer_t buffer,
     +                              const TPMI_ALG_SYM_OBJECT algorithm,
     +                              const TPMU_SYM_MODE *p);
     +
     +void
    -+grub_tpm2_mu_TPMT_SYM_DEF_Marshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMT_SYM_DEF_Marshal (grub_tpm2_buffer_t buffer,
     +                             const TPMT_SYM_DEF *p);
     +
     +void
    -+grub_tpm2_mu_TPMS_PCR_SELECTION_Marshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMS_PCR_SELECTION_Marshal (grub_tpm2_buffer_t buffer,
     +                                   const TPMS_PCR_SELECTION* 
pcrSelection);
     +
     +void
    -+grub_tpm2_mu_TPML_PCR_SELECTION_Marshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPML_PCR_SELECTION_Marshal (grub_tpm2_buffer_t buffer,
     +                                   const TPML_PCR_SELECTION* 
pcrSelection);
     +
     +void
    -+grub_tpm2_mu_TPMA_OBJECT_Marshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMA_OBJECT_Marshal (grub_tpm2_buffer_t buffer,
     +                            const TPMA_OBJECT *p);
     +
     +void
    -+grub_tpm2_mu_TPMS_SCHEME_XOR_Marshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMS_SCHEME_XOR_Marshal (grub_tpm2_buffer_t buffer,
     +                                const TPMS_SCHEME_XOR *p);
     +
     +void
    -+grub_tpm2_mu_TPMS_SCHEME_HMAC_Marshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMS_SCHEME_HMAC_Marshal (grub_tpm2_buffer_t buffer,
     +                                 const TPMS_SCHEME_HMAC *p);
     +
     +void
    -+grub_tpm2_mu_TPMU_SCHEME_KEYEDHASH_Marshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMU_SCHEME_KEYEDHASH_Marshal (grub_tpm2_buffer_t buffer,
     +                                      const TPMI_ALG_KEYEDHASH_SCHEME 
scheme,
     +                                      const TPMU_SCHEME_KEYEDHASH *p);
     +
     +void
    -+grub_tpm2_mu_TPMT_KEYEDHASH_SCHEME_Marshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMT_KEYEDHASH_SCHEME_Marshal (grub_tpm2_buffer_t buffer,
     +                                      const TPMT_KEYEDHASH_SCHEME *p);
     +
     +void
    -+grub_tpm2_mu_TPMS_KEYEDHASH_PARMS_Marshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMS_KEYEDHASH_PARMS_Marshal (grub_tpm2_buffer_t buffer,
     +                                     const TPMS_KEYEDHASH_PARMS *p);
     +
     +void
    -+grub_tpm2_mu_TPMT_SYM_DEF_OBJECT_Marshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMT_SYM_DEF_OBJECT_Marshal (grub_tpm2_buffer_t buffer,
     +                                    const TPMT_SYM_DEF_OBJECT *p);
     +
     +void
    -+grub_tpm2_mu_TPMU_ASYM_SCHEME_Marshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMU_ASYM_SCHEME_Marshal (grub_tpm2_buffer_t buffer,
     +                                 const TPMI_ALG_RSA_DECRYPT scheme,
     +                                 const TPMU_ASYM_SCHEME *p);
     +
     +void
    -+grub_tpm2_mu_TPMT_RSA_SCHEME_Marshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMT_RSA_SCHEME_Marshal (grub_tpm2_buffer_t buffer,
     +                                const TPMT_RSA_SCHEME *p);
     +
     +void
    -+grub_tpm2_mu_TPMS_RSA_PARMS_Marshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMS_RSA_PARMS_Marshal (grub_tpm2_buffer_t buffer,
     +                               const TPMS_RSA_PARMS *p);
     +
     +void
    -+grub_tpm2_mu_TPMS_SYMCIPHER_PARMS_Marshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMS_SYMCIPHER_PARMS_Marshal (grub_tpm2_buffer_t buffer,
     +                                     const TPMS_SYMCIPHER_PARMS *p);
     +
     +void
    -+grub_tpm2_mu_TPMT_ECC_SCHEME_Marshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMT_ECC_SCHEME_Marshal (grub_tpm2_buffer_t buffer,
     +                                const TPMT_ECC_SCHEME *p);
     +
     +void
    -+grub_tpm2_mu_TPMU_KDF_SCHEME_Marshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMU_KDF_SCHEME_Marshal (grub_tpm2_buffer_t buffer,
     +                                const TPMI_ALG_KDF scheme,
     +                                const TPMU_KDF_SCHEME *p);
     +
     +void
    -+grub_tpm2_mu_TPMT_KDF_SCHEME_Marshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMT_KDF_SCHEME_Marshal (grub_tpm2_buffer_t buffer,
     +                                const TPMT_KDF_SCHEME *p);
     +
     +void
    -+grub_tpm2_mu_TPMS_ECC_PARMS_Marshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMS_ECC_PARMS_Marshal (grub_tpm2_buffer_t buffer,
     +                               const TPMS_ECC_PARMS *p);
     +
     +void
    -+grub_tpm2_mu_TPMU_PUBLIC_PARMS_Marshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMU_PUBLIC_PARMS_Marshal (grub_tpm2_buffer_t buffer,
     +                                  const grub_uint32_t type,
     +                                  const TPMU_PUBLIC_PARMS *p);
     +
     +void
    -+grub_tpm2_mu_TPMS_ECC_POINT_Marshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMS_ECC_POINT_Marshal (grub_tpm2_buffer_t buffer,
     +                               const TPMS_ECC_POINT *p);
     +
     +void
    -+grub_tpm2_mu_TPMU_PUBLIC_ID_Marshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMU_PUBLIC_ID_Marshal (grub_tpm2_buffer_t buffer,
     +                               const TPMI_ALG_PUBLIC type,
     +                               const TPMU_PUBLIC_ID *p);
     +
     +void
    -+grub_tpm2_mu_TPMT_PUBLIC_Marshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMT_PUBLIC_PARMS_Marshal (grub_tpm2_buffer_t buffer,
    ++                                  const TPMT_PUBLIC_PARMS *p);
    ++
    ++void
    ++grub_tpm2_mu_TPMT_PUBLIC_Marshal (grub_tpm2_buffer_t buffer,
     +                            const TPMT_PUBLIC *p);
     +
     +void
    -+grub_tpm2_mu_TPM2B_PUBLIC_Marshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPM2B_PUBLIC_Marshal (grub_tpm2_buffer_t buffer,
     +                             const TPM2B_PUBLIC *p);
     +
     +void
    -+grub_tpm2_mu_TPMS_SENSITIVE_CREATE_Marshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMS_SENSITIVE_CREATE_Marshal (grub_tpm2_buffer_t buffer,
     +                                      const TPMS_SENSITIVE_CREATE *p);
     +
     +void
    -+grub_tpm2_mu_TPM2B_SENSITIVE_CREATE_Marshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPM2B_SENSITIVE_CREATE_Marshal (grub_tpm2_buffer_t buffer,
     +                                       const TPM2B_SENSITIVE_CREATE 
*sensitiveCreate);
     +
     +void
    -+grub_tpm2_mu_TPM2B_Unmarshal (grub_tpm2_buffer_t buf,
    -+                        TPM2B* p);
    ++grub_tpm2_mu_TPMU_SENSITIVE_COMPOSITE_Marshal (grub_tpm2_buffer_t buffer,
    ++                                               const TPMI_ALG_PUBLIC type,
    ++                                               const 
TPMU_SENSITIVE_COMPOSITE *p);
    ++void
    ++grub_tpm2_mu_TPMT_SENSITIVE_Marshal (grub_tpm2_buffer_t buffer,
    ++                                     const TPMT_SENSITIVE *p);
    ++
    ++void
    ++grub_tpm2_mu_TPM2B_SENSITIVE_Marshal (grub_tpm2_buffer_t buffer,
    ++                                      const TPM2B_SENSITIVE *p);
    ++
    ++void
    ++grub_tpm2_mu_TPMS_SIGNATURE_RSA_Marshal (grub_tpm2_buffer_t buffer,
    ++                                         const TPMS_SIGNATURE_RSA *p);
    ++
    ++void
    ++grub_tpm2_mu_TPMS_SIGNATURE_ECC_Marshal (grub_tpm2_buffer_t buffer,
    ++                                         const TPMS_SIGNATURE_ECC *p);
    ++
    ++void
    ++grub_tpm2_mu_TPMU_HA_Marshal (grub_tpm2_buffer_t buffer,
    ++                              const TPMI_ALG_HASH hashAlg,
    ++                              const TPMU_HA *p);
    ++
    ++void
    ++grub_tpm2_mu_TPMT_HA_Marshal (grub_tpm2_buffer_t buffer,
    ++                              const TPMT_HA *p);
    ++
    ++void
    ++grub_tpm2_mu_TPMU_SIGNATURE_Marshal (grub_tpm2_buffer_t buffer,
    ++                                     const TPMI_ALG_SIG_SCHEME sigAlg,
    ++                                     const TPMU_SIGNATURE *p);
    ++
    ++void
    ++grub_tpm2_mu_TPMT_SIGNATURE_Marshal (grub_tpm2_buffer_t buffer,
    ++                                     const TPMT_SIGNATURE *p);
    ++
    ++void
    ++grub_tpm2_mu_TPMT_TK_VERIFIED_Marshal (grub_tpm2_buffer_t buffer,
    ++                                       const TPMT_TK_VERIFIED *p);
     +
     +void
    -+grub_tpm2_mu_TPMS_AUTH_RESPONSE_Unmarshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMS_AUTH_RESPONSE_Unmarshal (grub_tpm2_buffer_t buffer,
     +                                     TPMS_AUTH_RESPONSE* p);
     +
     +void
    -+grub_tpm2_mu_TPM2B_DIGEST_Unmarshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPM2B_DIGEST_Unmarshal (grub_tpm2_buffer_t buffer,
     +                               TPM2B_DIGEST* digest);
     +
     +void
    -+grub_tpm2_mu_TPMA_OBJECT_Unmarshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPM2B_NONCE_Unmarshal (grub_tpm2_buffer_t buffer,
    ++                              TPM2B_NONCE* nonce);
    ++
    ++void
    ++grub_tpm2_mu_TPM2B_DATA_Unmarshal (grub_tpm2_buffer_t buffer,
    ++                             TPM2B_DATA* data);
    ++
    ++void
    ++grub_tpm2_mu_TPMS_CREATION_DATA_Unmarshal (grub_tpm2_buffer_t buffer,
    ++                                     TPMS_CREATION_DATA *data);
    ++
    ++void
    ++grub_tpm2_mu_TPM2B_CREATION_DATA_Unmarshal (grub_tpm2_buffer_t buffer,
    ++                                      TPM2B_CREATION_DATA *data);
    ++
    ++void
    ++grub_tpm2_mu_TPM2B_PRIVATE_Unmarshal (grub_tpm2_buffer_t buffer,
    ++                                TPM2B_PRIVATE* private);
    ++
    ++void
    ++grub_tpm2_mu_TPM2B_SENSITIVE_DATA_Unmarshal (grub_tpm2_buffer_t buffer,
    ++                                       TPM2B_SENSITIVE_DATA *data);
    ++
    ++void
    ++grub_tpm2_mu_TPM2B_PUBLIC_KEY_RSA_Unmarshal (grub_tpm2_buffer_t buffer,
    ++                                       TPM2B_PUBLIC_KEY_RSA *rsa);
    ++
    ++void
    ++grub_tpm2_mu_TPM2B_ECC_PARAMETER_Unmarshal (grub_tpm2_buffer_t buffer,
    ++                                      TPM2B_ECC_PARAMETER *param);
    ++
    ++void
    ++grub_tpm2_mu_TPMA_OBJECT_Unmarshal (grub_tpm2_buffer_t buffer,
     +                              TPMA_OBJECT *p);
     +
     +void
    -+grub_tpm2_mu_TPMS_SCHEME_HMAC_Unmarshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMS_SCHEME_HMAC_Unmarshal (grub_tpm2_buffer_t buffer,
     +                                   TPMS_SCHEME_HMAC *p);
     +
     +void
    -+grub_tpm2_mu_TPMS_SCHEME_XOR_Unmarshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMS_SCHEME_XOR_Unmarshal (grub_tpm2_buffer_t buffer,
     +                                  TPMS_SCHEME_XOR *p);
     +
     +void
    -+grub_tpm2_mu_TPMU_SCHEME_KEYEDHASH_Unmarshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMU_SCHEME_KEYEDHASH_Unmarshal (grub_tpm2_buffer_t buffer,
     +                                        TPMI_ALG_KEYEDHASH_SCHEME scheme,
     +                                        TPMU_SCHEME_KEYEDHASH *p);
     +
     +void
    -+grub_tpm2_mu_TPMT_KEYEDHASH_SCHEME_Unmarshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMT_KEYEDHASH_SCHEME_Unmarshal (grub_tpm2_buffer_t buffer,
     +                                        TPMT_KEYEDHASH_SCHEME *p);
     +
     +void
    -+grub_tpm2_mu_TPMS_KEYEDHASH_PARMS_Unmarshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMS_KEYEDHASH_PARMS_Unmarshal (grub_tpm2_buffer_t buffer,
     +                                       TPMS_KEYEDHASH_PARMS *p);
     +
     +void
    -+grub_tpm2_mu_TPMU_SYM_KEY_BITS_Unmarshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMU_SYM_KEY_BITS_Unmarshal (grub_tpm2_buffer_t buffer,
     +                                    TPMI_ALG_SYM_OBJECT algorithm,
     +                                    TPMU_SYM_KEY_BITS *p);
     +
     +void
    -+grub_tpm2_mu_TPMU_SYM_MODE_Unmarshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMU_SYM_MODE_Unmarshal (grub_tpm2_buffer_t buffer,
     +                                TPMI_ALG_SYM_OBJECT algorithm,
     +                                TPMU_SYM_MODE *p);
     +
     +void
    -+grub_tpm2_mu_TPMT_SYM_DEF_OBJECT_Unmarshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMT_SYM_DEF_OBJECT_Unmarshal (grub_tpm2_buffer_t buffer,
     +                                      TPMT_SYM_DEF_OBJECT *p);
     +
     +void
    -+grub_tpm2_mu_TPMS_SYMCIPHER_PARMS_Unmarshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMS_SYMCIPHER_PARMS_Unmarshal (grub_tpm2_buffer_t buffer,
     +                                       TPMS_SYMCIPHER_PARMS *p);
     +
     +void
    -+grub_tpm2_mu_TPMU_ASYM_SCHEME_Unmarshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMU_ASYM_SCHEME_Unmarshal (grub_tpm2_buffer_t buffer,
     +                                   TPMI_ALG_RSA_DECRYPT scheme,
     +                                   TPMU_ASYM_SCHEME *p);
     +
     +void
    -+grub_tpm2_mu_TPMT_RSA_SCHEME_Unmarshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMT_RSA_SCHEME_Unmarshal (grub_tpm2_buffer_t buffer,
     +                                  TPMT_RSA_SCHEME *p);
     +
     +void
    -+grub_tpm2_mu_TPMS_RSA_PARMS_Unmarshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMS_RSA_PARMS_Unmarshal (grub_tpm2_buffer_t buffer,
     +                                 TPMS_RSA_PARMS *p);
     +
     +void
    -+grub_tpm2_mu_TPMT_ECC_SCHEME_Unmarshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMT_ECC_SCHEME_Unmarshal (grub_tpm2_buffer_t buffer,
     +                                  TPMT_ECC_SCHEME *p);
     +
     +void
    -+grub_tpm2_mu_TPMU_KDF_SCHEME_Unmarshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMU_KDF_SCHEME_Unmarshal (grub_tpm2_buffer_t buffer,
     +                                  TPMI_ALG_KDF scheme,
     +                                  TPMU_KDF_SCHEME *p);
     +
     +void
    -+grub_tpm2_mu_TPMT_KDF_SCHEME_Unmarshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMT_KDF_SCHEME_Unmarshal (grub_tpm2_buffer_t buffer,
     +                                  TPMT_KDF_SCHEME *p);
     +
     +void
    -+grub_tpm2_mu_TPMS_ECC_PARMS_Unmarshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMS_ECC_PARMS_Unmarshal (grub_tpm2_buffer_t buffer,
     +                                 TPMS_ECC_PARMS *p);
     +
     +void
    -+grub_tpm2_mu_TPMU_PUBLIC_PARMS_Unmarshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMU_PUBLIC_PARMS_Unmarshal (grub_tpm2_buffer_t buffer,
     +                                    grub_uint32_t type,
     +                                    TPMU_PUBLIC_PARMS *p);
     +
     +void
    -+grub_tpm2_mu_TPMS_ECC_POINT_Unmarshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMS_ECC_POINT_Unmarshal (grub_tpm2_buffer_t buffer,
     +                                 TPMS_ECC_POINT *p);
     +
     +void
    -+grub_tpm2_mu_TPMU_PUBLIC_ID_Unmarshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMU_PUBLIC_ID_Unmarshal (grub_tpm2_buffer_t buffer,
     +                                 TPMI_ALG_PUBLIC type,
     +                                 TPMU_PUBLIC_ID *p);
     +
     +void
    -+grub_tpm2_mu_TPMT_PUBLIC_Unmarshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMT_PUBLIC_Unmarshal (grub_tpm2_buffer_t buffer,
     +                              TPMT_PUBLIC *p);
     +
     +void
    -+grub_tpm2_mu_TPM2B_PUBLIC_Unmarshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPM2B_PUBLIC_Unmarshal (grub_tpm2_buffer_t buffer,
     +                               TPM2B_PUBLIC *p);
     +
     +void
    -+grub_tpm2_mu_TPMS_NV_PUBLIC_Unmarshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMS_NV_PUBLIC_Unmarshal (grub_tpm2_buffer_t buffer,
     +                                 TPMS_NV_PUBLIC *p);
     +
     +void
    -+grub_tpm2_mu_TPM2B_NV_PUBLIC_Unmarshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPM2B_NV_PUBLIC_Unmarshal (grub_tpm2_buffer_t buffer,
     +                                  TPM2B_NV_PUBLIC *p);
     +
     +void
    -+grub_tpm2_mu_TPM2B_NAME_Unmarshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPM2B_NAME_Unmarshal (grub_tpm2_buffer_t buffer,
     +                             TPM2B_NAME *n);
     +
     +void
    -+grub_tpm2_mu_TPMS_TAGGED_PROPERTY_Unmarshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMS_TAGGED_PROPERTY_Unmarshal (grub_tpm2_buffer_t buffer,
     +                                       TPMS_TAGGED_PROPERTY* property);
     +
     +void
    -+grub_tpm2_mu_TPMS_CAPABILITY_DATA_tpmProperties_Unmarshal 
(grub_tpm2_buffer_t buf,
    -+                                                     
TPMS_CAPABILITY_DATA* capabilityData);
    ++grub_tpm2_mu_TPMT_TK_CREATION_Unmarshal (grub_tpm2_buffer_t buffer,
    ++                                   TPMT_TK_CREATION *p);
    ++
    ++void
    ++grub_tpm2_mu_TPMT_TK_HASHCHECK_Unmarshal (grub_tpm2_buffer_t buffer,
    ++                                          TPMT_TK_HASHCHECK *p);
     +
     +void
    -+grub_tpm2_mu_TPMT_TK_CREATION_Unmarshal (grub_tpm2_buffer_t buf,
    -+                                   TPMT_TK_CREATION *p);
    ++grub_tpm2_mu_TPMT_TK_VERIFIED_Unmarshal (grub_tpm2_buffer_t buffer,
    ++                                         TPMT_TK_VERIFIED *p);
     +
     +void
    -+grub_tpm2_mu_TPMS_PCR_SELECTION_Unmarshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPMS_PCR_SELECTION_Unmarshal (grub_tpm2_buffer_t buffer,
     +                                     TPMS_PCR_SELECTION* pcrSelection);
     +
     +void
    -+grub_tpm2_mu_TPML_PCR_SELECTION_Unmarshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPML_PCR_SELECTION_Unmarshal (grub_tpm2_buffer_t buffer,
     +                                     TPML_PCR_SELECTION* pcrSelection);
     +
     +void
    -+grub_tpm2_mu_TPML_DIGEST_Unmarshal (grub_tpm2_buffer_t buf,
    ++grub_tpm2_mu_TPML_DIGEST_Unmarshal (grub_tpm2_buffer_t buffer,
     +                              TPML_DIGEST* digest);
     +
    ++void
    ++grub_tpm2_mu_TPMS_SIGNATURE_RSA_Unmarshal (grub_tpm2_buffer_t buffer,
    ++                                           TPMS_SIGNATURE_RSA *p);
    ++
    ++void
    ++grub_tpm2_mu_TPMS_SIGNATURE_ECC_Unmarshal (grub_tpm2_buffer_t buffer,
    ++                                           TPMS_SIGNATURE_ECC *p);
    ++
    ++void
    ++grub_tpm2_mu_TPMU_HA_Unmarshal (grub_tpm2_buffer_t buffer,
    ++                                TPMI_ALG_HASH hashAlg,
    ++                                TPMU_HA *p);
    ++
    ++void
    ++grub_tpm2_mu_TPMT_HA_Unmarshal (grub_tpm2_buffer_t buffer,
    ++                                TPMT_HA *p);
    ++
    ++void
    ++grub_tpm2_mu_TPMU_SIGNATURE_Unmarshal (grub_tpm2_buffer_t buffer,
    ++                                       TPMI_ALG_SIG_SCHEME sigAlg,
    ++                                       TPMU_SIGNATURE *p);
    ++
    ++void
    ++grub_tpm2_mu_TPMT_SIGNATURE_Unmarshal (grub_tpm2_buffer_t buffer,
    ++                                       TPMT_SIGNATURE *p);
    ++
     +#endif /* ! GRUB_TPM2_MU_HEADER */
     
      ## include/grub/tpm2/tcg2.h (new) ##
10:  5602679b9 ! 11:  5ecd4ef2f key_protector: Add TPM2 Key Protector
    @@ Commit message
         sequence is always based on the PCR selection from the command
         parameters.
     
    -    Currently, there is only one supported policy command: TPM2_PolicyPCR.
    -    The command set can be extended to support advanced features, such as
    -    authorized policy, in the future.
    +    This commit only supports one policy command: TPM2_PolicyPCR. The
    +    command set will be extended to support advanced features, such as
    +    authorized policy, in the later commits.
     
         Signed-off-by: Hernan Gatta <hegatta@linux.microsoft.com>
         Signed-off-by: Gary Lin <glin@suse.com>
    @@ grub-core/tpm2/args.c (new)
     +
     +grub_err_t
     +grub_tpm2_protector_parse_asymmetric (const char *value,
    -+                                TPM_ALG_ID *asymmetric,
    -+                                TPM_KEY_BITS *rsa_bits,
    -+                                TPM_ECC_CURVE *ecc_curve)
    ++                                grub_srk_type_t *srk_type)
     +{
     +  if (grub_strcasecmp (value, "ECC") == 0 ||
     +      grub_strcasecmp (value, "ECC_NIST_P256") == 0)
     +    {
    -+      *asymmetric = TPM_ALG_ECC;
    -+      *ecc_curve = TPM_ECC_NIST_P256;
    ++      srk_type->type = TPM_ALG_ECC;
    ++      srk_type->detail.ecc_curve = TPM_ECC_NIST_P256;
     +    }
     +  else if (grub_strcasecmp (value, "RSA") == 0 ||
     +     grub_strcasecmp (value, "RSA2048") == 0)
     +    {
    -+      *asymmetric = TPM_ALG_RSA;
    -+      *rsa_bits = 2048;
    ++      srk_type->type = TPM_ALG_RSA;
    ++      srk_type->detail.rsa_bits = 2048;
     +    }
     +  else if (grub_strcasecmp (value, "RSA3072") == 0)
     +    {
    -+      *asymmetric = TPM_ALG_RSA;
    -+      *rsa_bits = 3072;
    ++      srk_type->type = TPM_ALG_RSA;
    ++      srk_type->detail.rsa_bits = 3072;
     +    }
     +  else if (grub_strcasecmp (value, "RSA4096") == 0)
     +    {
    -+      *asymmetric = TPM_ALG_RSA;
    -+      *rsa_bits = 4096;
    ++      srk_type->type = TPM_ALG_RSA;
    ++      srk_type->detail.rsa_bits = 4096;
     +    }
     +  else if (grub_strcasecmp (value, "ECC_NIST_P384") == 0)
     +    {
    -+      *asymmetric = TPM_ALG_ECC;
    -+      *ecc_curve = TPM_ECC_NIST_P384;
    ++      srk_type->type = TPM_ALG_ECC;
    ++      srk_type->detail.ecc_curve = TPM_ECC_NIST_P384;
     +    }
     +  else if (grub_strcasecmp (value, "ECC_NIST_P521") == 0)
     +    {
    -+      *asymmetric = TPM_ALG_ECC;
    -+      *ecc_curve = TPM_ECC_NIST_P521;
    ++      srk_type->type = TPM_ALG_ECC;
    ++      srk_type->detail.ecc_curve = TPM_ECC_NIST_P521;
     +    }
     +  else if (grub_strcasecmp (value, "ECC_BN_P256") == 0)
     +    {
    -+      *asymmetric = TPM_ALG_ECC;
    -+      *ecc_curve = TPM_ECC_BN_P256;
    ++      srk_type->type = TPM_ALG_ECC;
    ++      srk_type->detail.ecc_curve = TPM_ECC_BN_P256;
     +    }
     +  else if (grub_strcasecmp (value, "ECC_BN_P638") == 0)
     +    {
    -+      *asymmetric = TPM_ALG_ECC;
    -+      *ecc_curve = TPM_ECC_BN_P638;
    ++      srk_type->type = TPM_ALG_ECC;
    ++      srk_type->detail.ecc_curve = TPM_ECC_BN_P638;
     +    }
     +  else if (grub_strcasecmp (value, "ECC_SM2_P256") == 0)
     +    {
    -+      *asymmetric = TPM_ALG_ECC;
    -+      *ecc_curve = TPM_ECC_SM2_P256;
    ++      srk_type->type = TPM_ALG_ECC;
    ++      srk_type->detail.ecc_curve = TPM_ECC_SM2_P256;
     +    }
     +  else
     +    return grub_error (GRUB_ERR_OUT_OF_RANGE,
    @@ grub-core/tpm2/module.c (new)
     +  grub_tpm2_protector_mode_t mode;
     +  grub_uint8_t pcrs[TPM_MAX_PCRS];
     +  grub_uint8_t pcr_count;
    -+  TPM_ALG_ID asymmetric;
    -+  TPM_KEY_BITS rsa_bits;
    -+  TPM_ECC_CURVE ecc_curve;
    ++  grub_srk_type_t srk_type;
     +  TPM_ALG_ID bank;
     +  const char *tpm2key;
     +  const char *keyfile;
    @@ grub-core/tpm2/module.c (new)
     +  err = GRUB_ERR_NONE;
     +
     +error:
    -+  grub_file_close (file);
    ++  if (file != NULL)
    ++    grub_file_close (file);
     +
     +  return err;
     +}
    @@ grub-core/tpm2/module.c (new)
     +  buf.size = sealed_key_size;
     +
     +  grub_tpm2_mu_TPM2B_PUBLIC_Unmarshal (&buf, &sk->public);
    -+  grub_tpm2_mu_TPM2B_Unmarshal (&buf, (TPM2B *)&sk->private);
    ++  grub_tpm2_mu_TPM2B_PRIVATE_Unmarshal (&buf, &sk->private);
     +
     +  if (buf.error)
     +    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Malformed TPM wire key 
file"));
    @@ grub-core/tpm2/module.c (new)
     +  err = grub_tpm2key_get_parent (tpm2key, &parent_tmp);
     +  if (err != GRUB_ERR_NONE)
     +    goto error;
    ++
    ++  /*  The parent handle should be either PERMANENT or PERSISTENT. */
    ++  if (!TPM_HT_IS_PERMANENT (parent_tmp) && !TPM_HT_IS_PERSISTENT 
(parent_tmp))
    ++    {
    ++      err = GRUB_ERR_OUT_OF_RANGE;
    ++      goto error;
    ++    }
    ++
     +  *parent = parent_tmp;
     +
     +  /* Retrieve the public part of the sealed key */
    @@ grub-core/tpm2/module.c (new)
     +  buf.offset = 0;
     +
     +  grub_tpm2_mu_TPM2B_PUBLIC_Unmarshal (&buf, &sk->public);
    -+  grub_tpm2_mu_TPM2B_Unmarshal (&buf, (TPM2B *)&sk->private);
    ++  grub_tpm2_mu_TPM2B_PRIVATE_Unmarshal (&buf, &sk->private);
     +
     +  if (buf.error)
     +    {
    @@ grub-core/tpm2/module.c (new)
     +  return err;
     +}
     +
    ++/* Check if the SRK exists in the specified handle */
     +static grub_err_t
    -+grub_tpm2_protector_srk_get (const struct grub_tpm2_protector_context 
*ctx,
    -+                       TPM_HANDLE parent, TPM_HANDLE *srk)
    ++grub_tpm2_protector_srk_check (const TPM_HANDLE srk_handle)
     +{
     +  TPM_RC rc;
     +  TPM2B_PUBLIC public;
    ++
    ++  /* Find SRK */
    ++  rc = TPM2_ReadPublic (srk_handle, NULL, &public);
    ++  if (rc == TPM_RC_SUCCESS)
    ++    return GRUB_ERR_NONE;
    ++
    ++  return grub_error (GRUB_ERR_BAD_ARGUMENT,
    ++               N_("Failed to retrieve SRK from 0x%x (TPM2_ReadPublic: 
0x%x)"),
    ++               srk_handle, rc);
    ++}
    ++
    ++/* Get the SRK with the template */
    ++static grub_err_t
    ++grub_tpm2_protector_srk_get (const grub_srk_type_t srk_type,
    ++                       const TPM_HANDLE parent,
    ++                       TPM_HANDLE *srk_handle)
    ++{
    ++  TPM_RC rc;
    ++  TPMT_PUBLIC_PARMS parms = { 0 };
     +  TPMS_AUTH_COMMAND authCommand = { 0 };
     +  TPM2B_SENSITIVE_CREATE inSensitive = { 0 };
     +  TPM2B_PUBLIC inPublic = { 0 };
    @@ grub-core/tpm2/module.c (new)
     +  TPM2B_DIGEST creationHash = { 0 };
     +  TPMT_TK_CREATION creationTicket = { 0 };
     +  TPM2B_NAME srkName = { 0 };
    -+  TPM_HANDLE srkHandle;
    -+
    -+  if (ctx->srk != 0)
    -+    {
    -+      /* Find SRK */
    -+      rc = TPM2_ReadPublic (ctx->srk, NULL, &public);
    -+      if (rc == TPM_RC_SUCCESS)
    -+  {
    -+    *srk = ctx->srk;
    -+    return GRUB_ERR_NONE;
    -+  }
    ++  TPM_HANDLE tmp_handle = 0;
     +
    -+      return grub_error (GRUB_ERR_BAD_DEVICE,
    -+                   N_("Failed to retrieve SRK (TPM2_ReadPublic: 0x%x)"),
    -+                   rc);
    -+    }
    -+
    -+  /* Create SRK */
    -+  authCommand.sessionHandle = TPM_RS_PW;
    -+  inPublic.publicArea.type = ctx->asymmetric;
    -+  inPublic.publicArea.nameAlg  = TPM_ALG_SHA256;
    ++  inPublic.publicArea.type = srk_type.type;
    ++  inPublic.publicArea.nameAlg = TPM_ALG_SHA256;
     +  inPublic.publicArea.objectAttributes.restricted = 1;
     +  inPublic.publicArea.objectAttributes.userWithAuth = 1;
     +  inPublic.publicArea.objectAttributes.decrypt = 1;
    @@ grub-core/tpm2/module.c (new)
     +  inPublic.publicArea.objectAttributes.sensitiveDataOrigin = 1;
     +  inPublic.publicArea.objectAttributes.noDA = 1;
     +
    -+  if (ctx->asymmetric == TPM_ALG_RSA)
    ++  if (srk_type.type == TPM_ALG_RSA)
     +    {
     +      inPublic.publicArea.parameters.rsaDetail.symmetric.algorithm = 
TPM_ALG_AES;
     +      inPublic.publicArea.parameters.rsaDetail.symmetric.keyBits.aes = 
128;
     +      inPublic.publicArea.parameters.rsaDetail.symmetric.mode.aes = 
TPM_ALG_CFB;
     +      inPublic.publicArea.parameters.rsaDetail.scheme.scheme = 
TPM_ALG_NULL;
    -+      inPublic.publicArea.parameters.rsaDetail.keyBits = ctx->rsa_bits;
    ++      inPublic.publicArea.parameters.rsaDetail.keyBits = 
srk_type.detail.rsa_bits;
     +      inPublic.publicArea.parameters.rsaDetail.exponent = 0;
     +    }
    -+  else if (ctx->asymmetric == TPM_ALG_ECC)
    ++  else if (srk_type.type == TPM_ALG_ECC)
     +    {
     +      inPublic.publicArea.parameters.eccDetail.symmetric.algorithm = 
TPM_ALG_AES;
     +      inPublic.publicArea.parameters.eccDetail.symmetric.keyBits.aes = 
128;
     +      inPublic.publicArea.parameters.eccDetail.symmetric.mode.aes = 
TPM_ALG_CFB;
     +      inPublic.publicArea.parameters.eccDetail.scheme.scheme = 
TPM_ALG_NULL;
    -+      inPublic.publicArea.parameters.eccDetail.curveID = ctx->ecc_curve;
    ++      inPublic.publicArea.parameters.eccDetail.curveID = 
srk_type.detail.ecc_curve;
     +      inPublic.publicArea.parameters.eccDetail.kdf.scheme = TPM_ALG_NULL;
     +    }
     +  else
     +    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Unknown SRK 
algorithm"));
     +
    ++  /* Test the parameters before SRK generation */
    ++  parms.type = srk_type.type;
    ++  grub_memcpy (&parms.parameters, &inPublic.publicArea.parameters,
    ++         sizeof (TPMU_PUBLIC_PARMS));
    ++
    ++  rc = TPM2_TestParms (&parms, NULL);
    ++  if (rc != TPM_RC_SUCCESS)
    ++    return grub_error (GRUB_ERR_BAD_ARGUMENT,
    ++                 N_("Unsupported SRK template (TPM2_TestParms: 0x%x)"),
    ++                 rc);
    ++
    ++  /* Create SRK */
    ++  authCommand.sessionHandle = TPM_RS_PW;
     +  rc = TPM2_CreatePrimary (parent, &authCommand, &inSensitive, &inPublic,
    -+                     &outsideInfo, &creationPcr, &srkHandle, &outPublic,
    ++                     &outsideInfo, &creationPcr, &tmp_handle, &outPublic,
     +                     &creationData, &creationHash, &creationTicket,
     +                     &srkName, NULL);
     +  if (rc != TPM_RC_SUCCESS)
    @@ grub-core/tpm2/module.c (new)
     +                 N_("Could not create SRK (TPM2_CreatePrimary: 0x%x)"),
     +                 rc);
     +
    -+  *srk = srkHandle;
    ++  *srk_handle = tmp_handle;
    ++
    ++  return GRUB_ERR_NONE;
    ++}
    ++
    ++/* Load the SRK from the persistent handle or create one with a given 
type of
    ++   template, and then associate the sealed key with the SRK
    ++   Return values:
    ++   * GRUB_ERR_NONE: Everything is fine.
    ++   * GRUB_ERR_BAD_ARGUMENT: The SRK doesn't match. Try another one.
    ++   * Other: Something goes wrong.
    ++*/
    ++static grub_err_t
    ++grub_tpm2_protector_srk_load (const grub_srk_type_t srk_type,
    ++                        const TPM2_SEALED_KEY *sealed_key,
    ++                        const TPM_HANDLE parent,
    ++                        TPM_HANDLE *sealed_handle,
    ++                        TPM_HANDLE *srk_handle)
    ++{
    ++  TPMS_AUTH_COMMAND authCmd = { 0 };
    ++  TPM2B_NAME name = { 0 };
    ++  TPM_RC rc;
    ++  grub_err_t err;
    ++
    ++  if (srk_handle == NULL)
    ++    return GRUB_ERR_BUG;
    ++
    ++  if (*srk_handle != 0)
    ++    {
    ++      err = grub_tpm2_protector_srk_check (*srk_handle);
    ++      if (err != GRUB_ERR_NONE)
    ++  return err;
    ++    }
    ++  else
    ++    {
    ++      err = grub_tpm2_protector_srk_get (srk_type, parent, srk_handle);
    ++      if (err != GRUB_ERR_NONE)
    ++  return err;
    ++    }
    ++
    ++  /* Load the sealed key and associate it with the SRK */
    ++  authCmd.sessionHandle = TPM_RS_PW;
    ++  rc = TPM2_Load (*srk_handle, &authCmd, &sealed_key->private, 
&sealed_key->public,
    ++            sealed_handle, &name, NULL);
    ++  /* If TPM2_Load returns (TPM_RC_INTEGRITY | TPM_RC_P | TPM_RC_1), then 
it
    ++     implies the wrong SRK is used. */
    ++  if (rc == (TPM_RC_INTEGRITY | TPM_RC_P | TPM_RC_1))
    ++    {
    ++      err = grub_error (GRUB_ERR_BAD_ARGUMENT, N_("SRK not matched"));
    ++      goto error;
    ++    }
    ++  else if (rc != TPM_RC_SUCCESS)
    ++    {
    ++      err = grub_error (GRUB_ERR_BAD_DEVICE,
    ++                  N_("Failed to load sealed key (TPM2_Load: 0x%x)"),
    ++                  rc);
    ++      goto error;
    ++    }
     +
     +  return GRUB_ERR_NONE;
    ++
    ++error:
    ++  if (!TPM_HT_IS_PERSISTENT (*srk_handle))
    ++    TPM2_FlushContext (*srk_handle);
    ++
    ++  return err;
    ++}
    ++
    ++static const char *
    ++srk_type_to_name (grub_srk_type_t srk_type)
    ++{
    ++  if (srk_type.type == TPM_ALG_ECC)
    ++    {
    ++      switch (srk_type.detail.ecc_curve)
    ++        {
    ++  case TPM_ECC_NIST_P256:
    ++    return "ECC_NIST_P256";
    ++        }
    ++    }
    ++  else if (srk_type.type == TPM_ALG_RSA)
    ++   {
    ++      switch (srk_type.detail.rsa_bits)
    ++  {
    ++    case 2048:
    ++      return "RSA2048";
    ++    case 3072:
    ++      return "RSA3072";
    ++    case 4096:
    ++      return "RSA4096";
    ++  }
    ++   }
    ++
    ++  return "Unknown";
    ++}
    ++
    ++static grub_err_t
    ++grub_tpm2_protector_load_key (const struct grub_tpm2_protector_context 
*ctx,
    ++                        const TPM2_SEALED_KEY *sealed_key,
    ++                        const TPM_HANDLE parent_handle,
    ++                        TPM_HANDLE *sealed_handle,
    ++                        TPM_HANDLE *srk_handle)
    ++{
    ++  grub_err_t err;
    ++  int i;
    ++  grub_srk_type_t fallback_srks[] = {
    ++    {
    ++      .type = TPM_ALG_ECC,
    ++      .detail.ecc_curve = TPM_ECC_NIST_P256,
    ++    },
    ++    {
    ++      .type = TPM_ALG_RSA,
    ++      .detail.rsa_bits = 2048,
    ++    },
    ++    {
    ++      .type = TPM_ALG_RSA,
    ++      .detail.rsa_bits = 3072,
    ++    },
    ++    {
    ++      .type = TPM_ALG_ERROR,
    ++    }
    ++  };
    ++
    ++  /* Try the given persistent SRK if exists */
    ++  if (*srk_handle != 0)
    ++    {
    ++      err = grub_tpm2_protector_srk_load (ctx->srk_type, sealed_key,
    ++                                    parent_handle, sealed_handle,
    ++                                    srk_handle);
    ++      if (err != GRUB_ERR_BAD_ARGUMENT)
    ++  return err;
    ++
    ++      grub_print_error ();
    ++      grub_printf_ (N_("Trying the specified SRK algorithm: %s\n"),
    ++              srk_type_to_name (ctx->srk_type));
    ++      grub_errno = GRUB_ERR_NONE;
    ++      *srk_handle = 0;
    ++    }
    ++
    ++  /* Try the specified algorithm for the SRK template */
    ++  if (*srk_handle == 0)
    ++    {
    ++      err = grub_tpm2_protector_srk_load (ctx->srk_type, sealed_key,
    ++                                    parent_handle, sealed_handle,
    ++                                    srk_handle);
    ++      if (err != GRUB_ERR_BAD_ARGUMENT)
    ++  return err;
    ++
    ++      grub_print_error ();
    ++      grub_errno = GRUB_ERR_NONE;
    ++      *srk_handle = 0;
    ++    }
    ++
    ++  /* Try all the fallback SRK templates */
    ++  for (i = 0; fallback_srks[i].type != TPM_ALG_ERROR; i++)
    ++    {
    ++      /* Skip the specified algorithm */
    ++      if (fallback_srks[i].type == ctx->srk_type.type &&
    ++    (fallback_srks[i].detail.rsa_bits == ctx->srk_type.detail.rsa_bits ||
    ++     fallback_srks[i].detail.ecc_curve == ctx->srk_type.detail.ecc_curve))
    ++  continue;
    ++
    ++      grub_printf_ (N_("Trying fallback %s template\n"),
    ++              srk_type_to_name (fallback_srks[i]));
    ++
    ++      *srk_handle = 0;
    ++
    ++      err = grub_tpm2_protector_srk_load (fallback_srks[i], sealed_key,
    ++                                    parent_handle, sealed_handle,
    ++                                    srk_handle);
    ++      if (err != GRUB_ERR_BAD_ARGUMENT)
    ++  return err;
    ++
    ++      grub_print_error ();
    ++      grub_errno = GRUB_ERR_NONE;
    ++  }
    ++
    ++  return err;
     +}
     +
     +static grub_err_t
    @@ grub-core/tpm2/module.c (new)
     +grub_tpm2_protector_srk_recover (const struct grub_tpm2_protector_context 
*ctx,
     +                           grub_uint8_t **key, grub_size_t *key_size)
     +{
    -+  TPMS_AUTH_COMMAND authCmd = { 0 };
     +  TPM2_SEALED_KEY sealed_key = { 0 };
    -+  TPM2B_NAME name = { 0 };
     +  void *file_bytes = NULL;
     +  grub_size_t file_size = 0;
     +  TPM_HANDLE parent_handle = 0;
    @@ grub-core/tpm2/module.c (new)
     +  tpm2key_policy_t policy_seq = NULL;
     +  tpm2key_authpolicy_t authpol = NULL;
     +  tpm2key_authpolicy_t authpol_seq = NULL;
    -+  TPM_RC rc;
     +  grub_err_t err;
     +
     +  /*
    @@ grub-core/tpm2/module.c (new)
     +  goto exit1;
     +    }
     +
    -+  /* Get the SRK to unseal the sealed key */
    -+  err = grub_tpm2_protector_srk_get (ctx, parent_handle, &srk_handle);
    ++  /* Set the SRK handle if it is specified with '--srk' or inside the key 
file */
    ++  if (ctx->srk != 0)
    ++    srk_handle = ctx->srk;
    ++  else if (TPM_HT_IS_PERSISTENT (parent_handle))
    ++    srk_handle = parent_handle;
    ++
    ++  /* Load the sealed key into TPM and associate it with the SRK */
    ++  err = grub_tpm2_protector_load_key (ctx, &sealed_key, parent_handle,
    ++                                &sealed_handle, &srk_handle);
     +  if (err != GRUB_ERR_NONE)
     +    goto exit1;
     +
    -+  /* Load the sealed key and associate it with the SRK */
    -+  authCmd.sessionHandle = TPM_RS_PW;
    -+  rc = TPM2_Load (srk_handle, &authCmd, &sealed_key.private, 
&sealed_key.public,
    -+            &sealed_handle, &name, NULL);
    -+  if (rc != TPM_RC_SUCCESS)
    -+    {
    -+      err = grub_error (GRUB_ERR_BAD_DEVICE,
    -+                  N_("Failed to load sealed key (TPM2_Load: 0x%x)"),
    -+                  rc);
    -+      goto exit2;
    -+    }
    -+
     +  /*
     +   * Set err to an error code to trigger the standalone policy sequence
     +   * if there is no authpolicy sequence
    @@ grub-core/tpm2/module.c (new)
     +  {
     +    err = grub_tpm2_protector_simple_policy_seq (ctx, &policy_seq);
     +    if (err != GRUB_ERR_NONE)
    -+      goto exit3;
    ++      goto exit2;
     +  }
     +
     +      err = grub_tpm2_protector_unseal (policy_seq, sealed_handle, key, 
key_size);
    @@ grub-core/tpm2/module.c (new)
     +  if (err == GRUB_ERR_NONE)
     +    while (grub_error_pop ());
     +
    -+exit3:
    ++exit2:
     +  TPM2_FlushContext (sealed_handle);
     +
    -+exit2:
    -+  TPM2_FlushContext (srk_handle);
    ++  if (!TPM_HT_IS_PERSISTENT (srk_handle))
    ++    TPM2_FlushContext (srk_handle);
     +
     +exit1:
     +  grub_tpm2key_free_policy_seq (policy_seq);
    @@ grub-core/tpm2/module.c (new)
     +    return grub_error (GRUB_ERR_BAD_ARGUMENT,
     +                 N_("In NV Index mode, an SRK cannot be specified"));
     +
    -+  if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_NV && ctx->asymmetric)
    ++  if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_NV && ctx->srk_type.type)
     +    return grub_error (GRUB_ERR_BAD_ARGUMENT,
     +                 N_("In NV Index mode, an asymmetric key type cannot be "
     +                    "specified"));
    @@ grub-core/tpm2/module.c (new)
     +
     +  if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_SRK)
     +    {
    -+      if (!ctx->asymmetric)
    ++      if (ctx->srk_type.type == TPM_ALG_ERROR)
     +        {
    -+    ctx->asymmetric = TPM_ALG_RSA;
    -+    ctx->rsa_bits = 2048;
    ++    ctx->srk_type.type = TPM_ALG_ECC;
    ++    ctx->srk_type.detail.ecc_curve = TPM_ECC_NIST_P256;
     +        }
     +    }
     +
    @@ grub-core/tpm2/module.c (new)
     +  if (state[OPTION_ASYMMETRIC].set)  /* asymmetric */
     +    {
     +      err = grub_tpm2_protector_parse_asymmetric 
(state[OPTION_ASYMMETRIC].arg,
    -+                                            
&grub_tpm2_protector_ctx.asymmetric,
    -+                                            
&grub_tpm2_protector_ctx.rsa_bits,
    -+                                            
&grub_tpm2_protector_ctx.ecc_curve);
    ++                                            
&grub_tpm2_protector_ctx.srk_type);
     +      if (err != GRUB_ERR_NONE)
     +  return err;
     +    }
    @@ include/grub/tpm2/internal/args.h (new)
     +#include <grub/err.h>
     +#include <grub/tpm2/tpm2.h>
     +
    ++struct grub_srk_type
    ++{
    ++  TPM_ALG_ID type;
    ++  union {
    ++    TPM_KEY_BITS rsa_bits;
    ++    TPM_ECC_CURVE ecc_curve;
    ++  } detail;
    ++};
    ++typedef struct grub_srk_type grub_srk_type_t;
    ++
     +grub_err_t
     +grub_tpm2_protector_parse_pcrs (char *value, grub_uint8_t *pcrs,
     +                          grub_uint8_t *pcr_count);
     +
     +grub_err_t
     +grub_tpm2_protector_parse_asymmetric (const char *value,
    -+                                TPM_ALG_ID *asymmetric,
    -+                                TPM_KEY_BITS *rsa_bits,
    -+                                TPM_ECC_CURVE *ecc_curve);
    ++                                grub_srk_type_t *srk_type);
     +
     +grub_err_t
     +grub_tpm2_protector_parse_bank (const char *value, TPM_ALG_ID *bank);
11:  b280029ad = 12:  94f0f74c6 cryptodisk: Support key protectors
12:  1cceb47a6 ! 13:  161d8c56f util/grub-protect: Add new tool
    @@ Commit message
     
         $ sudo grub-protect --action=add \
                             --protector=tpm2 \
    +                        --tpm2-pcrs=0,2,4,7,9 \
                             --tpm2key \
                             --tpm2-keyfile=luks-key \
                             --tpm2-outfile=/boot/efi/boot/grub2/sealed.tpm
    @@ Commit message
     
         $ sudo grub-protect --action=add \
                             --protector=tpm2 \
    +                        --tpm2-pcrs=0,2,4,7,9 \
                             --tpm2-keyfile=luks-key \
                             --tpm2-outfile=/boot/efi/boot/grub2/sealed.key
     
    @@ Commit message
     
         Or, for the raw sealed key:
     
    -    tpm2_key_protector_init --keyfile=(hd0,gpt1)/boot/grub2/sealed.key
    +    tpm2_key_protector_init --keyfile=(hd0,gpt1)/boot/grub2/sealed.key 
--pcrs=0,2,4,7,9
         cryptomount -u <SDB1_UUID> -P tpm2
     
    +    The benefit of using TPM 2.0 Key File is that the PCR set is already
    +    written in the key file, so there is no need to specify PCRs when
    +    invoking tpm2_key_protector_init.
    +
         Signed-off-by: Hernan Gatta <hegatta@linux.microsoft.com>
         Signed-off-by: Gary Lin <glin@suse.com>
     
    @@ util/grub-protect.c (new)
     +  const char *tpm2_device;
     +  grub_uint8_t tpm2_pcrs[TPM_MAX_PCRS];
     +  grub_uint8_t tpm2_pcr_count;
    -+  TPM_ALG_ID tpm2_asymmetric;
    -+  TPM_KEY_BITS rsa_bits;
    -+  TPM_ECC_CURVE ecc_curve;
    ++  grub_srk_type_t srk_type;
     +  TPM_ALG_ID tpm2_bank;
     +  TPM_HANDLE tpm2_srk;
     +  const char *tpm2_keyfile;
    @@ util/grub-protect.c (new)
     +    }
     +
     +  len = ftell (f);
    -+  if (len == 0)
    ++  if (len <= 0)
     +    {
     +       err = GRUB_ERR_FILE_READ_ERROR;
     +       goto exit1;
    @@ util/grub-protect.c (new)
     +  return err;
     +}
     +
    -+static grub_err_t
    -+grub_protect_get_grub_drive_for_file (const char *filepath, char **drive)
    -+{
    -+  grub_err_t err = GRUB_ERR_IO;
    -+  char *disk;
    -+  char **devices;
    -+  char *grub_dev;
    -+  char *grub_path;
    -+  char *efi_drive;
    -+  char *partition;
    -+  char *grub_drive;
    -+  grub_device_t dev;
    -+  grub_size_t grub_drive_len;
    -+  int n;
    -+
    -+  grub_path = grub_canonicalize_file_name (filepath);
    -+  if (grub_path == NULL)
    -+    goto exit1;
    -+
    -+  devices = grub_guess_root_devices (grub_path);
    -+  if (devices == NULL || devices[0] == NULL)
    -+    goto exit2;
    -+
    -+  disk = devices[0];
    -+
    -+  grub_util_pull_device (disk);
    -+
    -+  grub_dev = grub_util_get_grub_dev (disk);
    -+  if (grub_dev == NULL)
    -+    goto exit3;
    -+
    -+  dev = grub_device_open (grub_dev);
    -+  if (dev == NULL)
    -+    goto exit4;
    -+
    -+  efi_drive = grub_util_guess_efi_drive (disk);
    -+  if (efi_drive == NULL)
    -+    goto exit5;
    -+
    -+  partition = grub_partition_get_name (dev->disk->partition);
    -+  if (partition == NULL)
    -+    goto exit6;
    -+
    -+  grub_drive_len = grub_strlen (efi_drive) + grub_strlen (partition) + 3;
    -+  grub_drive = grub_malloc (grub_drive_len + 1);
    -+  if (grub_drive == NULL)
    -+    goto exit7;
    -+
    -+  n = grub_snprintf (grub_drive, grub_drive_len + 1, "(%s,%s)", efi_drive,
    -+               partition);
    -+  if (n != grub_drive_len)
    -+    goto exit8;
    -+
    -+  *drive = grub_drive;
    -+  grub_drive = NULL;
    -+  err = GRUB_ERR_NONE;
    -+
    -+exit8:
    -+  grub_free (grub_drive);
    -+
    -+exit7:
    -+  grub_free (partition);
    -+
    -+exit6:
    -+  grub_free (efi_drive);
    -+
    -+exit5:
    -+  grub_device_close (dev);
    -+
    -+exit4:
    -+  grub_free (grub_dev);
    -+
    -+exit3:
    -+  grub_free (devices);
    -+
    -+exit2:
    -+  grub_free (grub_path);
    -+
    -+exit1:
    -+  return err;
    -+}
    -+
     +grub_err_t
     +grub_tcg2_get_max_output_size (grub_size_t *size)
     +{
    @@ util/grub-protect.c (new)
     +  grub_protector_tpm2_fd = open (dev_node, O_RDWR);
     +  if (grub_protector_tpm2_fd == -1)
     +    {
    -+      fprintf (stderr, _("Could not open TPM device (Error: %u).\n"), 
errno);
    ++      fprintf (stderr, _("Could not open TPM device (%s).\n"), strerror 
(errno));
     +      return GRUB_ERR_FILE_NOT_FOUND;
     +    }
     +
    @@ util/grub-protect.c (new)
     +
     +  /* Create SRK */
     +  authCommand.sessionHandle = TPM_RS_PW;
    -+  inPublic.publicArea.type = args->tpm2_asymmetric;
    ++  inPublic.publicArea.type = args->srk_type.type;
     +  inPublic.publicArea.nameAlg  = TPM_ALG_SHA256;
     +  inPublic.publicArea.objectAttributes.restricted = 1;
     +  inPublic.publicArea.objectAttributes.userWithAuth = 1;
    @@ util/grub-protect.c (new)
     +  inPublic.publicArea.objectAttributes.sensitiveDataOrigin = 1;
     +  inPublic.publicArea.objectAttributes.noDA = 1;
     +
    -+  switch (args->tpm2_asymmetric)
    ++  switch (args->srk_type.type)
     +    {
     +    case TPM_ALG_RSA:
     +      inPublic.publicArea.parameters.rsaDetail.symmetric.algorithm = 
TPM_ALG_AES;
     +      inPublic.publicArea.parameters.rsaDetail.symmetric.keyBits.aes = 
128;
     +      inPublic.publicArea.parameters.rsaDetail.symmetric.mode.aes = 
TPM_ALG_CFB;
     +      inPublic.publicArea.parameters.rsaDetail.scheme.scheme = 
TPM_ALG_NULL;
    -+      inPublic.publicArea.parameters.rsaDetail.keyBits = args->rsa_bits;
    ++      inPublic.publicArea.parameters.rsaDetail.keyBits = 
args->srk_type.detail.rsa_bits;
     +      inPublic.publicArea.parameters.rsaDetail.exponent = 0;
     +      break;
     +
    @@ util/grub-protect.c (new)
     +      inPublic.publicArea.parameters.eccDetail.symmetric.keyBits.aes = 
128;
     +      inPublic.publicArea.parameters.eccDetail.symmetric.mode.aes = 
TPM_ALG_CFB;
     +      inPublic.publicArea.parameters.eccDetail.scheme.scheme = 
TPM_ALG_NULL;
    -+      inPublic.publicArea.parameters.eccDetail.curveID = args->ecc_curve;
    ++      inPublic.publicArea.parameters.eccDetail.curveID = 
args->srk_type.detail.ecc_curve;
     +      inPublic.publicArea.parameters.eccDetail.kdf.scheme = TPM_ALG_NULL;
     +      break;
     +
    @@ util/grub-protect.c (new)
     +      goto error;
     +    }
     +
    -+  /* Use TPM_RH_OWNER as the default parent handle */
    -+  parent = grub_cpu_to_be32 (TPM_RH_OWNER);
    ++  /* Use the SRK handle as the parent handle if specified
    ++     Otherwise, Use TPM_RH_OWNER as the default parent handle */
    ++  if (args->tpm2_srk != 0)
    ++    parent = grub_cpu_to_be32 (args->tpm2_srk);
    ++  else
    ++    parent = grub_cpu_to_be32 (TPM_RH_OWNER);
     +  ret = asn1_write_value (tpm2key, "parent", &parent, sizeof (parent));
     +  if (ret != ASN1_SUCCESS)
     +    {
    @@ util/grub-protect.c (new)
     +grub_protect_tpm2_add (struct grub_protect_args *args)
     +{
     +  grub_err_t err;
    -+  grub_uint8_t *key;
    ++  grub_uint8_t *key = NULL;
     +  grub_size_t key_size;
     +  TPM_HANDLE srk;
     +  TPM2B_DIGEST policy_digest;
     +  TPM2_SEALED_KEY sealed_key;
    -+  char *grub_drive = NULL;
    -+
    -+  grub_protect_get_grub_drive_for_file (args->tpm2_outfile, &grub_drive);
     +
     +  err = grub_protect_tpm2_open_device (args->tpm2_device);
     +  if (err != GRUB_ERR_NONE)
    @@ util/grub-protect.c (new)
     +    fprintf (stderr,
     +       _("Input key is too long, maximum allowed size is %u bytes.\n"),
     +       TPM_MAX_SYM_DATA);
    -+    return GRUB_ERR_OUT_OF_RANGE;
    ++    err = GRUB_ERR_OUT_OF_RANGE;
    ++    goto exit2;
     +  }
     +
     +  err = grub_protect_tpm2_get_srk (args, &srk);
    @@ util/grub-protect.c (new)
     +  if (err != GRUB_ERR_NONE)
     +    goto exit3;
     +
    -+  if (grub_drive)
    -+    {
    -+      printf (_("GRUB drive for the sealed key file: %s\n"), grub_drive);
    -+      grub_free (grub_drive);
    -+    }
    -+  else
    -+    {
    -+      fprintf (stderr,
    -+         _("Warning: Could not determine GRUB drive for sealed key "
    -+           "file.\n"));
    -+      err = GRUB_ERR_NONE;
    -+    }
    -+
     +exit3:
     +  TPM2_FlushContext (srk);
     +
    @@ util/grub-protect.c (new)
     +    args->tpm2_pcr_count = 1;
     +  }
     +
    -+      if (args->tpm2_asymmetric == TPM_ALG_ERROR)
    ++      if (args->srk_type.type == TPM_ALG_ERROR)
     +  {
    -+    args->tpm2_asymmetric = TPM_ALG_RSA;
    -+    args->rsa_bits = 2048;
    ++    args->srk_type.type = TPM_ALG_ECC;
    ++    args->srk_type.detail.rsa_bits = TPM_ECC_NIST_P256;
     +  }
     +
     +      if (args->tpm2_bank == TPM_ALG_ERROR)
    @@ util/grub-protect.c (new)
     +    return EINVAL;
     +  }
     +
    -+      err = grub_tpm2_protector_parse_asymmetric (arg, 
&args->tpm2_asymmetric,
    -+                                            &args->rsa_bits, 
&args->ecc_curve);
    ++      err = grub_tpm2_protector_parse_asymmetric (arg, &args->srk_type);
     +      if (err != GRUB_ERR_NONE)
     +  {
     +    if (grub_errno != GRUB_ERR_NONE)
13:  7aa196b17 <  -:  --------- tpm2: Add TPM2 types, structures, and command 
constants
14:  843a0cb76 <  -:  --------- tpm2: Add more marshal/unmarshal functions
15:  043c77591 <  -:  --------- tpm2: Implement more TPM2 commands
16:  9e1565125 = 14:  c1deb7fe6 tpm2: Support authorized policy
17:  cb501a8a6 = 15:  abb4c9461 tpm2: Implement NV index
18:  f360a6676 = 16:  1f9d2b3a2 cryptodisk: Fallback to passphrase
19:  60058fd98 = 17:  976072355 cryptodisk: wipe out the cached keys from 
protectors
20:  25709b60c = 18:  188abeb62 diskfilter: look up cryptodisk devices first
21:  35854d3cd ! 19:  62e5e2c43 tpm2: Enable tpm2 module for grub-emu
    @@ Commit message
         the host.
     
         Since grub-emu can directly access the device node on host, it's easy 
to
    -    implement the essential TCG2 command with the standard read/write
    -    functions and enable the commands from tpm2 module for grub-emu, so 
that
    -    we can further test TPM key unsealing with grub-emu.
    +    implement the essential TCG2 command submission function with the
    +    read/write functions and enable tpm2 module for grub-emu, so that we 
can
    +    further test TPM key unsealing with grub-emu.
     
         Signed-off-by: Gary Lin <glin@suse.com>
     
22:  626435733 ! 20:  ef7d48126 tests: Add tpm2_test
    @@ Metadata
      ## Commit message ##
         tests: Add tpm2_test
     
    -    For TPM 2.0 TSS stack, the TCG2 command sending function is the only
    +    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, not only a simple grub-shell rescue
    +    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. The LUKS password is sealed by
    -    grub-protect against PCR 0 and 1. The last step is to launch grub-emu 
to
    -    load the LUKS image, try to mount the image with 
tpm2_key_protector_init
    -    and cryptomount, and verify the result.
    +    swtpm_cuse and PCR 0 and 1 are extended.
    +
    +    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.
     
    @@ tests/tpm2_test.in (new)
     +    exit $ret
     +fi
     +
    -+# Seal the password with grub-protect
    -+grub-protect \
    -+  --tpm2-device=${tpm2dev} \
    -+  --action=add \
    -+  --protector=tpm2 \
    -+  --tpm2key \
    -+  --tpm2-asymmetric=RSA2048 \
    -+  --tpm2-bank=sha256 \
    -+  --tpm2-pcrs=0,1 \
    -+  --tpm2-keyfile=${lukskeyfile} \
    -+  --tpm2-outfile=${sealedkey}
    -+ret=$?
    -+if [ "$ret" -ne 0 ]; then
    ++tpm2_seal_unseal() {
    ++    local tpm2_alg="$1"
    ++    local handle_type="$2"
    ++    local srk_test="$3"
    ++
    ++    local grub_tpm2_alg=${tpm2_alg}
    ++
    ++    local extra_opt=""
    ++    local extra_grub_opt=""
    ++
    ++    local persistent_handle="0x81000000"
    ++
    ++    if [ "${handle_type}" == "persistent" ]; then
    ++  extra_opt="--tpm2-srk=${persistent_handle}"
    ++    fi
    ++
    ++    # Seal the password with grub-protect
    ++    grub-protect ${extra_opt} \
    ++      --tpm2-device=${tpm2dev} \
    ++      --action=add \
    ++      --protector=tpm2 \
    ++      --tpm2key \
    ++      --tpm2-asymmetric=${tpm2_alg} \
    ++      --tpm2-bank=sha256 \
    ++      --tpm2-pcrs=0,1 \
    ++      --tpm2-keyfile=${lukskeyfile} \
    ++      --tpm2-outfile=${sealedkey}
    ++    ret=$?
    ++    if [ "$ret" -ne 0 ]; then
     +  echo "Failed to seal the secret key"
    -+  exit 1
    -+fi
    ++  return 1
    ++    fi
    ++
    ++    # Flip the asymmetric algorithm in grub.cfg to trigger fallback SRKs
    ++    if [ "${srk_test}" == "fallback_srk" ]; then
    ++        if [[ "${tpm2_alg}" == RSA* ]]; then
    ++            grub_tpm2_alg="ECC"
    ++        elif [[ "${tpm2_alg}" == ECC* ]]; then
    ++            grub_tpm2_alg="RSA"
    ++        fi
    ++    fi
     +
    -+# Write the TPM unsealing script
    -+cat > ${tpm2testdir}/testcase.cfg <<EOF
    ++    if [ "${handle_type}" != "persistent" ]; then
    ++  extra_grub_opt="-a ${grub_tpm2_alg}"
    ++    fi
    ++
    ++    # Write the TPM unsealing script
    ++    cat > ${tpm2testdir}/testcase.cfg <<EOF
     +loopback luks (host)${luksfile}
    -+tpm2_key_protector_init -T (host)${sealedkey}
    ++tpm2_key_protector_init -T (host)${sealedkey} ${extra_grub_opt}
     +if cryptomount -a --protector tpm2; then
     +    echo "${vtext}"
     +fi
     +EOF
     +
    -+# Test TPM unsealing with the same PCR
    -+${grubshell} --timeout=$timeout --grub-emu-opts="-t ${tpm2dev}" < 
${tpm2testdir}/testcase.cfg > ${testoutput} || ret=$?
    ++    # Test TPM unsealing with the same PCR
    ++    ${grubshell} --timeout=$timeout --grub-emu-opts="-t ${tpm2dev}" < 
${tpm2testdir}/testcase.cfg > ${testoutput}
    ++    ret=$?
    ++
    ++    # Remove the persistent handle
    ++    if [ "${handle_type}" == "persistent" ]; then
    ++  grub-protect \
    ++          --tpm2-device=${tpm2dev} \
    ++          --protector=tpm2 \
    ++          --action=remove \
    ++          --tpm2-srk=${persistent_handle} \
    ++          --tpm2-evict
    ++    fi
    ++
    ++    return $ret
    ++}
    ++
    ++tpm2_seal_unseal RSA transient no_fallback_srk
    ++ret=$?
    ++if [ "$ret" -eq 0 ]; then
    ++    if ! grep -q "^${vtext}$" "$testoutput"; then
    ++  echo "error: test not verified [`cat $testoutput`]" >&2
    ++  exit 1
    ++    fi
    ++else
    ++    echo "grub-emu exited with error: $ret" >&2
    ++    exit $ret
    ++fi
     +
    ++tpm2_seal_unseal ECC transient no_fallback_srk
    ++ret=$?
     +if [ "$ret" -eq 0 ]; then
     +    if ! grep -q "^${vtext}$" "$testoutput"; then
    -+        echo "error: test not verified [`cat $testoutput`]" >&2
    -+        exit 1
    ++  echo "error: test not verified [`cat $testoutput`]" >&2
    ++  exit 1
    ++    fi
    ++else
    ++    echo "grub-emu exited with error: $ret" >&2
    ++    exit $ret
    ++fi
    ++
    ++tpm2_seal_unseal RSA persistent no_fallback_srk
    ++ret=$?
    ++if [ "$ret" -eq 0 ]; then
    ++    if ! grep -q "^${vtext}$" "$testoutput"; then
    ++  echo "error: test not verified [`cat $testoutput`]" >&2
    ++  exit 1
    ++    fi
    ++else
    ++    echo "grub-emu exited with error: $ret" >&2
    ++    exit $ret
    ++fi
    ++
    ++tpm2_seal_unseal ECC persistent no_fallback_srk
    ++ret=$?
    ++if [ "$ret" -eq 0 ]; then
    ++    if ! grep -q "^${vtext}$" "$testoutput"; then
    ++  echo "error: test not verified [`cat $testoutput`]" >&2
    ++  exit 1
    ++    fi
    ++else
    ++    echo "grub-emu exited with error: $ret" >&2
    ++    exit $ret
    ++fi
    ++
    ++tpm2_seal_unseal RSA transient fallback_srk
    ++ret=$?
    ++if [ "$ret" -eq 0 ]; then
    ++    if ! grep -q "^${vtext}$" "$testoutput"; then
    ++  echo "error: test not verified [`cat $testoutput`]" >&2
    ++  exit 1
    ++    fi
    ++else
    ++    echo "grub-emu exited with error: $ret" >&2
    ++    exit $ret
    ++fi
    ++
    ++tpm2_seal_unseal ECC transient fallback_srk
    ++ret=$?
    ++if [ "$ret" -eq 0 ]; then
    ++    if ! grep -q "^${vtext}$" "$testoutput"; then
    ++  echo "error: test not verified [`cat $testoutput`]" >&2
    ++  exit 1
     +    fi
     +else
     +    echo "grub-emu exited with error: $ret" >&2
-- 
2.35.3




reply via email to

[Prev in Thread] Current Thread [Next in Thread]