grub-devel
[Top][All Lists]
Advanced

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

[PATCH v21 00/33] Automatic Disk Unlock with TPM2


From: Gary Lin
Subject: [PATCH v21 00/33] Automatic Disk Unlock with TPM2
Date: Mon, 4 Nov 2024 15:31:33 +0800

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

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 GRUB, 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~7,9-17 are grabbed from
Daniel Axtens's "appended signature secure boot support" (*3) to import
libtasn1 into GRUB. Besides, the libtasn1 version is upgraded to
4.19.0 instead of 4.16.0 in the original patch.

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

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

Patch 19~25 are based on 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
- 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 26 implements the authorized policy support.

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

Patch 28 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 29 and 30 fix the potential security issues spotted by Fabian Vogt.

Patch 31 and 32 implement the TPM2 key unsealing testcases.

Patch 33 documents TPM2 key protector including the new GRUB commands and
the user-space utility.

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/efi/grub/sealed.tpm

3. Unseal the key with the proper commands in grub.cfg:
   tpm2_key_protector_init --tpm2key=(hd0,gpt1)/efi/grub/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

v21:
- Updating the commit message of a asn1 test patch
- libtasn1 patches are created by the following repo against the
  libtasn1-4.19.0-base-v5 tag:
  https://github.com/lcp/grub2/tree/import-libtasn1-4.19.0-v5
- Adding the TPM response header struct to calculate the minimum size of
  the TPM 2.0 response
- Fixing the grub_error messages
- Marking some error messages for translation
- Adding 'extern' to the global functions of the tpm2 key protector
- Updating grub-protect
  - Adding more error messages
  - Commenting id-sealedkey OID
  - Amending the argument verification function
  - Fixing a comment
  - Fixing the exit value
- Updating the document

v20:
- https://lists.gnu.org/archive/html/grub-devel/2024-10/msg00266.html
- GIT repo: https://github.com/lcp/grub2/tree/tpm2-unlock-v20
- Rearranging the order of the libtasn1 patches
- libtasn1 patches are created by the following repo against the
  libtasn1-4.19.0-base-v4 tag:
  https://github.com/lcp/grub2/tree/import-libtasn1-4.19.0-v4
- Excluding a libtasn1 testcase to avoid a potential gcc warning when
  'long' is the same as 'int'
- Replacing grub_swap_bytes32() with grub_cpu_to_be32() to make the TPM
  command size always big endian
- Correcting the GRUB path in the commit messages and the document
  - "/efi/grub2" => "/efi/grub"
  - "/boot/efi/boot/grub2" => "/boot/efi/efi/grub/"
  - "(hd0,gpt1)/boot/grub2/" => "(hd0,gpt1)/efi/grub"
- Removing the unnecessary "grub_errno = GRUB_ERR_NONE;"
- Replacing 'lu' with 'PRIuGRUB_UINT64_T' when setting the error
  message for 'uint64_t' to avoid the portability issue
- Removing the 'grub_' and 'GRUB_' prefixes from the local types,
  functions, and variables
- Documenting the option '-P' for 'cryptomount'
- Fixing coding style issues
- Removing the unused headers from grub-core/lib/tss2/tcg2_emu.c
- Updating the TPM2 key protector in user manual

v19:
- https://lists.gnu.org/archive/html/grub-devel/2024-09/msg00055.html
- GIT repo: https://github.com/lcp/grub2/tree/tpm2-unlock-v19
- Updating the coverity report for libtasn1
- Splitting the strcat() patch for libtasn1
- Addressing why the header paths are adjusted in libtasn1.h
- Fixing the order of the copyright headers
- Breaking down the patch for asn1 tests into the smaller patches
- libtasn1 patches are created by the following repo against the
  libtasn1-4.19.0-base-v3 tag:
  https://github.com/lcp/grub2/tree/import-libtasn1-4.19.0-v3
- Marking the 'extern' functions
- Amending the string length checks
- Unmarking the technical strings for translation
- Fixing more line foldings and coding style issues
- Renaming the TPM2 types to add the '_t' postfix for typedefs
- Adding the 'grub_' prefix to the global functions from tss2 and
  removing the 'grub_' prefix from the location functions
- Adding more comments about the passphrase fallback
- Simplying the diskfilter check
- Documenting TPM2 key protector in the user manual

v18:
- https://lists.gnu.org/archive/html/grub-devel/2024-06/msg00228.html
- GIT repo: https://github.com/lcp/grub2/tree/tpm2-unlock-v18
- Updating the steps to import libtasn1
  - Importing test cases from libtasn1 and then applying the follow-up
    patch by autogen.sh
  - The patch files in patch 3~8 are created with the following repo
    against the libtasn1-4.19.0-base-v2 tag:
    https://github.com/lcp/grub2/tree/import-libtasn1-4.19.0-v2
- Splitting the grub compatibility patch for libtasn1
- Moving the TSS2 code to grub-core/lib/tss2 and renaming
  grub_tpm2_mu_*() functions to grub_Tss2_MU_*()
- Splitting the TSS2 patch into 3 patches
- Fixing the types of TPMA_SESSION, TPMA_OBJECT, and TPMA_LOCALITY 
- Renaming the tpm2 module to tpm2_key_protector
- Adding more comments to asn1_read_uint32() and defining the lower and
  upper bounds for tpm2key elements
  - Also fixing a bug that allows 100 elements in the key file
- Fixing the copyright headers
- Fixing the coding style

v17:
- https://lists.gnu.org/archive/html/grub-devel/2024-06/msg00108.html
- GIT repo: https://github.com/lcp/grub2/tree/tpm2-unlock-v17
- Fixing the missing space in strncat()
- Updating the steps to import libtasn1
- Moving libtasn1.h to grub-core/lib/libtasn1/ and fixing the affected
  patches
  - libtasn1.h is included in tpm2key.h, so there is no need to include
    the header again in module.c and tpm2key.c. 
- Applying the libtasn1 patches in a different way
  - Instead of applying the patches directly in the grub2 source code,
    libtasn1 is copied to grub-core/lib/libtasn1-grub by autogen.sh and
    then the script applies the libtasn1 patches to libtasn1-grub.
  - The patch files in patch 3, 4, and 5 are created by the following
    repo against the libtasn1-4.19.0-base tag.
    https://github.com/lcp/grub2/tree/import-libtasn1-4.19.0
- Correcting the description of the tpm2_test commit to replace
  swtpm_cuse with "swtpm chardev"

v16:
- https://lists.gnu.org/archive/html/grub-devel/2024-05/msg00093.html
- GIT repo: https://github.com/lcp/grub2/tree/tpm2-unlock-v16
- Rebasing patch 6, 12, and 16 to fix the conflicts with the latest
  master branch
- Changes in cryptodisk:
  - Disallowing that both OPTION_KEYFILE and OPTION_PROTECTOR are set
    since the key data for "--key-file" would be overwritten by the key
    protectors
  - Resetting the cargs key data when the key from a key protector
    doesn't work for the disk to ensure the passphrase prompt will be
    triggered later
  - Adding the comment to address why grub_errno is only cleared for
    cargs->key_len == 0

v15:
- https://lists.gnu.org/archive/html/grub-devel/2024-05/msg00059.html 
- GIT repo: https://github.com/lcp/grub2/tree/tpm2-unlock-v15
- Changes in tpm2_test
  - Quoting the variables which contain file paths
  - Correcting the exit code for several commands
  - Writing the verification text directly into the LUKS device
  - Amending the waiting loop for swtpm
  - Replacing exit with return in tpm2_seal_unseal() and
    tpm2_seal_unseal_nv()
  - Collecting the parameters for the SRK mode testcases in an array
    and invoking tpm2_seal_unseal() with a for loop
  - Moving the tpm2-tools commands for the NV index mode to a separate
    function  
  - Using tpm2_evictcontrol to remove the object from the NV index to
    match the key sealing commands
  - Printing the test results
  - Printing error messages to stderr

v14:
- https://lists.gnu.org/archive/html/grub-devel/2024-05/msg00011.html
- GIT repo: https://github.com/lcp/grub2/tree/tpm2-unlock-v14
- Addressing the libtasn1 patches more in the document
- Various improvements in tpm2_test
  - Verifying the test inside the LUKS device
  - Improving the return status checks and the waiting loop for swtpm
  - Fixing the portability issues
  - Making all variables braced
- Renaming grub-emu-opts to --emu-opts (grub-shell)

v13:
- https://lists.gnu.org/archive/html/grub-devel/2024-04/msg00155.html
- GIT repo: https://github.com/lcp/grub2/tree/tpm2-unlock-v13
- Fixing typos and a few multi-line comments
- Improving the conditional checks for the arguments of
  tpm2_key_protector_init 
- Updating to the latest TPM 2.0 Key File format
  - Adding the new optional fields: description and rsaParent
  - Handling "rsaParent == TRUE" when unsealing the tpm2key
  - Setting "rsaParent" to "TRUE" when sealing the key with RSA SRK
- Removing non-standard SRKs: RSA3072, RSA4096, ECC_NIST_P384,
  ECC_NIST_P521, and ECC_SM2_P256
- Adding more error messages to grub-protect
- Improving the error checking for the swtpm chardev instance
- Exiting the tpm2_test script if grub-protect failed to seal the key   

v12:
- https://lists.gnu.org/archive/html/grub-devel/2024-04/msg00108.html
- GIT repo: https://github.com/lcp/grub2/tree/tpm2-unlock-v12
- Fixing typos and indentation
- Removing the unused TPM commands: TPM2_HashSequenceStart,
  TPM2_SequenceUpdate, and TPM2_SequenceComplete,
- Following the TCG EK templates to set the parameters of SRK
- Removing ECC_BN_P256 and ECC_BN_P638 from the SRK algorithm list since
  those two algorithms are not mentioned in the TCG EK templates
- Updating the help messages of the tpm2 module and grub-protect
- Removing the unnecessary NULL checks
- Adding the manpage for grub-protect
- Replacing grub_crypto_hash() with TPM2_Hash() in grub-protect to
  support SHA384 PCR banks
- Using 'swtpm chardev' to start swtpm instead of 'swtpm_cuse' since
  some distros may not build swtpm with cuse
- Adding a new testcase without specifying the SRK type to test the
  default SRK settings
- Amending tpm2_test to remove the duplicate error checking code
- Silencing the tpm2-tools commands in tpm2_test
- Fixing the exit trap of tpm2_test to removing the working directory
  on success

v11:
- https://lists.gnu.org/archive/html/grub-devel/2024-04/msg00052.html
- GIT repo: https://github.com/lcp/grub2/tree/tpm2-unlock-v11
- Adding the missing default: handlers in grub-core/tpm2/mu.c
- Updating the help messages and commit messages to reflect the change
  of the default SRK algorithm (RSA2048 -> ECC_NIST_P256)
- Adding the testcase for the NV index mode

v10:
- https://lists.gnu.org/archive/html/grub-devel/2024-04/msg00019.html
- GIT repo: https://github.com/lcp/grub2/tree/tpm2-unlock-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://lists.gnu.org/archive/html/grub-devel/2024-02/msg00007.html
- GIT repo: 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

*****************************************
* Anaylsis of libtasn1 Coverity issuses *
*****************************************

2 Memory corruptions: CID 435762, CID 435766

________________________________________________________________________________________________________
*** CID 435762:  Memory - corruptions  (OVERRUN)
/grub-core/lib/libtasn1/lib/coding.c: 152 in _asn1_tag_der()
146               if (k > ASN1_MAX_TAG_SIZE - 1)
147                 break;              /* will not encode larger tags */
148             }
149           *ans_len = k + 1;
150           while (k--)
151             ans[*ans_len - 1 - k] = temp[k] + 128;
>>>     CID 435762:  Memory - corruptions  (OVERRUN)
>>>     Overrunning array of 4 bytes at byte offset 4 by dereferencing pointer 
>>> "ans + (*ans_len - 1)".
152           ans[*ans_len - 1] -= 128;
153         }
154     }
155     
156     /**
157      * asn1_octet_der:

Reported to upstream: https://gitlab.com/gnutls/libtasn1/-/issues/49
A quick fix is also provided in patch 8.

________________________________________________________________________________________________________
*** CID 435766:  Memory - corruptions  (OVERRUN)
/grub-core/lib/libtasn1/lib/decoding.c: 1204 in asn1_der_decoding2()
1198                    }
1199     
1200                  DECR_LEN (ider_len, len2);
1201     
1202                  tlen = strlen (temp);
1203                  if (tlen > 0)
>>>     CID 435766:  Memory - corruptions  (OVERRUN)
>>>     Allocating insufficient memory for the terminating null of the string.
1204                    _asn1_set_value (p, temp, tlen);
1205     
1206                  counter += len2;
1207                  move = RIGHT;
1208                  break;
1209                case ASN1_ETYPE_OCTET_STRING:


Reported to upstream: https://gitlab.com/gnutls/libtasn1/-/issues/50
It's likely to be false positive because DER data is not NUL terminated.
I suggest to ignore this issue.

==
7 Integer handling issues:
CID 435774, CID 435773, CID 435772, CID 435768, CID 435765, CID 435764, CID 
435763    

Those are related to Gnulib macros and all false positive.

________________________________________________________________________________________________________
*** CID 435774:  Integer handling issues  (CONSTANT_EXPRESSION_RESULT)
/grub-core/lib/libtasn1/lib/decoding.c: 481 in asn1_get_object_id_der()
475            */
476           if (leading != 0 && der[len_len + k] == 0x80)
477             return ASN1_DER_ERROR;
478           leading = 0;
479     
480           /* check for wrap around */
>>>     CID 435774:  Integer handling issues  (CONSTANT_EXPRESSION_RESULT)
>>>     "val < ((((1 ? 0 : val) - 1 < 0) ? ~((((1 ? 0 : val) + 1 << 62UL /* 
>>> sizeof (+val) * 8 - 2 */) - 1) * 2 + 1) : ((1 ? 0 : val) + 0)) >> 7)" is 
>>> always false regardless of the values of its operands. This occurs as the 
>>> second operand of "?:".
481           if (INT_LEFT_SHIFT_OVERFLOW (val, 7))
482             return ASN1_DER_ERROR;
483     
484           val = val << 7;
485           val |= der[len_len + k] & 0x7F;
486     

/grub-core/lib/libtasn1/lib/decoding.c: 481 in asn1_get_object_id_der()

Here are the related macros from gnulib:

#define _GL_INT_NEGATE_CONVERT(e, v) ((1 ? 0 : (e)) - (v))

#define EXPR_SIGNED(e) (_GL_INT_NEGATE_CONVERT (e, 1) < 0)

#define _GL_INT_CONVERT(e, v) ((1 ? 0 : (e)) + (v))

#define TYPE_WIDTH(t) (sizeof (t) * CHAR_BIT)

#define _GL_SIGNED_INT_MAXIMUM(e)                                       \
  (((_GL_INT_CONVERT (e, 1) << (TYPE_WIDTH (+ (e)) - 2)) - 1) * 2 + 1)

#define _GL_INT_MINIMUM(e)                                              \
  (EXPR_SIGNED (e)                                                      \
   ? ~ _GL_SIGNED_INT_MAXIMUM (e)                                       \
   : _GL_INT_CONVERT (e, 0))

#define _GL_INT_MAXIMUM(e)                                              \
  (EXPR_SIGNED (e)                                                      \
   ? _GL_SIGNED_INT_MAXIMUM (e)                                         \
   : _GL_INT_NEGATE_CONVERT (e, 1))

#define INT_LEFT_SHIFT_RANGE_OVERFLOW(a, b, min, max)   \
  ((a) < 0                                              \
   ? (a) < (min) >> (b)                                 \
   : (max) >> (b) < (a))

#define INT_LEFT_SHIFT_OVERFLOW(a, b) \
  INT_LEFT_SHIFT_RANGE_OVERFLOW (a, b, \
                                 _GL_INT_MINIMUM (a), _GL_INT_MAXIMUM (a))

The statement in question is expanded "(a) < (min) >> (b)" from
'INT_LEFT_SHIFT_RANGE_OVERFLOW'.

'(a) < (min) >> (b)'
=> '(val) < _GL_INT_MINIMUM (val) >> (7)'
=> '(val) < \
     (EXPR_SIGNED (val) \
      ? ~ _GL_SIGNED_INT_MAXIMUM (val) \
      : _GL_INT_CONVERT (val, 0)) \
     >> (7)'
=> '(val) < \
     ((_GL_INT_NEGATE_CONVERT (val, 1) < 0) \
      ? ~ _GL_SIGNED_INT_MAXIMUM (val) \
      : _GL_INT_CONVERT (val, 0)) \
     >> (7)'
=> '(val) < \
     ((((1 ? 0 : (val)) - (1)) < 0) \
      ? ~ _GL_SIGNED_INT_MAXIMUM (val) \
      : _GL_INT_CONVERT (val, 0)) \
     >> (7)'
=> '(val) < \
     ((((1 ? 0 : (val)) - (1)) < 0) \
      ? ~ (((_GL_INT_CONVERT (val, 1) << (TYPE_WIDTH (+ (val)) - 2)) - 1) * 2 + 
1) \
      : _GL_INT_CONVERT (val, 0)) \
     >> (7)'
=> '(val) < \
     ((((1 ? 0 : (val)) - (1)) < 0) \
      ? ~ (((((1 ? 0 : (val)) + (1)) << (TYPE_WIDTH (+ (val)) - 2)) - 1) * 2 + 
1) \
      : _GL_INT_CONVERT (val, 0)) \
     >> (7)'
=> '(val) < \
     ((((1 ? 0 : (val)) - (1)) < 0) \
      ? ~ (((((1 ? 0 : (val)) + (1)) << ((sizeof (val) * CHAR_BIT) - 2)) - 1) * 
2 + 1) \
      : _GL_INT_CONVERT (val, 0)) \
     >> (7)'
=> '(val) < \
     ((((1 ? 0 : (val)) - (1)) < 0) \
      ? ~ (((((1 ? 0 : (val)) + (1)) << ((sizeof (val) * CHAR_BIT) - 2)) - 1) * 
2 + 1) \
      : ((1 ? 0 : (val)) + (0))) \
     >> (7)'

'_GL_INT_MINIMUM' returns the minimum value of the given type. Since 'val' is
'uint64_t', '_GL_INT_MINIMUM (val)' is 0

'(val) < _GL_INT_MINIMUM (val) >> (7)' => '(val) < 0 >> (7)' => '(val) < 0'

For 'uint64_t val', the result is always false.

Furthermore, For 'INT_LEFT_SHIFT_RANGE_OVERFLOW':

  ((a) < 0                                              \
   ? (a) < (min) >> (b)                                 \
   : (max) >> (b) < (a))
=>
  ((val) < 0                                              \
   ? (val) < (min) >> (7)                                 \
   : (max) >> (7) < (val))

Since 'val' is 'uint64_t', the statement in question, '(a) < (min) >> (b)', is
always ignored. Thus, the result of the statement doesn't even matter.

Summary:
  We can ignore CID 435774 because the statement in question is designed to be
  "FALSE" and even ignored.

________________________________________________________________________________________________________
*** CID 435773:  Integer handling issues  (NO_EFFECT)
/grub-core/lib/libtasn1/lib/decoding.c: 439 in asn1_get_object_id_der()
433         return ASN1_DER_ERROR;
434     
435       val0 = 0;
436     
437       for (k = 0; k < len; k++)
438         {
>>>     CID 435773:  Integer handling issues  (NO_EFFECT)
>>>     This less-than-zero comparison of an unsigned value is never true. "(1 
>>> ? 0UL : val0) - 1UL < 0UL".
439           if (INT_LEFT_SHIFT_OVERFLOW (val0, 7))
440             return ASN1_DER_ERROR;
441     
442           val0 <<= 7;
443           val0 |= der[len_len + k] & 0x7F;
444           if (!(der[len_len + k] & 0x80))

Here are the related macros from gnulib:

#define _GL_INT_NEGATE_CONVERT(e, v) ((1 ? 0 : (e)) - (v))

#define EXPR_SIGNED(e) (_GL_INT_NEGATE_CONVERT (e, 1) < 0)

#define _GL_INT_CONVERT(e, v) ((1 ? 0 : (e)) + (v))

#define TYPE_WIDTH(t) (sizeof (t) * CHAR_BIT)

#define _GL_SIGNED_INT_MAXIMUM(e)                                       \
  (((_GL_INT_CONVERT (e, 1) << (TYPE_WIDTH (+ (e)) - 2)) - 1) * 2 + 1)

#define _GL_INT_MINIMUM(e)                                              \
  (EXPR_SIGNED (e)                                                      \
   ? ~ _GL_SIGNED_INT_MAXIMUM (e)                                       \
   : _GL_INT_CONVERT (e, 0))

#define _GL_INT_MAXIMUM(e)                                              \
  (EXPR_SIGNED (e)                                                      \
   ? _GL_SIGNED_INT_MAXIMUM (e)                                         \
   : _GL_INT_NEGATE_CONVERT (e, 1))

#define INT_LEFT_SHIFT_RANGE_OVERFLOW(a, b, min, max)   \
  ((a) < 0                                              \
   ? (a) < (min) >> (b)                                 \
   : (max) >> (b) < (a))

#define INT_LEFT_SHIFT_OVERFLOW(a, b) \
  INT_LEFT_SHIFT_RANGE_OVERFLOW (a, b, \
                                 _GL_INT_MINIMUM (a), _GL_INT_MAXIMUM (a))

The statement in question is the expanded 'EXPR_SIGNED (val0)' from either
'_GL_INT_MAXIMUM' or '_GL_INT_MINIMUM'

'EXPR_SIGNED (val0)'
=> '(_GL_INT_NEGATE_CONVERT (val0, 1) < 0)'
=> '(((1 ? 0 : (val0)) - (1)) < 0)'

'EXPR_SIGNED' is designed to test if the given expression is signed, and
'EXPR_SIGNED (val0)' is expected to be false for 'uint64_t val0'. The macro
dutifully reflects the fact.

Summary:
  We can ignore CID 435773 because 'EXPR_SIGNED' is designed to be "FALSE"
  when using it on 'uint64_t val0'.

________________________________________________________________________________________________________
*** CID 435772:  Integer handling issues  (NO_EFFECT)
/grub-core/lib/libtasn1/lib/decoding.c: 204 in asn1_get_tag_der()
198           /* Long form */
199           punt = 1;
200           ris = 0;
201           while (punt < der_len && der[punt] & 128)
202             {
203     
>>>     CID 435772:  Integer handling issues  (NO_EFFECT)
>>>     This less-than-zero comparison of an unsigned value is never true. "(1 
>>> ? 0U : ((1 ? 0U : ris) + 128U)) - 1U < 0U".
204               if (INT_MULTIPLY_OVERFLOW (ris, 128))
205                 return ASN1_DER_ERROR;
206               ris *= 128;
207     
208               if (INT_ADD_OVERFLOW (ris, ((unsigned) (der[punt] & 0x7F))))
209                 return ASN1_DER_ERROR;

Here are the related macros gnulib:

#define _GL_INT_NEGATE_CONVERT(e, v) ((1 ? 0 : (e)) - (v))

#define _GL_INT_CONVERT(e, v) ((1 ? 0 : (e)) + (v))

#define EXPR_SIGNED(e) (_GL_INT_NEGATE_CONVERT (e, 1) < 0)

#define TYPE_WIDTH(t) (sizeof (t) * CHAR_BIT)

#define _GL_SIGNED_INT_MAXIMUM(e)                                       \
  (((_GL_INT_CONVERT (e, 1) << (TYPE_WIDTH (+ (e)) - 2)) - 1) * 2 + 1)

#define _GL_INT_MINIMUM(e)                                              \
  (EXPR_SIGNED (e)                                                      \
   ? ~ _GL_SIGNED_INT_MAXIMUM (e)                                       \
   : _GL_INT_CONVERT (e, 0))

#define _GL_INT_MAXIMUM(e)                                              \
  (EXPR_SIGNED (e)                                                      \
   ? _GL_SIGNED_INT_MAXIMUM (e)                                         \
   : _GL_INT_NEGATE_CONVERT (e, 1))

#define INT_MULTIPLY_RANGE_OVERFLOW(a, b, min, max)     \
  ((b) < 0                                              \
   ? ((a) < 0                                           \
      ? (a) < (max) / (b)                               \
      : (b) == -1                                       \
      ? 0                                               \
      : (min) / (b) < (a))                              \
   : (b) == 0                                           \
   ? 0                                                  \
   : ((a) < 0                                           \
      ? (a) < (min) / (b)                               \
      : (max) / (b) < (a)))

# define _GL_MULTIPLY_OVERFLOW(a, b, min, max)                           \
   (((min) == 0 && (((a) < 0 && 0 < (b)) || ((b) < 0 && 0 < (a))))       \
    || INT_MULTIPLY_RANGE_OVERFLOW (a, b, min, max))

#define _GL_BINARY_OP_OVERFLOW(a, b, op_result_overflow)        \
  op_result_overflow (a, b,                                     \
                      _GL_INT_MINIMUM (_GL_INT_CONVERT (a, b)), \
                      _GL_INT_MAXIMUM (_GL_INT_CONVERT (a, b)))

#define INT_MULTIPLY_OVERFLOW(a, b) \
  _GL_BINARY_OP_OVERFLOW (a, b, _GL_MULTIPLY_OVERFLOW)

The statement in question is the expanded 'EXPR_SIGNED (_GL_INT_CONVERT (ris, 
128))'
from either '_GL_INT_MINIMUM' or '_GL_INT_MAXIMUM'.

'EXPR_SIGNED (_GL_INT_CONVERT (ris, 128))'
=> 'EXPR_SIGNED ((1 ? 0 : (ris)) + (128))'
=> '(_GL_INT_NEGATE_CONVERT (((1 ? 0 : (ris)) + (128), 1) < 0))'
=> '((1 ? 0 : ((1 ? 0 : ris) + 128)) - 1 < 0)'

'_GL_INT_CONVERT(e, v)' returns a value with the common real type of 'e' and 'v'
and the value of 'v'. Since the common type of 'unsigned int ris' and '128' is
'unsigned int', '_GL_INT_CONVERT (ris, 128)' is '128U'.

'EXPR_SIGNED' is designed to check if the given expression is signed. Thus,
'EXPR_SIGNED (128U)' is expected to be false.

Summary:
  We can ignore CID 435772. The statement in question is the combination of
  'EXPR_SIGNED' and '_GL_INT_CONVERT' which is used to test if the common type
  of the given two variables is signed. Those macros dutifully reflect the
  fact: the common type of 'ris' and '128' is unsigned, so the result is
  always "FALSE" by design.

________________________________________________________________________________________________________
*** CID 435768:    (CONSTANT_EXPRESSION_RESULT)
/grub-core/lib/libtasn1/lib/decoding.c: 204 in asn1_get_tag_der()
198           /* Long form */
199           punt = 1;
200           ris = 0;
201           while (punt < der_len && der[punt] & 128)
202             {
203     
>>>     CID 435768:    (CONSTANT_EXPRESSION_RESULT)
>>>     "ris < (((1 ? 0 : ((1 ? 0 : ris) + 128)) - 1 < 0) ? ~((((1 ? 0 : ((1 ? 
>>> 0 : ris) + 128)) + 1 << 30UL /* sizeof (+((1 ? 0 : ris) + 128)) * 8 - 2 */) 
>>> - 1) * 2 + 1) : ((1 ? 0 : ((1 ? 0 : ris) + 128)) + 0)) / 128" is always 
>>> false regardless of the values of its operands. This occurs as the second 
>>> operand of "?:".
204               if (INT_MULTIPLY_OVERFLOW (ris, 128))
205                 return ASN1_DER_ERROR;
206               ris *= 128;
207     
208               if (INT_ADD_OVERFLOW (ris, ((unsigned) (der[punt] & 0x7F))))
209                 return ASN1_DER_ERROR;
/grub-core/lib/libtasn1/lib/decoding.c: 217 in asn1_get_tag_der()
211               punt++;
212             }
213     
214           if (punt >= der_len)
215             return ASN1_DER_ERROR;
216     
>>>     CID 435768:    (CONSTANT_EXPRESSION_RESULT)
>>>     "ris < (((1 ? 0 : ((1 ? 0 : ris) + 128)) - 1 < 0) ? ~((((1 ? 0 : ((1 ? 
>>> 0 : ris) + 128)) + 1 << 30UL /* sizeof (+((1 ? 0 : ris) + 128)) * 8 - 2 */) 
>>> - 1) * 2 + 1) : ((1 ? 0 : ((1 ? 0 : ris) + 128)) + 0)) / 128" is always 
>>> false regardless of the values of its operands. This occurs as the second 
>>> operand of "?:".
217           if (INT_MULTIPLY_OVERFLOW (ris, 128))
218             return ASN1_DER_ERROR;
219           ris *= 128;
220     
221           if (INT_ADD_OVERFLOW (ris, ((unsigned) (der[punt] & 0x7F))))
222             return ASN1_DER_ERROR;

Here are the related macros gnulib:

#define _GL_INT_NEGATE_CONVERT(e, v) ((1 ? 0 : (e)) - (v))

#define _GL_INT_CONVERT(e, v) ((1 ? 0 : (e)) + (v))

#define EXPR_SIGNED(e) (_GL_INT_NEGATE_CONVERT (e, 1) < 0)

#define TYPE_WIDTH(t) (sizeof (t) * CHAR_BIT)

#define _GL_SIGNED_INT_MAXIMUM(e)                                       \
  (((_GL_INT_CONVERT (e, 1) << (TYPE_WIDTH (+ (e)) - 2)) - 1) * 2 + 1)

#define _GL_INT_MINIMUM(e)                                              \
  (EXPR_SIGNED (e)                                                      \
   ? ~ _GL_SIGNED_INT_MAXIMUM (e)                                       \
   : _GL_INT_CONVERT (e, 0))

#define _GL_INT_MAXIMUM(e)                                              \
  (EXPR_SIGNED (e)                                                      \
   ? _GL_SIGNED_INT_MAXIMUM (e)                                         \
   : _GL_INT_NEGATE_CONVERT (e, 1))

#define INT_MULTIPLY_RANGE_OVERFLOW(a, b, min, max)     \
  ((b) < 0                                              \
   ? ((a) < 0                                           \
      ? (a) < (max) / (b)                               \
      : (b) == -1                                       \
      ? 0                                               \
      : (min) / (b) < (a))                              \
   : (b) == 0                                           \
   ? 0                                                  \
   : ((a) < 0                                           \
      ? (a) < (min) / (b)                               \
      : (max) / (b) < (a)))

# define _GL_MULTIPLY_OVERFLOW(a, b, min, max)                           \
   (((min) == 0 && (((a) < 0 && 0 < (b)) || ((b) < 0 && 0 < (a))))       \
    || INT_MULTIPLY_RANGE_OVERFLOW (a, b, min, max))

#define _GL_BINARY_OP_OVERFLOW(a, b, op_result_overflow)        \
  op_result_overflow (a, b,                                     \
                      _GL_INT_MINIMUM (_GL_INT_CONVERT (a, b)), \
                      _GL_INT_MAXIMUM (_GL_INT_CONVERT (a, b)))

#define INT_MULTIPLY_OVERFLOW(a, b) \
  _GL_BINARY_OP_OVERFLOW (a, b, _GL_MULTIPLY_OVERFLOW)

The statement in question is the expanded '(a) < (min) / (b)' from
'INT_MULTIPLY_RANGE_OVERFLOW'.

'(a) < (min) / (b)'
=> '(a) < (_GL_INT_MINIMUM (_GL_INT_CONVERT (a, b))) / (b)'
=> '(ris) < (_GL_INT_MINIMUM (_GL_INT_CONVERT (ris, 128))) / (128)'
=> '(ris) < \
     (EXPR_SIGNED (_GL_INT_CONVERT (ris, 128)) \
      ? ~ _GL_SIGNED_INT_MAXIMUM (_GL_INT_CONVERT (ris, 128)) \
      : _GL_INT_CONVERT (_GL_INT_CONVERT (ris, 128), 0)) \
     / (128)'
=> '(ris) < \
     ((_GL_INT_NEGATE_CONVERT (_GL_INT_CONVERT (ris, 128), 1) < 0) \
      ? ~ _GL_SIGNED_INT_MAXIMUM (_GL_INT_CONVERT (ris, 128)) \
      : _GL_INT_CONVERT (_GL_INT_CONVERT (ris, 128), 0)) \
     / (128)'
=> '(ris) < \
     ((((1 ? 0 : (_GL_INT_CONVERT (ris, 128))) - (1)) < 0) \
      ? ~ _GL_SIGNED_INT_MAXIMUM (_GL_INT_CONVERT (ris, 128)) \
      : _GL_INT_CONVERT (_GL_INT_CONVERT (ris, 128), 0)) \
     / (128)'
=> '(ris) < \
     ((((1 ? 0 : ((1 ? 0 : (ris)) + (128))) - (1)) < 0) \
      ? ~ _GL_SIGNED_INT_MAXIMUM (_GL_INT_CONVERT (ris, 128)) \
      : _GL_INT_CONVERT (_GL_INT_CONVERT (ris, 128), 0)) \
     / (128)'
=> '(ris) < \
     ((((1 ? 0 : ((1 ? 0 : (ris)) + (128))) - (1)) < 0) \
      ? ~ (((_GL_INT_CONVERT (_GL_INT_CONVERT (ris, 128), 1) << (TYPE_WIDTH (+ 
(_GL_INT_CONVERT (ris, 128))) - 2)) - 1) * 2 + 1) \
      : _GL_INT_CONVERT (_GL_INT_CONVERT (ris, 128), 0)) \
     / (128)'
=> '(ris) < \
     ((((1 ? 0 : ((1 ? 0 : (ris)) + (128))) - (1)) < 0) \
      ? ~ (((((1 ? 0 : (_GL_INT_CONVERT (ris, 128))) + (1)) << (TYPE_WIDTH (+ 
(_GL_INT_CONVERT (ris, 128))) - 2)) - 1) * 2 + 1) \
      : _GL_INT_CONVERT (_GL_INT_CONVERT (ris, 128), 0)) \
     / (128)'
=> '(ris) < \
     ((((1 ? 0 : ((1 ? 0 : (ris)) + (128))) - (1)) < 0) \
      ? ~ (((((1 ? 0 : ((1 ? 0 : (ris)) + (128))) + (1)) << (TYPE_WIDTH (+ 
(_GL_INT_CONVERT (ris, 128))) - 2)) - 1) * 2 + 1) \
      : _GL_INT_CONVERT (_GL_INT_CONVERT (ris, 128), 0)) \
     / (128)'
=> '(ris) < \
     ((((1 ? 0 : ((1 ? 0 : (ris)) + (128))) - (1)) < 0) \
      ? ~ (((((1 ? 0 : ((1 ? 0 : (ris)) + (128))) + (1)) << ((sizeof (+ 
(_GL_INT_CONVERT (ris, 128))) * CHAR_BIT) - 2)) - 1) * 2 + 1) \
      : _GL_INT_CONVERT (_GL_INT_CONVERT (ris, 128), 0)) \
     / (128)'
=> '(ris) < \
     ((((1 ? 0 : ((1 ? 0 : (ris)) + (128))) - (1)) < 0) \
      ? ~ (((((1 ? 0 : ((1 ? 0 : (ris)) + (128))) + (1)) << ((sizeof (+ ((1 ? 0 
: (ris)) + (128))) * CHAR_BIT) - 2)) - 1) * 2 + 1) \
      : _GL_INT_CONVERT (_GL_INT_CONVERT (ris, 128), 0)) \
     / (128)'
=> '(ris) < \
     ((((1 ? 0 : ((1 ? 0 : (ris)) + (128))) - (1)) < 0) \
      ? ~ (((((1 ? 0 : ((1 ? 0 : (ris)) + (128))) + (1)) << ((sizeof (+ ((1 ? 0 
: (ris)) + (128))) * CHAR_BIT) - 2)) - 1) * 2 + 1) \
      : _GL_INT_CONVERT (_GL_INT_CONVERT (ris, 128), 0)) \
     / (128)'
=> '(ris) < \
     ((((1 ? 0 : ((1 ? 0 : (ris)) + (128))) - (1)) < 0) \
      ? ~ (((((1 ? 0 : ((1 ? 0 : (ris)) + (128))) + (1)) << ((sizeof (+ ((1 ? 0 
: (ris)) + (128))) * CHAR_BIT) - 2)) - 1) * 2 + 1) \
      : ((1 ? 0 : (_GL_INT_CONVERT (ris, 128)) + (0)) \
     / (128)'
=> '(ris) < \
     ((((1 ? 0 : ((1 ? 0 : (ris)) + (128))) - (1)) < 0) \
      ? ~ (((((1 ? 0 : ((1 ? 0 : (ris)) + (128))) + (1)) << ((sizeof (+ ((1 ? 0 
: (ris)) + (128))) * CHAR_BIT) - 2)) - 1) * 2 + 1) \
      : ((1 ? 0 : ((1 ? 0 : (ris)) + (128)) + (0)) \
     / (128)'

'_GL_INT_CONVERT(e, v)' returns a value with the common real type of 'e' and 
'v' and
the value of 'v'. Since the common type of 'unsigned int ris' and '128' is
'unsigned int', '_GL_INT_CONVERT (ris, 128)' is '128U'.

'_GL_INT_MINIMUM (128U)' returns the minimum value of 'unsigned int', i.e. 0.

'(ris) < (_GL_INT_MINIMUM (_GL_INT_CONVERT (ris, 128))) / (128)'
=> '(ris) < 0 / (128)'
=> '(ris) < 0'

For 'unsigned int ris', the result is always false.

Futhermore, in 'INT_MULTIPLY_RANGE_OVERFLOW', 'a' is 'unsigned int ris' and 'b'
is '128'. We can skip the statements for 'b < 0' and 'b == 0' and reduce the
macro to 

  (a) < 0                \
   ? (a) < (min) / (b)   \
   : (max) / (b) < (a)))
=>
  (ris) < 0                  \
   ? (ris) < (min) / (128)   \
   : (max) / (128) < (ris)))

Since 'ris' is 'unsigned int', the statement in question, '(a) < (min) / (b)',
is always ignored. Thus, the result of the statement doesn't even matter.

Summary:
  We can ignore CID 435768 because the statement in question is designed to be
  "FALSE" and even ignored.

________________________________________________________________________________________________________
*** CID 435765:  Integer handling issues  (CONSTANT_EXPRESSION_RESULT)
/grub-core/lib/libtasn1/lib/decoding.c: 439 in asn1_get_object_id_der()
433         return ASN1_DER_ERROR;
434     
435       val0 = 0;
436     
437       for (k = 0; k < len; k++)
438         {
>>>     CID 435765:  Integer handling issues  (CONSTANT_EXPRESSION_RESULT)
>>>     "val0 < ((((1 ? 0 : val0) - 1 < 0) ? ~((((1 ? 0 : val0) + 1 << 62UL /* 
>>> sizeof (+val0) * 8 - 2 */) - 1) * 2 + 1) : ((1 ? 0 : val0) + 0)) >> 7)" is 
>>> always false regardless of the values of its operands. This occurs as the 
>>> second operand of "?:".
439           if (INT_LEFT_SHIFT_OVERFLOW (val0, 7))
440             return ASN1_DER_ERROR;
441     
442           val0 <<= 7;
443           val0 |= der[len_len + k] & 0x7F;
444           if (!(der[len_len + k] & 0x80))

Here are the related macros from gnulib:

#define _GL_INT_NEGATE_CONVERT(e, v) ((1 ? 0 : (e)) - (v))

#define EXPR_SIGNED(e) (_GL_INT_NEGATE_CONVERT (e, 1) < 0)

#define _GL_INT_CONVERT(e, v) ((1 ? 0 : (e)) + (v))

#define TYPE_WIDTH(t) (sizeof (t) * CHAR_BIT)

#define _GL_SIGNED_INT_MAXIMUM(e)                                       \
  (((_GL_INT_CONVERT (e, 1) << (TYPE_WIDTH (+ (e)) - 2)) - 1) * 2 + 1)

#define _GL_INT_MINIMUM(e)                                              \
  (EXPR_SIGNED (e)                                                      \
   ? ~ _GL_SIGNED_INT_MAXIMUM (e)                                       \
   : _GL_INT_CONVERT (e, 0))

#define _GL_INT_MAXIMUM(e)                                              \
  (EXPR_SIGNED (e)                                                      \
   ? _GL_SIGNED_INT_MAXIMUM (e)                                         \
   : _GL_INT_NEGATE_CONVERT (e, 1))

#define INT_LEFT_SHIFT_RANGE_OVERFLOW(a, b, min, max)   \
  ((a) < 0                                              \
   ? (a) < (min) >> (b)                                 \
   : (max) >> (b) < (a))

#define INT_LEFT_SHIFT_OVERFLOW(a, b) \
  INT_LEFT_SHIFT_RANGE_OVERFLOW (a, b, \
                                 _GL_INT_MINIMUM (a), _GL_INT_MAXIMUM (a))

The statement in question is expanded '(a) < (min) >> (b)' from
INT_LEFT_SHIFT_RANGE_OVERFLOW.

'(a) < (min) >> (b)'
=> '(val) < (_GL_INT_MINIMUM (val)) >> (7)'
=> '(val) < \
     (EXPR_SIGNED (val) \
      ? ~ _GL_SIGNED_INT_MAXIMUM (val) \
      : _GL_INT_CONVERT (val, 0)) \
     >> (7)'
=> '(val) < \
     ((_GL_INT_NEGATE_CONVERT (val, 1) < 0) \
      ? ~ _GL_SIGNED_INT_MAXIMUM (val) \
      : _GL_INT_CONVERT (val, 0)) \
     >> (7)'
=> '(val) < \
     ((((1 ? 0 : (val)) - (1)) < 0) \
      ? ~ _GL_SIGNED_INT_MAXIMUM (val) \
      : _GL_INT_CONVERT (val, 0)) \
     >> (7)'
=> '(val) < \
     ((((1 ? 0 : (val)) - (1)) < 0) \
      ? ~ (((_GL_INT_CONVERT (val, 1) << (TYPE_WIDTH (+ (val)) - 2)) - 1) * 2 + 
1) \
      : _GL_INT_CONVERT (val, 0)) \
     >> (7)'
=> '(val) < \
     ((((1 ? 0 : (val)) - (1)) < 0) \
      ? ~ (((((1 ? 0 : (val)) + (1)) << (TYPE_WIDTH (+ (val)) - 2)) - 1) * 2 + 
1) \
      : _GL_INT_CONVERT (val, 0)) \
     >> (7)'
=> '(val) < \
     ((((1 ? 0 : (val)) - (1)) < 0) \
      ? ~ (((((1 ? 0 : (val)) + (1)) << ((sizeof (+ (val)) * CHAR_BIT) - 2)) - 
1) * 2 + 1) \
      : _GL_INT_CONVERT (val, 0)) \
     >> (7)'
=> '(val) < \
     ((((1 ? 0 : (val)) - (1)) < 0) \
      ? ~ (((((1 ? 0 : (val)) + (1)) << ((sizeof (+ (val)) * CHAR_BIT) - 2)) - 
1) * 2 + 1) \
      : ((1 ? 0 : (val)) + (0))) \
     >> (7)'

'_GL_INT_MINIMUM' returns the minimum value of the given type. For 'uint64_t 
val',
'_GL_INT_MINIMUM (val)' is 0.

'(val) < (_GL_INT_MINIMUM (val)) >> (7)' => '(val) < 0 >> (7)' => '(val) < 0'

For 'uint64_t val', the result is always false.

Furthermore, in 'INT_LEFT_SHIFT_RANGE_OVERFLOW':

  ((a) < 0                                              \
   ? (a) < (min) >> (b)                                 \
   : (max) >> (b) < (a))
=>
  ((val) < 0                                            \
   ? (val) < (min) >> (7)                               \
   : (max) >> (7) < (val))

Since 'val' is 'uint64_t', the statement in question, '(a) < (min) >> (b)', is
always ignored. Thus, the result of the statement doesn't even matter.

Summary:
  We can ignore CID 435765 because the statement in question is designed to be
  "FALSE" and even ignored.

________________________________________________________________________________________________________
*** CID 435764:  Integer handling issues  (NO_EFFECT)
/grub-core/lib/libtasn1/lib/decoding.c: 137 in asn1_get_length_der()
131           punt = 1;
132           if (k)
133             {                       /* definite length method */
134               ans = 0;
135               while (punt <= k && punt < der_len)
136                 {
>>>     CID 435764:  Integer handling issues  (NO_EFFECT)
>>>     This less-than-zero comparison of an unsigned value is never true. "(1 
>>> ? 0U : ((1 ? 0U : ans) + 256U)) - 1U < 0U".
137                   if (INT_MULTIPLY_OVERFLOW (ans, 256))
138                     return -2;
139                   ans *= 256;
140     
141                   if (INT_ADD_OVERFLOW (ans, ((unsigned) der[punt])))
142                     return -2;

Here are the related macros from gnulib:

#define _GL_INT_NEGATE_CONVERT(e, v) ((1 ? 0 : (e)) - (v))

#define _GL_INT_CONVERT(e, v) ((1 ? 0 : (e)) + (v))

#define EXPR_SIGNED(e) (_GL_INT_NEGATE_CONVERT (e, 1) < 0)

#define TYPE_WIDTH(t) (sizeof (t) * CHAR_BIT)

#define _GL_SIGNED_INT_MAXIMUM(e)                                       \
  (((_GL_INT_CONVERT (e, 1) << (TYPE_WIDTH (+ (e)) - 2)) - 1) * 2 + 1)

#define _GL_INT_MINIMUM(e)                                              \
  (EXPR_SIGNED (e)                                                      \
   ? ~ _GL_SIGNED_INT_MAXIMUM (e)                                       \
   : _GL_INT_CONVERT (e, 0))

#define _GL_INT_MAXIMUM(e)                                              \
  (EXPR_SIGNED (e)                                                      \
   ? _GL_SIGNED_INT_MAXIMUM (e)                                         \
   : _GL_INT_NEGATE_CONVERT (e, 1))

#define INT_MULTIPLY_RANGE_OVERFLOW(a, b, min, max)     \
  ((b) < 0                                              \
   ? ((a) < 0                                           \
      ? (a) < (max) / (b)                               \
      : (b) == -1                                       \
      ? 0                                               \
      : (min) / (b) < (a))                              \
   : (b) == 0                                           \
   ? 0                                                  \
   : ((a) < 0                                           \
      ? (a) < (min) / (b)                               \
      : (max) / (b) < (a)))

# define _GL_MULTIPLY_OVERFLOW(a, b, min, max)                           \
   (((min) == 0 && (((a) < 0 && 0 < (b)) || ((b) < 0 && 0 < (a))))       \
    || INT_MULTIPLY_RANGE_OVERFLOW (a, b, min, max))

#define _GL_BINARY_OP_OVERFLOW(a, b, op_result_overflow)        \
  op_result_overflow (a, b,                                     \
                      _GL_INT_MINIMUM (_GL_INT_CONVERT (a, b)), \
                      _GL_INT_MAXIMUM (_GL_INT_CONVERT (a, b)))

#define INT_MULTIPLY_OVERFLOW(a, b) \
  _GL_BINARY_OP_OVERFLOW (a, b, _GL_MULTIPLY_OVERFLOW)

The statement in question is expanded 'EXPR_SIGNED (_GL_INT_CONVERT (ans, 256))'
from either '_GL_INT_MINIMUM' or '_GL_INT_MAXIMUM'.

'EXPR_SIGNED (_GL_INT_CONVERT (ans, 256))'
=> 'EXPR_SIGNED ((1 ? 0 : (ans)) + (256))'
=> '(_GL_INT_NEGATE_CONVERT (((1 ? 0 : (ans)) + (256)), 1) < 0)'
=> '((1 ? 0 : ((1 ? 0 : (ans)) + (256))) - (1))'

'_GL_INT_CONVERT(e, v)' returns a value with the common real type of 'e' and 
'v' and
the value of 'v'. Since the common type of 'unsigned int ans' and '256' is
'unsigned int', '_GL_INT_CONVERT (ans, 256)' is '256U'.

'EXPR_SIGNED' is designed to check if the given expression is signed. Thus,
'EXPR_SIGNED (256U)' is expected to be false.

Summary:
  We can ignore CID 435764. The statement in question is the combination of
  'EXPR_SIGNED' and '_GL_INT_CONVERT' which is used to test if the common type
  of the given two variables is signed. Those macros dutifully reflect the
  fact: the common type of 'ans' and '256' is unsigned, so the result is
  always "FALSE" by design.

________________________________________________________________________________________________________
*** CID 435763:  Integer handling issues  (CONSTANT_EXPRESSION_RESULT)
/grub-core/lib/libtasn1/lib/decoding.c: 137 in asn1_get_length_der()
131           punt = 1;
132           if (k)
133             {                       /* definite length method */
134               ans = 0;
135               while (punt <= k && punt < der_len)
136                 {
>>>     CID 435763:  Integer handling issues  (CONSTANT_EXPRESSION_RESULT)
>>>     "ans < (((1 ? 0 : ((1 ? 0 : ans) + 256)) - 1 < 0) ? ~((((1 ? 0 : ((1 ? 
>>> 0 : ans) + 256)) + 1 << 30UL /* sizeof (+((1 ? 0 : ans) + 256)) * 8 - 2 */) 
>>> - 1) * 2 + 1) : ((1 ? 0 : ((1 ? 0 : ans) + 256)) + 0)) / 256" is always 
>>> false regardless of the values of its operands. This occurs as the second 
>>> operand of "?:".
137                   if (INT_MULTIPLY_OVERFLOW (ans, 256))
138                     return -2;
139                   ans *= 256;
140     
141                   if (INT_ADD_OVERFLOW (ans, ((unsigned) der[punt])))
142                     return -2;

Here are the related macros from gnulib:

#define _GL_INT_NEGATE_CONVERT(e, v) ((1 ? 0 : (e)) - (v))

#define _GL_INT_CONVERT(e, v) ((1 ? 0 : (e)) + (v))

#define EXPR_SIGNED(e) (_GL_INT_NEGATE_CONVERT (e, 1) < 0)

#define TYPE_WIDTH(t) (sizeof (t) * CHAR_BIT)

#define _GL_SIGNED_INT_MAXIMUM(e)                                       \
  (((_GL_INT_CONVERT (e, 1) << (TYPE_WIDTH (+ (e)) - 2)) - 1) * 2 + 1)

#define _GL_INT_MINIMUM(e)                                              \
  (EXPR_SIGNED (e)                                                      \
   ? ~ _GL_SIGNED_INT_MAXIMUM (e)                                       \
   : _GL_INT_CONVERT (e, 0))

#define _GL_INT_MAXIMUM(e)                                              \
  (EXPR_SIGNED (e)                                                      \
   ? _GL_SIGNED_INT_MAXIMUM (e)                                         \
   : _GL_INT_NEGATE_CONVERT (e, 1))

#define INT_MULTIPLY_RANGE_OVERFLOW(a, b, min, max)     \
  ((b) < 0                                              \
   ? ((a) < 0                                           \
      ? (a) < (max) / (b)                               \
      : (b) == -1                                       \
      ? 0                                               \
      : (min) / (b) < (a))                              \
   : (b) == 0                                           \
   ? 0                                                  \
   : ((a) < 0                                           \
      ? (a) < (min) / (b)                               \
      : (max) / (b) < (a)))

# define _GL_MULTIPLY_OVERFLOW(a, b, min, max)                           \
   (((min) == 0 && (((a) < 0 && 0 < (b)) || ((b) < 0 && 0 < (a))))       \
    || INT_MULTIPLY_RANGE_OVERFLOW (a, b, min, max))

#define _GL_BINARY_OP_OVERFLOW(a, b, op_result_overflow)        \
  op_result_overflow (a, b,                                     \
                      _GL_INT_MINIMUM (_GL_INT_CONVERT (a, b)), \
                      _GL_INT_MAXIMUM (_GL_INT_CONVERT (a, b)))

#define INT_MULTIPLY_OVERFLOW(a, b) \
  _GL_BINARY_OP_OVERFLOW (a, b, _GL_MULTIPLY_OVERFLOW)

The statement in question is the expanded '(a) < (min) / (b)' from
INT_MULTIPLY_RANGE_OVERFLOW.

'(a) < (min) / (b)'
=> '(a) < (_GL_INT_MINIMUM (_GL_INT_CONVERT (a, b))) / (b)'
=> '(ans) < (_GL_INT_MINIMUM (_GL_INT_CONVERT (ans, 256))) / (256)'
=> '(ans) < \
     (EXPR_SIGNED (_GL_INT_CONVERT (ans, 256)) \
      ? ~ _GL_SIGNED_INT_MAXIMUM (_GL_INT_CONVERT (ans, 256)) \
      : _GL_INT_CONVERT (_GL_INT_CONVERT (ans, 256), 0)) \
     / (256)'
=> '(ans) < \
     (_GL_INT_NEGATE_CONVERT (_GL_INT_CONVERT (ans, 256), 1) < 0) \
      ? ~ _GL_SIGNED_INT_MAXIMUM (_GL_INT_CONVERT (ans, 256)) \
      : _GL_INT_CONVERT (_GL_INT_CONVERT (ans, 256), 0)) \
     / (256)'
=> '(ans) < \
     (((1 ? 0 : (_GL_INT_CONVERT (ans, 256))) - (1)) < 0) \
      ? ~ _GL_SIGNED_INT_MAXIMUM (_GL_INT_CONVERT (ans, 256)) \
      : _GL_INT_CONVERT (_GL_INT_CONVERT (ans, 256), 0)) \
     / (256)'
=> '(ans) < \
     (((1 ? 0 : ((1 ? 0 : (ans)) + (256))) - (1)) < 0) \
      ? ~ (((_GL_INT_CONVERT (_GL_INT_CONVERT (ans, 256), 1) << (TYPE_WIDTH (+ 
(_GL_INT_CONVERT (ans, 256))) - 2)) - 1) * 2 + 1) \
      : _GL_INT_CONVERT (_GL_INT_CONVERT (ans, 256), 0)) \
     / (256)'
=> '(ans) < \
     (((1 ? 0 : ((1 ? 0 : (ans)) + (256))) - (1)) < 0) \
      ? ~ ((((1 ? 0 : (_GL_INT_CONVERT (ans, 256))) + (1)) << (TYPE_WIDTH (+ 
(_GL_INT_CONVERT (ans, 256))) - 2)) - 1) * 2 + 1) \
      : _GL_INT_CONVERT (_GL_INT_CONVERT (ans, 256), 0)) \
     / (256)'
=> '(ans) < \
     (((1 ? 0 : ((1 ? 0 : (ans)) + (256))) - (1)) < 0) \
      ? ~ ((((1 ? 0 : ((1 ? 0 : (ans)) + (256))) + (1)) << (TYPE_WIDTH (+ 
(_GL_INT_CONVERT (ans, 256))) - 2)) - 1) * 2 + 1) \
      : _GL_INT_CONVERT (_GL_INT_CONVERT (ans, 256), 0)) \
     / (256)'
=> '(ans) < \
     (((1 ? 0 : ((1 ? 0 : (ans)) + (256))) - (1)) < 0) \
      ? ~ ((((1 ? 0 : ((1 ? 0 : (ans)) + (256))) + (1)) << ((sizeof (+ 
(_GL_INT_CONVERT (ans, 256))) * CHAR_BIT) - 2)) - 1) * 2 + 1) \
      : _GL_INT_CONVERT (_GL_INT_CONVERT (ans, 256), 0)) \
     / (256)'
=> '(ans) < \
     (((1 ? 0 : ((1 ? 0 : (ans)) + (256))) - (1)) < 0) \
      ? ~ ((((1 ? 0 : ((1 ? 0 : (ans)) + (256))) + (1)) << ((sizeof (+ ((1 ? 0 
: (ans)) + (1))) * CHAR_BIT) - 2)) - 1) * 2 + 1) \
      : _GL_INT_CONVERT (_GL_INT_CONVERT (ans, 256), 0)) \
     / (256)'
=> '(ans) < \
     (((1 ? 0 : ((1 ? 0 : (ans)) + (256))) - (1)) < 0) \
      ? ~ ((((1 ? 0 : ((1 ? 0 : (ans)) + (256))) + (1)) << ((sizeof (+ ((1 ? 0 
: (ans)) + (1))) * CHAR_BIT) - 2)) - 1) * 2 + 1) \
      : ((1 ? 0 : (_GL_INT_CONVERT (ans, 256))) + (0)) ) \
     / (256)'
=> '(ans) < \
     (((1 ? 0 : ((1 ? 0 : (ans)) + (256))) - (1)) < 0) \
      ? ~ ((((1 ? 0 : ((1 ? 0 : (ans)) + (256))) + (1)) << ((sizeof (+ ((1 ? 0 
: (ans)) + (1))) * CHAR_BIT) - 2)) - 1) * 2 + 1) \
      : ((1 ? 0 : ((1 ? 0 : (ans)) + (256))) + (0)) ) \
     / (256)'


'_GL_INT_CONVERT(e, v)' returns a value with the common real type of 'e' and 
'v' and
the value of 'v'. Since the common type of 'unsigned int ans' and '256' is
'unsigned int', '_GL_INT_CONVERT (ans, 256)' is '256U'.

'_GL_INT_MINIMUM (256U)' returns the minimum value of 'unsigned int', i.e. 0.

'(ans) < (_GL_INT_MINIMUM (_GL_INT_CONVERT (ans, 256))) / (256)' => '(ans) < 0 
/ (256)' => '(ans) < 0'

For 'unsigned int ans', the result is always false.

Furthermore, in 'INT_MULTIPLY_RANGE_OVERFLOW', 'a' is 'unsigned int ans' and 'b'
is '256'. We can skip the statements for 'b < 0' and 'b == 0' and reduce the
macro to 

  (a) < 0                \
   ? (a) < (min) / (b)   \
   : (max) / (b) < (a)))
=>
  (ans) < 0                  \
   ? (ans) < (min) / (256)   \
   : (max) / (256) < (ans))) \

Since 'ans' is 'unsigned int', the statement in question, '(a) < (min) / (b)',
is always ignored. Thus, the result of the statement doesn't even matter.

Summary:
  We can ignore CID 435763 because the statement in question is designed to be
  "FALSE" and even ignored.

==================
Daniel Axtens (4):
  posix_wrap: tweaks in preparation for libtasn1
  libtasn1: import libtasn1-4.19.0
  libtasn1: compile into asn1 module
  asn1_test: test module for libtasn1

Gary Lin (23):
  libtasn1: disable code not needed in grub
  libtasn1: replace strcat() with strcpy() in _asn1_str_cat()
  libtasn1: replace strcat() with _asn1_str_cat()
  libtasn1: adjust the header paths in libtasn1.h
  libtasn1: Use grub_divmod64() for division
  libtasn1: fix the potential buffer overrun
  asn1_test: include asn1_test.h only
  asn1_test: rename the main functions to the test names
  asn1_test: return either 0 or 1 to reflect the results
  asn1_test: remove 'verbose' and the unnecessary printf()
  asn1_test: print the error messages with grub_printf()
  asn1_test: use the grub-specific functions and types
  asn1_test: enable the testcase only when GRUB_LONG_MAX is larger than
    GRUB_INT_MAX
  libtasn1: Add the documentation
  tss2: Add TPM2 buffer handling functions
  tss2: Add TPM2 types and Marshal/Unmarshal functions
  tss2: Add TPM2 Software Stack (TSS2) support
  tpm2_key_protector: Support authorized policy
  cryptodisk: wipe out the cached keys from protectors
  diskfilter: look up cryptodisk devices first
  tpm2_key_protector: Add grub-emu support
  tests: Add tpm2_key_protector_test
  docs: Document TPM2 key protector

Hernan Gatta (4):
  key_protector: Add key protectors framework
  key_protector: Add TPM2 Key Protector
  cryptodisk: Support key protectors
  util/grub-protect: Add new tool

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

 .gitignore                                    |    2 +
 Makefile.util.def                             |   39 +
 autogen.sh                                    |   33 +
 configure.ac                                  |   30 +
 docs/grub-dev.texi                            |   35 +
 docs/grub.texi                                |  524 +++-
 docs/man/grub-protect.h2m                     |    4 +
 grub-core/Makefile.am                         |    1 +
 grub-core/Makefile.core.def                   |   60 +
 grub-core/commands/tpm2_key_protector/args.c  |  127 +
 .../commands/tpm2_key_protector/module.c      | 1238 ++++++++
 grub-core/commands/tpm2_key_protector/tpm2.h  |   36 +
 .../commands/tpm2_key_protector/tpm2_args.h   |   49 +
 .../commands/tpm2_key_protector/tpm2key.asn   |   49 +
 .../commands/tpm2_key_protector/tpm2key.c     |  499 ++++
 .../commands/tpm2_key_protector/tpm2key.h     |   87 +
 .../tpm2_key_protector/tpm2key_asn1_tab.c     |   63 +
 grub-core/disk/cryptodisk.c                   |  268 +-
 grub-core/disk/diskfilter.c                   |   31 +-
 grub-core/disk/key_protector.c                |   73 +
 grub-core/kern/emu/main.c                     |   11 +-
 grub-core/kern/emu/misc.c                     |   51 +
 grub-core/lib/efi/tcg2.c                      |  143 +
 ...asn1-disable-code-not-needed-in-grub.patch |  320 +++
 ...-strcat-with-strcpy-in-_asn1_str_cat.patch |   33 +
 ...n1-replace-strcat-with-_asn1_str_cat.patch |   71 +
 ...djust-the-header-paths-in-libtasn1.h.patch |   39 +
 ...tasn1-Use-grub_divmod64-for-division.patch |   31 +
 ...sn1-fix-the-potential-buffer-overrun.patch |   36 +
 ...7-asn1_test-include-asn1_test.h-only.patch |  164 ++
 ...-the-main-functions-to-the-test-name.patch |  129 +
 ...-either-0-or-1-to-reflect-the-result.patch |   78 +
 ...e-verbose-and-the-unnecessary-printf.patch |  173 ++
 ...-the-error-messages-with-grub_printf.patch |  485 ++++
 ...he-grub-specific-functions-and-types.patch |  263 ++
 ...-the-testcase-only-when-GRUB_LONG_MA.patch |   48 +
 grub-core/lib/libtasn1/COPYING                |   16 +
 grub-core/lib/libtasn1/README.md              |   98 +
 grub-core/lib/libtasn1/lib/coding.c           | 1425 ++++++++++
 grub-core/lib/libtasn1/lib/decoding.c         | 2501 +++++++++++++++++
 grub-core/lib/libtasn1/lib/element.c          | 1109 ++++++++
 grub-core/lib/libtasn1/lib/element.h          |   42 +
 grub-core/lib/libtasn1/lib/errors.c           |  100 +
 grub-core/lib/libtasn1/lib/gstr.c             |   74 +
 grub-core/lib/libtasn1/lib/gstr.h             |   50 +
 grub-core/lib/libtasn1/lib/int.h              |  221 ++
 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        | 1225 ++++++++
 grub-core/lib/libtasn1/lib/structure.h        |   46 +
 grub-core/lib/libtasn1/libtasn1.h             |  643 +++++
 .../tests/CVE-2018-1000654-1_asn1_tab.h       |   32 +
 .../tests/CVE-2018-1000654-2_asn1_tab.h       |   36 +
 .../lib/libtasn1/tests/CVE-2018-1000654.c     |   72 +
 grub-core/lib/libtasn1/tests/Test_overflow.c  |  168 ++
 grub-core/lib/libtasn1/tests/Test_simple.c    |  226 ++
 grub-core/lib/libtasn1/tests/Test_strings.c   |  156 +
 .../lib/libtasn1/tests/object-id-decoding.c   |  121 +
 .../lib/libtasn1/tests/object-id-encoding.c   |  133 +
 grub-core/lib/libtasn1/tests/octet-string.c   |  230 ++
 grub-core/lib/libtasn1/tests/reproducers.c    |   90 +
 grub-core/lib/libtasn1_wrap/wrap.c            |   27 +
 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 +
 grub-core/lib/tss2/buffer.c                   |  147 +
 grub-core/lib/tss2/tcg2.h                     |   35 +
 grub-core/lib/tss2/tcg2_emu.c                 |   49 +
 grub-core/lib/tss2/tpm2_cmd.c                 | 1043 +++++++
 grub-core/lib/tss2/tpm2_cmd.h                 |  157 ++
 grub-core/lib/tss2/tss2.c                     |   21 +
 grub-core/lib/tss2/tss2_buffer.h              |   64 +
 grub-core/lib/tss2/tss2_mu.c                  | 1174 ++++++++
 grub-core/lib/tss2/tss2_mu.h                  |  397 +++
 grub-core/lib/tss2/tss2_structs.h             |  796 ++++++
 grub-core/lib/tss2/tss2_types.h               |  404 +++
 grub-core/tests/asn1/asn1_test.c              |   50 +
 grub-core/tests/asn1/asn1_test.h              |   45 +
 grub-core/tests/lib/functional_test.c         |    1 +
 include/grub/cryptodisk.h                     |   16 +
 include/grub/emu/misc.h                       |    5 +
 include/grub/key_protector.h                  |   47 +
 tests/asn1_test.in                            |   11 +
 tests/tpm2_key_protector_test.in              |  389 +++
 tests/util/grub-shell.in                      |    6 +-
 util/grub-protect.c                           | 1407 ++++++++++
 88 files changed, 21843 insertions(+), 80 deletions(-)
 create mode 100644 docs/man/grub-protect.h2m
 create mode 100644 grub-core/commands/tpm2_key_protector/args.c
 create mode 100644 grub-core/commands/tpm2_key_protector/module.c
 create mode 100644 grub-core/commands/tpm2_key_protector/tpm2.h
 create mode 100644 grub-core/commands/tpm2_key_protector/tpm2_args.h
 create mode 100644 grub-core/commands/tpm2_key_protector/tpm2key.asn
 create mode 100644 grub-core/commands/tpm2_key_protector/tpm2key.c
 create mode 100644 grub-core/commands/tpm2_key_protector/tpm2key.h
 create mode 100644 grub-core/commands/tpm2_key_protector/tpm2key_asn1_tab.c
 create mode 100644 grub-core/disk/key_protector.c
 create mode 100644 grub-core/lib/efi/tcg2.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-replace-strcat-with-strcpy-in-_asn1_str_cat.patch
 create mode 100644 
grub-core/lib/libtasn1-patches/0003-libtasn1-replace-strcat-with-_asn1_str_cat.patch
 create mode 100644 
grub-core/lib/libtasn1-patches/0004-libtasn1-adjust-the-header-paths-in-libtasn1.h.patch
 create mode 100644 
grub-core/lib/libtasn1-patches/0005-libtasn1-Use-grub_divmod64-for-division.patch
 create mode 100644 
grub-core/lib/libtasn1-patches/0006-libtasn1-fix-the-potential-buffer-overrun.patch
 create mode 100644 
grub-core/lib/libtasn1-patches/0007-asn1_test-include-asn1_test.h-only.patch
 create mode 100644 
grub-core/lib/libtasn1-patches/0008-asn1_test-rename-the-main-functions-to-the-test-name.patch
 create mode 100644 
grub-core/lib/libtasn1-patches/0009-asn1_test-return-either-0-or-1-to-reflect-the-result.patch
 create mode 100644 
grub-core/lib/libtasn1-patches/0010-asn1_test-remove-verbose-and-the-unnecessary-printf.patch
 create mode 100644 
grub-core/lib/libtasn1-patches/0011-asn1_test-print-the-error-messages-with-grub_printf.patch
 create mode 100644 
grub-core/lib/libtasn1-patches/0012-asn1_test-use-the-grub-specific-functions-and-types.patch
 create mode 100644 
grub-core/lib/libtasn1-patches/0013-asn1_test-enable-the-testcase-only-when-GRUB_LONG_MA.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/libtasn1.h
 create mode 100644 grub-core/lib/libtasn1/tests/CVE-2018-1000654-1_asn1_tab.h
 create mode 100644 grub-core/lib/libtasn1/tests/CVE-2018-1000654-2_asn1_tab.h
 create mode 100644 grub-core/lib/libtasn1/tests/CVE-2018-1000654.c
 create mode 100644 grub-core/lib/libtasn1/tests/Test_overflow.c
 create mode 100644 grub-core/lib/libtasn1/tests/Test_simple.c
 create mode 100644 grub-core/lib/libtasn1/tests/Test_strings.c
 create mode 100644 grub-core/lib/libtasn1/tests/object-id-decoding.c
 create mode 100644 grub-core/lib/libtasn1/tests/object-id-encoding.c
 create mode 100644 grub-core/lib/libtasn1/tests/octet-string.c
 create mode 100644 grub-core/lib/libtasn1/tests/reproducers.c
 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/lib/tss2/buffer.c
 create mode 100644 grub-core/lib/tss2/tcg2.h
 create mode 100644 grub-core/lib/tss2/tcg2_emu.c
 create mode 100644 grub-core/lib/tss2/tpm2_cmd.c
 create mode 100644 grub-core/lib/tss2/tpm2_cmd.h
 create mode 100644 grub-core/lib/tss2/tss2.c
 create mode 100644 grub-core/lib/tss2/tss2_buffer.h
 create mode 100644 grub-core/lib/tss2/tss2_mu.c
 create mode 100644 grub-core/lib/tss2/tss2_mu.h
 create mode 100644 grub-core/lib/tss2/tss2_structs.h
 create mode 100644 grub-core/lib/tss2/tss2_types.h
 create mode 100644 grub-core/tests/asn1/asn1_test.c
 create mode 100644 grub-core/tests/asn1/asn1_test.h
 create mode 100644 include/grub/key_protector.h
 create mode 100644 tests/asn1_test.in
 create mode 100644 tests/tpm2_key_protector_test.in
 create mode 100644 util/grub-protect.c

Range-diff against v20:
 -:  --------- >  1:  2cdb45a08 posix_wrap: tweaks in preparation for libtasn1
 -:  --------- >  2:  f069b4e35 libtasn1: import libtasn1-4.19.0
 -:  --------- >  3:  56bdb8c9c libtasn1: disable code not needed in grub
 -:  --------- >  4:  fd95d1a0c libtasn1: replace strcat() with strcpy() in 
_asn1_str_cat()
 -:  --------- >  5:  b8cf72c0b libtasn1: replace strcat() with _asn1_str_cat()
 -:  --------- >  6:  b274a1e0f libtasn1: adjust the header paths in libtasn1.h
 -:  --------- >  7:  e4581e36e libtasn1: Use grub_divmod64() for division
 -:  --------- >  8:  fdb2a66e7 libtasn1: fix the potential buffer overrun
 -:  --------- >  9:  3739920d3 asn1_test: include asn1_test.h only
 -:  --------- > 10:  1225831f7 asn1_test: rename the main functions to the 
test names
 -:  --------- > 11:  aa4f68b56 asn1_test: return either 0 or 1 to reflect the 
results
 -:  --------- > 12:  83342d997 asn1_test: remove 'verbose' and the unnecessary 
printf()
 -:  --------- > 13:  319d34b9e asn1_test: print the error messages with 
grub_printf()
 -:  --------- > 14:  859e00234 asn1_test: use the grub-specific functions and 
types
 1:  1572cd8af ! 15:  96d7d0998 asn1_test: exclude a testcase when long and int 
are the same
    @@ Metadata
     Author: Gary Lin <glin@suse.com>
     
      ## Commit message ##
    -    asn1_test: exclude a testcase when long and int are the same
    +    asn1_test: enable the testcase only when GRUB_LONG_MAX is larger than 
GRUB_INT_MAX
     
         There is a testcase to test the values larger than 'int' but smaller
         than 'long'. However, for some architectures, 'long' and 'int' are the
    @@ Commit message
                unsigned long num = ((long) GRUB_UINT_MAX) << 2;
                                                           ^~
     
    -    To avoid the unnecessary error, the testcase is opted out when
    -    GRUB_LONG_MAX is not larger than GRUB_INT_MAX.
    +    To avoid unnecessary error the testcase is enabled only when
    +    GRUB_LONG_MAX is larger than GRUB_INT_MAX.
     
         Signed-off-by: Daniel Axtens <dja@axtens.net>
         Signed-off-by: Gary Lin <glin@suse.com>
    +    Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
     
    - ## 
grub-core/lib/libtasn1-patches/0013-asn1_test-exclude-a-testcase-when-long-and-int-are-t.patch
 (new) ##
    + ## 
grub-core/lib/libtasn1-patches/0013-asn1_test-enable-the-testcase-only-when-GRUB_LONG_MA.patch
 (new) ##
     @@
    -+From 737bef13796f6dbeb4178d42bdb1f3e496971d52 Mon Sep 17 00:00:00 2001
    ++From 6d308d9053447dcc003a9ca740c47c00932d3569 Mon Sep 17 00:00:00 2001
     +From: Gary Lin <glin@suse.com>
     +Date: Mon, 7 Oct 2024 11:33:19 +0800
    -+Subject: [PATCH 13/13] asn1_test: exclude a testcase when long and int 
are the
    -+ same
    ++Subject: [PATCH 13/13] asn1_test: enable the testcase only when 
GRUB_LONG_MAX
    ++ is larger than GRUB_INT_MAX
     +
     +There is a testcase to test the values larger than 'int' but smaller
     +than 'long'. However, for some architectures, 'long' and 'int' are the
    @@ 
grub-core/lib/libtasn1-patches/0013-asn1_test-exclude-a-testcase-when-long-and-i
     +       unsigned long num = ((long) GRUB_UINT_MAX) << 2;
     +                                                  ^~
     +
    -+To avoid the unnecessary error, the testcase is opted out when
    -+GRUB_LONG_MAX is not larger than GRUB_INT_MAX.
    ++To avoid unnecessary error the testcase is enabled only when
    ++GRUB_LONG_MAX is larger than GRUB_INT_MAX.
     +
     +Signed-off-by: Daniel Axtens <dja@axtens.net>
     +Signed-off-by: Gary Lin <glin@suse.com>
    ++Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
     +---
     + grub-core/tests/asn1/tests/Test_overflow.c | 3 ++-
     + 1 file changed, 2 insertions(+), 1 deletion(-)
 2:  01bc77f99 = 16:  53ccf29c3 libtasn1: compile into asn1 module
 3:  9cd195194 ! 17:  6501acba8 asn1_test: test module for libtasn1
    @@ autogen.sh: mkdir -p grub-core/lib/libtasn1-grub/lib
     +  0010-asn1_test-remove-verbose-and-the-unnecessary-printf.patch \
     +  0011-asn1_test-print-the-error-messages-with-grub_printf.patch \
     +  0012-asn1_test-use-the-grub-specific-functions-and-types.patch \
    -+  0013-asn1_test-exclude-a-testcase-when-long-and-int-are-t.patch ; do
    ++  0013-asn1_test-enable-the-testcase-only-when-GRUB_LONG_MA.patch ; do
        patch -p1 -i grub-core/lib/libtasn1-patches/$patch
      done
      
 4:  d3b6748e4 = 18:  5fb816190 libtasn1: Add the documentation
 5:  9fed5b9b0 = 19:  1bc53f8fc key_protector: Add key protectors framework
 6:  e2535cf2f = 20:  b1a31f22e tss2: Add TPM2 buffer handling functions
 7:  c7f0aa98c ! 21:  7bc8ac87b tss2: Add TPM2 types and Marshal/Unmarshal 
functions
    @@ grub-core/lib/tss2/tss2_structs.h (new)
     +
     +#include <tss2_types.h>
     +
    ++/*
    ++ * TPM response header
    ++ *   This struct is used to calculate the minimum size of the TPM 2.0 
response.
    ++ *   The format of the response:
    ++ *
    ++ *   +----------------------+
    ++ *   | UINT16 tag           |
    ++ *   +----------------------+
    ++ *   | UINT32 repsonse_size |
    ++ *   +----------------------+
    ++ *   | UINT32 response_code |
    ++ *   +======================+
    ++ *   | response_data        | (optional)
    ++ *   +======================+
    ++ */
    ++struct __attribute__ ((__packed__)) TPM_RESPONSE_HEADER
    ++{
    ++  grub_uint16_t tag;
    ++  grub_uint32_t response_size;
    ++  TPM_RC_t response_code;
    ++};
    ++typedef struct TPM_RESPONSE_HEADER TPM_RESPONSE_HEADER_t;
    ++
     +/* TPMS_TAGGED_PROPERTY Structure */
     +struct TPMS_TAGGED_PROPERTY
     +{
 8:  55ad182d5 = 22:  531c8ed6a tss2: Add TPM2 Software Stack (TSS2) support
 9:  b74c06c22 ! 23:  7f2bf1675 key_protector: Add TPM2 Key Protector
    @@ Commit message
         Cc: James Bottomley <jejb@linux.ibm.com>
         Signed-off-by: Hernan Gatta <hegatta@linux.microsoft.com>
         Signed-off-by: Gary Lin <glin@suse.com>
    +    Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
     
      ## grub-core/Makefile.core.def ##
     @@ grub-core/Makefile.core.def: module = {
    @@ grub-core/commands/tpm2_key_protector/args.c (new)
     +    {
     +      next_pcr = grub_strchr (current_pcr, ',');
     +      if (next_pcr == current_pcr)
    -+  return grub_error (GRUB_ERR_BAD_ARGUMENT, "Empty entry in PCR list");
    ++  return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("empty entry in PCR 
list"));
     +      if (next_pcr != NULL)
     +  *next_pcr = '\0';
     +
     +      pcr = grub_strtoul (current_pcr, &pcr_end, 10);
     +      if (*current_pcr == '\0' || *pcr_end != '\0')
    -+  return grub_error (GRUB_ERR_BAD_NUMBER, "Entry '%s' in PCR list is not 
a number", current_pcr);
    ++  return grub_error (GRUB_ERR_BAD_NUMBER, N_("entry '%s' in PCR list is 
not a number"), current_pcr);
     +
     +      if (pcr > TPM_MAX_PCRS)
    -+  return grub_error (GRUB_ERR_OUT_OF_RANGE, "Entry %" PRIuGRUB_UINT64_T " 
in PCR list is too large to be a PCR number, PCR numbers range from 0 to %u", 
pcr, TPM_MAX_PCRS);
    ++  return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("entry %llu in PCR list is 
too large to be a PCR number, PCR numbers range from 0 to %u"), (unsigned long 
long)pcr, TPM_MAX_PCRS);
     +
     +      pcrs[i] = (grub_uint8_t) pcr;
     +      ++(*pcr_count);
    @@ grub-core/commands/tpm2_key_protector/args.c (new)
     +
     +      current_pcr = next_pcr + 1;
     +      if (*current_pcr == '\0')
    -+  return grub_error (GRUB_ERR_BAD_ARGUMENT, "Trailing comma at the end of 
PCR list");
    ++  return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("trailing comma at the end 
of PCR list"));
     +    }
     +
     +  if (i == TPM_MAX_PCRS)
    -+    return grub_error (GRUB_ERR_OUT_OF_RANGE, "Too many PCRs in PCR list, 
the maximum number of PCRs is %u", TPM_MAX_PCRS);
    ++    return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("too many PCRs in PCR 
list, the maximum number of PCRs is %u"), TPM_MAX_PCRS);
     +
     +  return GRUB_ERR_NONE;
     +}
    @@ grub-core/commands/tpm2_key_protector/args.c (new)
     +      srk_type->detail.rsa_bits = 2048;
     +    }
     +  else
    -+    return grub_error (GRUB_ERR_OUT_OF_RANGE, "Value '%s' is not a valid 
asymmetric key type", value);
    ++    return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("value '%s' is not a 
valid asymmetric key type"), value);
     +
     +  return GRUB_ERR_NONE;
     +}
    @@ grub-core/commands/tpm2_key_protector/args.c (new)
     +  else if (grub_strcasecmp (value, "SHA512") == 0)
     +    *bank = TPM_ALG_SHA512;
     +  else
    -+    return grub_error (GRUB_ERR_OUT_OF_RANGE, "Value '%s' is not a valid 
PCR bank", value);
    ++    return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("value '%s' is not a 
valid PCR bank"), value);
     +
     +  return GRUB_ERR_NONE;
     +}
    @@ grub-core/commands/tpm2_key_protector/args.c (new)
     +
     +  num = grub_strtoul (value, &str_end, 0);
     +  if (*value == '\0' || *str_end != '\0')
    -+    return grub_error (GRUB_ERR_BAD_NUMBER, "TPM handle value '%s' is not 
a number", value);
    ++    return grub_error (GRUB_ERR_BAD_NUMBER, N_("TPM handle value '%s' is 
not a number"), value);
     +
     +  if (num > GRUB_UINT_MAX)
    -+    return grub_error (GRUB_ERR_OUT_OF_RANGE, "Value %" PRIuGRUB_UINT64_T 
"is too large to be a TPM handle, TPM handles are unsigned 32-bit integers", 
num);
    ++    return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("value %llu is too large 
to be a TPM handle, TPM handles are unsigned 32-bit integers"), (unsigned long 
long)num);
     +
     +  *handle = (TPM_HANDLE_t) num;
     +
    @@ grub-core/commands/tpm2_key_protector/module.c (new)
     +    {
     +      /* Push errno from grub_file_open() into the error message stack */
     +      grub_error_push();
    -+      err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "Could not open file: 
%s", filepath);
    ++      err = grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("could not open file: 
%s"), filepath);
     +      goto error;
     +    }
     +
     +  file_size = grub_file_size (file);
     +  if (file_size == 0)
     +    {
    -+      err = grub_error (GRUB_ERR_OUT_OF_RANGE, "Could not read file size: 
%s", filepath);
    ++      err = grub_error (GRUB_ERR_OUT_OF_RANGE, N_("could not read file 
size: %s"), filepath);
     +      goto error;
     +    }
     +
     +  read_buffer = grub_malloc (file_size);
     +  if (read_buffer == NULL)
     +    {
    -+      err = grub_error (GRUB_ERR_OUT_OF_MEMORY, "Could not allocate 
buffer for %s", filepath);
    ++      err = grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("could not allocate 
buffer for %s"), filepath);
     +      goto error;
     +    }
     +
    @@ grub-core/commands/tpm2_key_protector/module.c (new)
     +  if (read_n != file_size)
     +    {
     +      grub_free (read_buffer);
    -+      err = grub_error (GRUB_ERR_FILE_READ_ERROR, "Could not retrieve 
file contents: %s", filepath);
    ++      err = grub_error (GRUB_ERR_FILE_READ_ERROR, N_("could not retrieve 
file contents: %s"), filepath);
     +      goto error;
     +    }
     +
    @@ grub-core/commands/tpm2_key_protector/module.c (new)
     +
     +  grub_tpm2_buffer_init (&buf);
     +  if (sealed_key_size > buf.cap)
    -+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Sealed key larger than %" 
PRIuGRUB_SIZE " bytes", buf.cap);
    ++    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("sealed key larger than 
%llu bytes"), (unsigned long long)buf.cap);
     +
     +  grub_memcpy (buf.data, sealed_key, sealed_key_size);
     +  buf.size = sealed_key_size;
    @@ grub-core/commands/tpm2_key_protector/module.c (new)
     +  grub_Tss2_MU_TPM2B_PRIVATE_Unmarshal (&buf, &sk->private);
     +
     +  if (buf.error != 0)
    -+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Malformed TPM wire key 
file");
    ++    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("malformed TPM wire key 
file"));
     +
     +  return GRUB_ERR_NONE;
     +}
    @@ grub-core/commands/tpm2_key_protector/module.c (new)
     +  grub_tpm2_buffer_init (&buf);
     +  if (sealed_pub_size + sealed_priv_size > buf.cap)
     +    {
    -+      err = grub_error (GRUB_ERR_BAD_ARGUMENT, "Sealed key larger than %" 
PRIuGRUB_SIZE " bytes", buf.cap);
    ++      err = grub_error (GRUB_ERR_BAD_ARGUMENT, N_("sealed key larger than 
%llu bytes"), (unsigned long long)buf.cap);
     +      goto error;
     +    }
     +
    @@ grub-core/commands/tpm2_key_protector/module.c (new)
     +
     +  if (buf.error != 0)
     +    {
    -+      err = grub_error (GRUB_ERR_BAD_ARGUMENT, "Malformed TPM 2.0 key 
file");
    ++      err = grub_error (GRUB_ERR_BAD_ARGUMENT, N_("malformed TPM 2.0 key 
file"));
     +      goto error;
     +    }
     +
    @@ grub-core/commands/tpm2_key_protector/module.c (new)
     +  if (rc == TPM_RC_SUCCESS)
     +    return GRUB_ERR_NONE;
     +
    -+  return grub_error (GRUB_ERR_BAD_ARGUMENT, "Failed to retrieve SRK from 
0x%x (TPM2_ReadPublic: 0x%x)", srk_handle, rc);
    ++  return grub_error (GRUB_ERR_BAD_ARGUMENT, "failed to retrieve SRK from 
0x%x (TPM2_ReadPublic: 0x%x)", srk_handle, rc);
     +}
     +
     +/* Get the SRK with the template */
    @@ grub-core/commands/tpm2_key_protector/module.c (new)
     +      inPublic.publicArea.parameters.eccDetail.kdf.scheme = TPM_ALG_NULL;
     +    }
     +  else
    -+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Unknown SRK algorithm");
    ++    return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown SRK algorithm");
     +
     +  /* Test the parameters before SRK generation */
     +  parms.type = srk_type.type;
    @@ grub-core/commands/tpm2_key_protector/module.c (new)
     +
     +  rc = grub_tpm2_testparms (&parms, NULL);
     +  if (rc != TPM_RC_SUCCESS)
    -+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported SRK template 
(TPM2_TestParms: 0x%x)", rc);
    ++    return grub_error (GRUB_ERR_BAD_ARGUMENT, "unsupported SRK template 
(TPM2_TestParms: 0x%x)", rc);
     +
     +  /* Create SRK */
     +  authCommand.sessionHandle = TPM_RS_PW;
    @@ grub-core/commands/tpm2_key_protector/module.c (new)
     +                          &creationData, &creationHash, &creationTicket,
     +                          &srkName, NULL);
     +  if (rc != TPM_RC_SUCCESS)
    -+    return grub_error (GRUB_ERR_BAD_DEVICE, "Could not create SRK 
(TPM2_CreatePrimary: 0x%x)", rc);
    ++    return grub_error (GRUB_ERR_BAD_DEVICE, "could not create SRK 
(TPM2_CreatePrimary: 0x%x)", rc);
     +
     +  *srk_handle = tmp_handle;
     +
    @@ grub-core/commands/tpm2_key_protector/module.c (new)
     +    }
     +  else if (rc != TPM_RC_SUCCESS)
     +    {
    -+      err = grub_error (GRUB_ERR_BAD_DEVICE, "Failed to load sealed key 
(TPM2_Load: 0x%x)", rc);
    ++      err = grub_error (GRUB_ERR_BAD_DEVICE, "failed to load sealed key 
(TPM2_Load: 0x%x)", rc);
     +      goto error;
     +    }
     +
    @@ grub-core/commands/tpm2_key_protector/module.c (new)
     +  grub_Tss2_MU_TPM2B_DIGEST_Unmarshal (cmd_buf, &pcr_digest);
     +  grub_Tss2_MU_TPML_PCR_SELECTION_Unmarshal (cmd_buf, &pcr_sel);
     +  if (cmd_buf->error != 0)
    -+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Failed to unmarshal 
CommandPolicy for TPM2_PolicyPCR");
    ++    return grub_error (GRUB_ERR_BAD_ARGUMENT, "failed to unmarshal 
commandPolicy for TPM2_PolicyPCR");
     +
     +  rc = grub_tpm2_policypcr (session, NULL, &pcr_digest, &pcr_sel, NULL);
     +  if (rc != TPM_RC_SUCCESS)
    -+    return grub_error (GRUB_ERR_BAD_DEVICE, "Failed to submit PCR policy 
(TPM2_PolicyPCR: 0x%x)", rc);
    ++    return grub_error (GRUB_ERR_BAD_DEVICE, "failed to submit PCR policy 
(TPM2_PolicyPCR: 0x%x)", rc);
     +
     +  return GRUB_ERR_NONE;
     +}
    @@ grub-core/commands/tpm2_key_protector/module.c (new)
     +      err = tpm2_protector_policypcr (session, &buf);
     +      break;
     +    default:
    -+      return grub_error (GRUB_ERR_BAD_ARGUMENT, "Unknown TPM Command: 
0x%x", policy->cmd_code);
    ++      return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown TPM Command: 
0x%x", policy->cmd_code);
     +    }
     +
     +  return err;
    @@ grub-core/commands/tpm2_key_protector/module.c (new)
     +                             TPM_SE_POLICY, &symmetric, TPM_ALG_SHA256,
     +                             &session, NULL, NULL);
     +  if (rc != TPM_RC_SUCCESS)
    -+    return grub_error (GRUB_ERR_BAD_DEVICE, "Failed to start auth session 
(TPM2_StartAuthSession: 0x%x)", rc);
    ++    return grub_error (GRUB_ERR_BAD_DEVICE, "failed to start auth session 
(TPM2_StartAuthSession: 0x%x)", rc);
     +
     +  /* Enforce the policy command sequence */
     +  err = tpm2_protector_enforce_policy_seq (policy_seq, session);
    @@ grub-core/commands/tpm2_key_protector/module.c (new)
     +  rc = grub_tpm2_unseal (sealed_handle, &authCmd, &data, NULL);
     +  if (rc != TPM_RC_SUCCESS)
     +    {
    -+      err = grub_error (GRUB_ERR_BAD_DEVICE, "Failed to unseal sealed key 
(TPM2_Unseal: 0x%x)", rc);
    ++      err = grub_error (GRUB_ERR_BAD_DEVICE, "failed to unseal sealed key 
(TPM2_Unseal: 0x%x)", rc);
     +      goto error;
     +    }
     +
    @@ grub-core/commands/tpm2_key_protector/module.c (new)
     +  key_out = grub_malloc (data.size);
     +  if (key_out == NULL)
     +    {
    -+      err = grub_error (GRUB_ERR_OUT_OF_MEMORY, "No memory left to 
allocate unlock key buffer");
    ++      err = grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("no memory left to 
allocate unlock key buffer"));
     +      goto error;
     +    }
     +
    @@ grub-core/commands/tpm2_key_protector/module.c (new)
     +{
     +  /* Expect a call to tpm2_protector_init before anybody tries to use us 
*/
     +  if (tpm2_protector_ctx.mode == TPM2_PROTECTOR_MODE_UNSET)
    -+    return grub_error (GRUB_ERR_INVALID_COMMAND, "Cannot use TPM2 key 
protector without initializing it, call tpm2_protector_init first");
    ++    return grub_error (GRUB_ERR_INVALID_COMMAND, N_("cannot use TPM2 key 
protector without initializing it, call tpm2_protector_init first"));
     +
     +  if (key == NULL || key_size == NULL)
     +    return GRUB_ERR_BAD_ARGUMENT;
    @@ grub-core/commands/tpm2_key_protector/module.c (new)
     +  /* Checks for SRK mode */
     +  if (ctx->mode == TPM2_PROTECTOR_MODE_SRK &&
     +      (ctx->keyfile == NULL && ctx->tpm2key == NULL))
    -+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "In SRK mode, a key file 
must be specified: --tpm2key/-T or --keyfile/-k");
    ++    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("in SRK mode, a key file 
must be specified: --tpm2key/-T or --keyfile/-k"));
     +
     +  if (ctx->mode == TPM2_PROTECTOR_MODE_SRK &&
     +      (ctx->keyfile != NULL && ctx->tpm2key != NULL))
    -+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "In SRK mode, please 
specify a key file with only --tpm2key/-T or --keyfile/-k");
    ++    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("in SRK mode, please 
specify a key file with only --tpm2key/-T or --keyfile/-k"));
     +
     +  if (ctx->mode == TPM2_PROTECTOR_MODE_SRK && ctx->nv != 0)
    -+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "In SRK mode, an NV Index 
cannot be specified");
    ++    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("in SRK mode, an NV 
Index cannot be specified"));
     +
     +  /* Checks for NV mode */
     +  if (ctx->mode == TPM2_PROTECTOR_MODE_NV && ctx->nv == 0)
    -+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "In NV Index mode, an NV 
Index must be specified: --nvindex or -n");
    ++    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("in NV Index mode, an NV 
Index must be specified: --nvindex or -n"));
     +
     +  if (ctx->mode == TPM2_PROTECTOR_MODE_NV &&
     +      (ctx->tpm2key != NULL || ctx->keyfile != NULL))
    -+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "In NV Index mode, a 
keyfile cannot be specified");
    ++    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("in NV Index mode, a 
keyfile cannot be specified"));
     +
     +  if (ctx->mode == TPM2_PROTECTOR_MODE_NV && ctx->srk != 0)
    -+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "In NV Index mode, an SRK 
cannot be specified");
    ++    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("in NV Index mode, an 
SRK cannot be specified"));
     +
     +  if (ctx->mode == TPM2_PROTECTOR_MODE_NV &&
     +      ctx->srk_type.type != TPM_ALG_ERROR)
    -+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "In NV Index mode, an 
asymmetric key type cannot be specified");
    ++    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("in NV Index mode, an 
asymmetric key type cannot be specified"));
     +
     +  /* Defaults assignment */
     +  if (ctx->bank == TPM_ALG_ERROR)
    @@ grub-core/commands/tpm2_key_protector/module.c (new)
     +
     +  *file = grub_strdup (value);
     +  if (*file == NULL)
    -+    return grub_error (GRUB_ERR_OUT_OF_MEMORY, "No memory to duplicate 
file path");
    ++    return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("no memory to duplicate 
file path"));
     +
     +  return GRUB_ERR_NONE;
     +}
    @@ grub-core/commands/tpm2_key_protector/module.c (new)
     +  else if (grub_strcmp (value, "nv") == 0)
     +    *mode = TPM2_PROTECTOR_MODE_NV;
     +  else
    -+    return grub_error (GRUB_ERR_OUT_OF_RANGE, "Value '%s' is not a valid 
TPM2 key protector mode", value);
    ++    return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("value '%s' is not a 
valid TPM2 key protector mode"), value);
     +
     +  return GRUB_ERR_NONE;
     +}
    @@ grub-core/commands/tpm2_key_protector/module.c (new)
     +  grub_err_t err;
     +
     +  if (argc)
    -+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "The TPM2 key protector 
does not accept any non-option arguments (i.e., like -o and/or --option only)");
    ++    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("the TPM2 key protector 
does not accept any non-option arguments (i.e., like -o and/or --option 
only)"));
     +
     +  grub_free ((void *) tpm2_protector_ctx.keyfile);
     +  grub_memset (&tpm2_protector_ctx, 0, sizeof (tpm2_protector_ctx));
    @@ grub-core/commands/tpm2_key_protector/module.c (new)
     +tpm2_protector_clear_cmd_handler (grub_extcmd_context_t ctxt 
__attribute__ ((unused)),
     +                            int argc, char **args __attribute__ 
((unused)))
     +{
    -+  if (argc)
    -+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "tpm2_key_protector_clear 
accepts no arguments");
    ++  if (argc != 0)
    ++    return grub_error (GRUB_ERR_BAD_ARGUMENT, 
N_("tpm2_key_protector_clear accepts no arguments"));
     +
     +  grub_free ((void *) tpm2_protector_ctx.keyfile);
     +  grub_memset (&tpm2_protector_ctx, 0, sizeof (tpm2_protector_ctx));
    @@ grub-core/commands/tpm2_key_protector/tpm2_args.h (new)
     +};
     +typedef struct grub_srk_type grub_srk_type_t;
     +
    -+grub_err_t
    ++extern grub_err_t
     +grub_tpm2_protector_parse_pcrs (char *value, grub_uint8_t *pcrs, 
grub_uint8_t *pcr_count);
     +
    -+grub_err_t
    ++extern grub_err_t
     +grub_tpm2_protector_parse_asymmetric (const char *value, grub_srk_type_t 
*srk_type);
     +
    -+grub_err_t
    ++extern grub_err_t
     +grub_tpm2_protector_parse_bank (const char *value, TPM_ALG_ID_t *bank);
     +
    -+grub_err_t
    ++extern grub_err_t
     +grub_tpm2_protector_parse_tpm_handle (const char *value, TPM_HANDLE_t 
*handle);
     +
     +#endif /* ! GRUB_TPM2_INTERNAL_ARGS_HEADER */
    @@ grub-core/commands/tpm2_key_protector/tpm2key.c (new)
     +   */
     +  ret = asn1_array2tree (tpm2key_asn1_tab, &tpm2key_asn1, NULL);
     +  if (ret != ASN1_SUCCESS)
    -+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Failed to parse TPM2KEY 
ASN.1 array");
    ++    return grub_error (GRUB_ERR_BAD_ARGUMENT, "failed to parse TPM2KEY 
ASN.1 array");
     +
     +  ret = asn1_create_element (tpm2key_asn1, "TPM2KEY.TPMKey", &tpm2key);
     +  if (ret != ASN1_SUCCESS)
    -+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Failed to create 
TPM2KEY.TPMKey");
    ++    return grub_error (GRUB_ERR_BAD_ARGUMENT, "failed to create 
TPM2KEY.TPMKey");
     +
     +  ret = asn1_der_decoding (&tpm2key, data, size, NULL);
     +  if (ret != ASN1_SUCCESS)
    -+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Failed to decode TPM2KEY 
DER");
    ++    return grub_error (GRUB_ERR_BAD_ARGUMENT, "failed to decode TPM2KEY 
DER");
     +
     +  /* Check if 'type' is Sealed Key or not */
     +  ret = asn1_allocate_and_read (tpm2key, "type", &type_oid, 
&type_oid_size);
     +  if (ret != ASN1_SUCCESS)
    -+    return grub_error (GRUB_ERR_BAD_FILE_TYPE, "Not a valid TPM2KEY 
file");
    ++    return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a valid TPM2KEY 
file");
     +
     +  if (grub_memcmp (sealed_key_oid, type_oid, type_oid_size) != 0)
     +    {
    -+      err = grub_error (GRUB_ERR_BAD_FILE_TYPE, "Not a valid TPM2KEY 
file");
    ++      err = grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a valid TPM2KEY 
file");
     +      goto error;
     +    }
     +
    @@ grub-core/commands/tpm2_key_protector/tpm2key.c (new)
     +    return grub_error (GRUB_ERR_BAD_ARGUMENT, "NULL pointer detected");
     +
     +  if (tpm2key == NULL)
    -+    return grub_error (GRUB_ERR_READ_ERROR, "Invalid parent node");
    ++    return grub_error (GRUB_ERR_READ_ERROR, "invalid parent node");
     +
     +  ret = asn1_allocate_and_read (tpm2key, "rsaParent", &bool_str, 
&bool_str_size);
     +  if (ret == ASN1_SUCCESS)
    @@ grub-core/commands/tpm2_key_protector/tpm2key.c (new)
     +  else if (ret == ASN1_ELEMENT_NOT_FOUND)
     +    *rsaparent = 0;
     +  else
    -+    return grub_error (GRUB_ERR_READ_ERROR, "Failed to retrieve 
rsaParent");
    ++    return grub_error (GRUB_ERR_READ_ERROR, "failed to retrieve 
rsaParent");
     +
     +  grub_free (bool_str);
     +
    @@ grub-core/commands/tpm2_key_protector/tpm2key.c (new)
     +    return grub_error (GRUB_ERR_BAD_ARGUMENT, "NULL pointer detected");
     +
     +  if (tpm2key == NULL)
    -+    return grub_error (GRUB_ERR_READ_ERROR, "Invalid parent node");
    ++    return grub_error (GRUB_ERR_READ_ERROR, "invalid parent node");
     +
     +  ret = asn1_read_uint32 (tpm2key, "parent", parent);
     +  if (ret != ASN1_SUCCESS)
    -+    return grub_error (GRUB_ERR_READ_ERROR, "Failed to retrieve parent");
    ++    return grub_error (GRUB_ERR_READ_ERROR, "failed to retrieve parent");
     +
     +  return GRUB_ERR_NONE;
     +}
    @@ grub-core/commands/tpm2_key_protector/tpm2key.c (new)
     +  int ret;
     +
     +  if (name == NULL || data == NULL || size == NULL)
    -+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid parameter(s)");
    ++    return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid parameter(s)");
     +
     +  if (tpm2key == NULL)
    -+    return grub_error (GRUB_ERR_READ_ERROR, "Invalid %s node", name);
    ++    return grub_error (GRUB_ERR_READ_ERROR, "invalid %s node", name);
     +
     +  ret = asn1_allocate_and_read (tpm2key, name, data, size);
     +  if (ret != ASN1_SUCCESS)
    -+    return grub_error (GRUB_ERR_READ_ERROR, "Failed to retrieve %s", 
name);
    ++    return grub_error (GRUB_ERR_READ_ERROR, "failed to retrieve %s", 
name);
     +
     +  return GRUB_ERR_NONE;
     +}
    @@ grub-core/commands/tpm2_key_protector/tpm2key.c (new)
     +      return GRUB_ERR_NONE;
     +    }
     +  else if (ret != ASN1_SUCCESS)
    -+    return grub_error (GRUB_ERR_READ_ERROR, "Failed to retrieve policy");
    ++    return grub_error (GRUB_ERR_READ_ERROR, "failed to retrieve policy");
     +
     +  return GRUB_ERR_NONE;
     +}
    @@ grub-core/commands/tpm2_key_protector/tpm2key.c (new)
     +      return GRUB_ERR_NONE;
     +    }
     +  else if (ret != ASN1_SUCCESS)
    -+    return grub_error (GRUB_ERR_READ_ERROR, "Failed to retrieve 
authPolicy");
    ++    return grub_error (GRUB_ERR_READ_ERROR, "failed to retrieve 
authPolicy");
     +
     +  /* Limit the number of authPolicy elements to two digits (99) */
     +  if (authpol_n > TPM2KEY_ELEMENTS_MAX || authpol_n < 
TPM2KEY_ELEMENTS_MIN)
    -+    return grub_error (GRUB_ERR_OUT_OF_RANGE, "Invalid number of 
authPolicy elements");
    ++    return grub_error (GRUB_ERR_OUT_OF_RANGE, "invalid number of 
authPolicy elements");
     +
     +  /*
     +   * Iterate the authPolicy elements backwards since grub_list_push() 
prepends
    @@ grub-core/commands/tpm2_key_protector/tpm2key.c (new)
     +    authpol = grub_zalloc (sizeof (struct tpm2key_authpolicy));
     +    if (authpol == NULL)
     +      {
    -+  err = grub_error (GRUB_ERR_OUT_OF_MEMORY, "Failed to allocate memory 
for authPolicy");
    ++  err = grub_error (GRUB_ERR_OUT_OF_MEMORY, "failed to allocate memory 
for authPolicy");
     +  goto error;
     +      }
     +    grub_snprintf (authpol_pol, AUTHPOLICY_POL_MAX, 
"authPolicy.?%d.Policy", i);
    @@ grub-core/commands/tpm2_key_protector/tpm2key.c (new)
     +    ret = tpm2key_get_policy_seq (tpm2key, authpol_pol, 
&authpol->policy_seq);
     +    if (ret != ASN1_SUCCESS)
     +      {
    -+        err = grub_error (GRUB_ERR_READ_ERROR, "Failed to retrieve policy 
from authPolicy");
    ++        err = grub_error (GRUB_ERR_READ_ERROR, "failed to retrieve policy 
from authPolicy");
     +        goto error;
     +      }
     +
    @@ grub-core/commands/tpm2_key_protector/tpm2key.h (new)
     +};
     +typedef struct tpm2key_authpolicy *tpm2key_authpolicy_t;
     +
    -+grub_err_t
    ++extern grub_err_t
     +grub_tpm2key_start_parsing (asn1_node *parsed_tpm2key, void *data, 
grub_size_t size);
     +
    -+void
    ++extern void
     +grub_tpm2key_end_parsing (asn1_node tpm2key);
     +
    -+grub_err_t
    ++extern grub_err_t
     +grub_tpm2key_get_rsaparent (asn1_node tpm2key, grub_uint8_t *rsaparent);
     +
    -+grub_err_t
    ++extern grub_err_t
     +grub_tpm2key_get_parent (asn1_node tpm2key, grub_uint32_t *parent);
     +
    -+grub_err_t
    ++extern grub_err_t
     +grub_tpm2key_get_pubkey (asn1_node tpm2key, void **data, grub_size_t 
*size);
     +
    -+grub_err_t
    ++extern grub_err_t
     +grub_tpm2key_get_privkey (asn1_node tpm2key, void **data, grub_size_t 
*size);
     +
    -+grub_err_t
    ++extern grub_err_t
     +grub_tpm2key_get_policy_seq (asn1_node tpm2key, tpm2key_policy_t 
*policy_seq);
     +
    -+void
    ++extern void
     +grub_tpm2key_free_policy_seq (tpm2key_policy_t policy_seq);
     +
    -+grub_err_t
    ++extern grub_err_t
     +grub_tpm2key_get_authpolicy_seq (asn1_node tpm2key, tpm2key_authpolicy_t 
*authpol_seq);
     +
    -+void
    ++extern void
     +grub_tpm2key_free_authpolicy_seq (tpm2key_authpolicy_t authpol_seq);
     +
     +#endif /* GRUB_TPM2_TPM2KEY_HEADER */
10:  903b1249b = 24:  3347a97c5 cryptodisk: Support key protectors
11:  5fdb8b86f ! 25:  12c7c467b util/grub-protect: Add new tool
    @@ util/grub-protect.c (new)
     +      .arg   = NULL,
     +      .flags = 0,
     +      .doc   =
    -+  N_("Use TPM 2.0 Key File instead of the raw format."),
    ++  N_("Use TPM 2.0 Key File format."),
     +      .group = 0
     +    },
     +    /* End of list */
    @@ util/grub-protect.c (new)
     +
     +  f = fopen (filepath, "rb");
     +  if (f == NULL)
    -+    return GRUB_ERR_FILE_NOT_FOUND;
    ++    {
    ++      fprintf (stderr, N_("Could not open file: %s\n"), filepath);
    ++      return GRUB_ERR_FILE_NOT_FOUND;
    ++    }
     +
     +  if (fseek (f, 0, SEEK_END))
     +    {
    -+       err = GRUB_ERR_FILE_READ_ERROR;
    -+       goto exit1;
    ++      fprintf (stderr, N_("Could not seek file: %s\n"), filepath);
    ++      err = GRUB_ERR_FILE_READ_ERROR;
    ++      goto exit1;
     +    }
     +
     +  len = ftell (f);
     +  if (len <= 0)
     +    {
    -+       err = GRUB_ERR_FILE_READ_ERROR;
    -+       goto exit1;
    ++      fprintf (stderr, N_("Could not get file length: %s\n"), filepath);
    ++      err = GRUB_ERR_FILE_READ_ERROR;
    ++      goto exit1;
     +    }
     +
     +  rewind (f);
    @@ util/grub-protect.c (new)
     +  buf = grub_malloc (len);
     +  if (buf == NULL)
     +    {
    -+       err = GRUB_ERR_OUT_OF_MEMORY;
    -+       goto exit1;
    ++      fprintf (stderr, N_("Could not allocate memory for file: %s\n"), 
filepath);
    ++      err = GRUB_ERR_OUT_OF_MEMORY;
    ++      goto exit1;
     +    }
     +
     +  if (fread (buf, len, 1, f) != 1)
     +    {
    -+       err = GRUB_ERR_FILE_READ_ERROR;
    -+       goto exit2;
    ++      fprintf (stderr, N_("Could not read file: %s\n"), filepath);
    ++      err = GRUB_ERR_FILE_READ_ERROR;
    ++      goto exit2;
     +    }
     +
     +  *buffer = buf;
    @@ util/grub-protect.c (new)
     +grub_tcg2_submit_command (grub_size_t input_size, grub_uint8_t *input,
     +                    grub_size_t output_size, grub_uint8_t *output)
     +{
    -+  static const grub_size_t header_size = sizeof (grub_uint16_t) +
    -+                                   (2 * sizeof(grub_uint32_t));
    -+
     +  if (write (protector_tpm2_fd, input, input_size) != input_size)
    -+    return GRUB_ERR_BAD_DEVICE;
    ++    {
    ++      fprintf (stderr, N_("Could not send TPM command.\n"));
    ++      return GRUB_ERR_BAD_DEVICE;
    ++    }
     +
    -+  if (read (protector_tpm2_fd, output, output_size) < header_size)
    -+    return GRUB_ERR_BAD_DEVICE;
    ++  if (read (protector_tpm2_fd, output, output_size) < sizeof 
(TPM_RESPONSE_HEADER_t))
    ++    {
    ++      fprintf (stderr, N_("Could not get TPM response.\n"));
    ++      return GRUB_ERR_BAD_DEVICE;
    ++    }
     +
     +  return GRUB_ERR_NONE;
     +}
    @@ util/grub-protect.c (new)
     +  protector_tpm2_fd = open (dev_node, O_RDWR);
     +  if (protector_tpm2_fd == -1)
     +    {
    -+      fprintf (stderr, "Could not open TPM device (%s).\n", strerror 
(errno));
    ++      fprintf (stderr, N_("Could not open TPM device (%s).\n"), strerror 
(errno));
     +      return GRUB_ERR_FILE_NOT_FOUND;
     +    }
     +
    @@ util/grub-protect.c (new)
     +  err = close (protector_tpm2_fd);
     +  if (err != GRUB_ERR_NONE)
     +  {
    -+    fprintf (stderr, "Could not close TPM device (Error: %u).\n", errno);
    ++    fprintf (stderr, N_("Could not close TPM device (%s).\n"), strerror 
(errno));
     +    return GRUB_ERR_IO;
     +  }
     +
    @@ util/grub-protect.c (new)
     +       (pcr_sel.pcrSelections[0].sizeOfSelect !=
     +  pcr_sel_out.pcrSelections[0].sizeOfSelect))
     +    {
    -+      fprintf (stderr, "Could not read all the specified PCRs.\n");
    ++      fprintf (stderr, N_("Could not read all the specified PCRs.\n"));
     +      return GRUB_ERR_BAD_DEVICE;
     +    }
     +
    @@ util/grub-protect.c (new)
     +  pcr_concat_len = pcr_digest_len * args->tpm2_pcr_count;
     +  if (pcr_concat_len > TPM_MAX_DIGEST_BUFFER)
     +    {
    -+      fprintf (stderr, "PCR concatenation buffer not enough.\n");
    ++      fprintf (stderr, N_("PCR concatenation buffer not enough.\n"));
     +      return GRUB_ERR_OUT_OF_RANGE;
     +    }
     +
    @@ util/grub-protect.c (new)
     +      if (pcr_values.digests[i].size != pcr_digest_len)
     +  {
     +    fprintf (stderr,
    -+             "Bad PCR value size: expected %" PRIuGRUB_SIZE " bytes but 
got %u bytes.\n",
    -+             pcr_digest_len, pcr_values.digests[i].size);
    ++             N_("Bad PCR value size: expected %llu bytes but got %u 
bytes.\n"),
    ++             (long long unsigned int)pcr_digest_len, 
pcr_values.digests[i].size);
     +    return GRUB_ERR_BAD_ARGUMENT;
     +  }
     +
    @@ util/grub-protect.c (new)
     +
     +extern asn1_static_node tpm2key_asn1_tab[];
     +
    ++/* id-sealedkey OID defined in TPM 2.0 Key Files Spec */
    ++#define TPM2KEY_SEALED_KEY_OID "2.23.133.10.1.5"
    ++
     +static grub_err_t
     +protect_tpm2_export_tpm2key (const protect_args_t *args,
     +                       tpm2_sealed_key_t *sealed_key)
     +{
    -+  const char *sealed_key_oid = "2.23.133.10.1.5";
    ++  const char *sealed_key_oid = TPM2KEY_SEALED_KEY_OID;
     +  asn1_node asn1_def = NULL;
     +  asn1_node tpm2key = NULL;
     +  grub_uint32_t parent;
    @@ util/grub-protect.c (new)
     +
     +  err = protect_write_file (args->tpm2_outfile, der_buf, der_buf_size);
     +  if (err != GRUB_ERR_NONE)
    -+    fprintf (stderr, "Could not write tpm2key file (Error: %u).\n", 
errno);
    ++    fprintf (stderr, N_("Could not write tpm2key file (%s).\n"), strerror 
(errno));
     +
     + error:
     +  grub_free (der_buf);
    @@ util/grub-protect.c (new)
     +
     +  err = protect_write_file (filepath, buf.data, buf.size);
     +  if (err != GRUB_ERR_NONE)
    -+    fprintf (stderr, "Could not write sealed key file (Error: %u).\n", 
errno);
    ++    fprintf (stderr, N_("Could not write sealed key file (%s).\n"), 
strerror (errno));
     +
     +  return err;
     +}
    @@ util/grub-protect.c (new)
     +    goto exit1;
     +
     +  if (key_size > TPM_MAX_SYM_DATA)
    -+  {
    -+    fprintf (stderr, "Input key size larger than %u bytes.\n", 
TPM_MAX_SYM_DATA);
    -+    err = GRUB_ERR_OUT_OF_RANGE;
    -+    goto exit2;
    -+  }
    ++    {
    ++      fprintf (stderr, N_("Input key size larger than %u bytes.\n"), 
TPM_MAX_SYM_DATA);
    ++      err = GRUB_ERR_OUT_OF_RANGE;
    ++      goto exit2;
    ++    }
     +
     +  err = protect_tpm2_get_srk (args, &srk);
     +  if (err != GRUB_ERR_NONE)
    @@ util/grub-protect.c (new)
     +static grub_err_t
     +protect_tpm2_args_verify (protect_args_t *args)
     +{
    ++  if (args->tpm2_device == NULL)
    ++    args->tpm2_device = "/dev/tpm0";
    ++
     +  switch (args->action)
     +    {
     +    case PROTECT_ACTION_ADD:
    @@ util/grub-protect.c (new)
     +    return GRUB_ERR_BAD_ARGUMENT;
     +  }
     +
    -+      if (args->tpm2_device == NULL)
    -+  args->tpm2_device = "/dev/tpm0";
    -+
     +      if (args->tpm2_pcr_count == 0)
     +  {
     +    args->tpm2_pcrs[0] = 7;
    @@ util/grub-protect.c (new)
     +    return GRUB_ERR_BAD_ARGUMENT;
     +  }
     +
    -+      if (args->tpm2_device == NULL)
    -+  args->tpm2_device = "/dev/tpm0";
    -+
     +      break;
     +
     +    default:
    @@ util/grub-protect.c (new)
     +      return GRUB_ERR_BAD_ARGUMENT;
     +    }
     +
    -+  /* At the moment, the only configurable key protector is the TPM2 one, 
so it
    -+   * is the only key protector supported by this tool. */
    ++  /*
    ++   * At the moment, the only configurable key protector is the TPM2 one, 
so it
    ++   * is the only key protector supported by this tool.
    ++   */
     +  if (args->protector != PROTECT_TYPE_TPM2)
     +    {
     +      fprintf (stderr, N_("--protector is mandatory and only 'tpm2' is 
currently supported.\n"));
    @@ util/grub-protect.c (new)
     +  if (argp_parse (&protect_argp, argc, argv, 0, 0, &args) != 0)
     +    {
     +      fprintf (stderr, N_("Could not parse arguments.\n"));
    -+      return GRUB_ERR_BAD_ARGUMENT;
    ++      return EXIT_FAILURE;
     +    }
     +
     +  protect_init (&argc, &argv);
    @@ util/grub-protect.c (new)
     +    goto exit;
     +
     +  err = protect_dispatch (&args);
    -+  if (err != GRUB_ERR_NONE)
    -+    goto exit;
     +
     + exit:
     +  protect_fini ();
     +
    -+  return err;
    ++  if (err != GRUB_ERR_NONE)
    ++    return EXIT_FAILURE;
    ++
    ++  return EXIT_SUCCESS;
     +}
12:  b9194893a ! 26:  677a1b1e9 tpm2_key_protector: Support authorized policy
    @@ grub-core/commands/tpm2_key_protector/module.c: tpm2_protector_policypcr 
(TPMI_S
     +  grub_Tss2_MU_TPM2B_DIGEST_Unmarshal (cmd_buf, &policy_ref);
     +  grub_Tss2_MU_TPMT_SIGNATURE_Unmarshal (cmd_buf, &signature);
     +  if (cmd_buf->error != 0)
    -+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Failed to unmarshal the 
buffer for TPM2_PolicyAuthorize");
    ++    return grub_error (GRUB_ERR_BAD_ARGUMENT, "failed to unmarshal the 
buffer for TPM2_PolicyAuthorize");
     +
     +  /* Retrieve Policy Digest */
     +  rc = grub_tpm2_policygetdigest (session, NULL, &pcr_policy, NULL);
     +  if (rc != TPM_RC_SUCCESS)
    -+    return grub_error (GRUB_ERR_BAD_DEVICE, "Failed to get policy digest 
(TPM2_PolicyGetDigest: 0x%x).", rc);
    ++    return grub_error (GRUB_ERR_BAD_DEVICE, "failed to get policy digest 
(TPM2_PolicyGetDigest: 0x%x).", rc);
     +
     +  /* Calculate the digest of the polcy for VerifySignature */
     +  sig_hash = TPMT_SIGNATURE_get_hash_alg (&signature);
     +  if (sig_hash == TPM_ALG_NULL)
    -+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Failed to get the hash 
algorithm of the signature");
    ++    return grub_error (GRUB_ERR_BAD_ARGUMENT, "failed to get the hash 
algorithm of the signature");
     +
     +  rc = grub_tpm2_hash (NULL, (TPM2B_MAX_BUFFER_t *) &pcr_policy, sig_hash,
     +                 TPM_RH_NULL, &pcr_policy_hash, NULL, NULL);
     +  if (rc != TPM_RC_SUCCESS)
    -+    return grub_error (GRUB_ERR_BAD_DEVICE, "Failed to create PCR policy 
hash (TPM2_Hash: 0x%x)", rc);
    ++    return grub_error (GRUB_ERR_BAD_DEVICE, "failed to create PCR policy 
hash (TPM2_Hash: 0x%x)", rc);
     +
     +  /* Load the public key */
     +  rc = grub_tpm2_loadexternal (NULL, NULL, &pubkey, TPM_RH_OWNER, 
&pubkey_handle, &pubname, NULL);
     +  if (rc != TPM_RC_SUCCESS)
    -+    return grub_error (GRUB_ERR_BAD_DEVICE, "Failed to load public key 
(TPM2_LoadExternal: 0x%x)", rc);
    ++    return grub_error (GRUB_ERR_BAD_DEVICE, "failed to load public key 
(TPM2_LoadExternal: 0x%x)", rc);
     +
     +  /* Verify the signature against the public key and the policy digest */
     +  rc = grub_tpm2_verifysignature (pubkey_handle, NULL, &pcr_policy_hash, 
&signature,
     +                            &verification_ticket, NULL);
     +  if (rc != TPM_RC_SUCCESS)
     +    {
    -+      err = grub_error (GRUB_ERR_BAD_DEVICE, "Failed to verify signature 
(TPM2_VerifySignature: 0x%x)", rc);
    ++      err = grub_error (GRUB_ERR_BAD_DEVICE, "failed to verify signature 
(TPM2_VerifySignature: 0x%x)", rc);
     +      goto error;
     +    }
     +
    @@ grub-core/commands/tpm2_key_protector/module.c: tpm2_protector_policypcr 
(TPMI_S
     +                            &verification_ticket, NULL);
     +  if (rc != TPM_RC_SUCCESS)
     +    {
    -+      err = grub_error (GRUB_ERR_BAD_DEVICE, "Failed to authorize PCR 
policy (TPM2_PolicyAuthorize: 0x%x)", rc);
    ++      err = grub_error (GRUB_ERR_BAD_DEVICE, "failed to authorize PCR 
policy (TPM2_PolicyAuthorize: 0x%x)", rc);
     +      goto error;
     +    }
     +
    @@ grub-core/commands/tpm2_key_protector/module.c: 
tpm2_protector_enforce_policy (t
     +      err = tpm2_protector_policyauthorize (session, &buf);
     +      break;
          default:
    -       return grub_error (GRUB_ERR_BAD_ARGUMENT, "Unknown TPM Command: 
0x%x", policy->cmd_code);
    +       return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown TPM Command: 
0x%x", policy->cmd_code);
          }
13:  ce493c766 = 27:  760c80f9e tpm2_key_protector: Implement NV index
14:  56b8f52f3 = 28:  d230994a3 cryptodisk: Fallback to passphrase
15:  56df542cc = 29:  3a649ca7c cryptodisk: wipe out the cached keys from 
protectors
16:  69d89e3ac = 30:  dc727ed5d diskfilter: look up cryptodisk devices first
17:  686de5074 ! 31:  1e3f55837 tpm2_key_protector: Add grub-emu support
    @@ grub-core/lib/tss2/tcg2_emu.c (new)
     +#include <grub/emu/misc.h>
     +
     +#include <tss2_buffer.h>
    ++#include <tss2_structs.h>
     +#include <tcg2.h>
     +
     +grub_err_t
    @@ grub-core/lib/tss2/tcg2_emu.c (new)
     +grub_tcg2_submit_command (grub_size_t input_size, grub_uint8_t *input,
     +                    grub_size_t output_size, grub_uint8_t *output)
     +{
    -+  static const grub_size_t header_size = sizeof (grub_uint16_t) +
    -+                                   (2 * sizeof (grub_uint32_t));
    -+
     +  if (grub_util_tpm_write (input, input_size) != input_size)
     +    return GRUB_ERR_BAD_DEVICE;
     +
    -+  if (grub_util_tpm_read (output, output_size) < header_size)
    ++  if (grub_util_tpm_read (output, output_size) < sizeof 
(TPM_RESPONSE_HEADER_t))
     +    return GRUB_ERR_BAD_DEVICE;
     +
     +  return GRUB_ERR_NONE;
18:  cf6366169 = 32:  882f52384 tests: Add tpm2_key_protector_test
19:  45fdafd47 ! 33:  0f690174d docs: Document TPM2 key protector
    @@ docs/grub.texi: either @var{expression1} or @var{expression2} is true
     +
     +The key file for SRK mode can be supplied with either @option{-T} or
     +@option{-k}. The @option{-T} option is for the path to the key file in
    -+TPM 2.0 Key File. Since the parameters for the TPM commands are written in
    -+the file, there is no need to set the PCR list(@option{-p}) and
    ++TPM 2.0 Key File format. Since the parameters for the TPM commands are 
written
    ++in the file, there is no need to set the PCR list(@option{-p}) and
     +bank(@option{-b}) when using the @option{-T} option. The @option{-k} 
option
     +is for the key file in the raw format, and the @option{-p} and @option{-b}
     +options are necessary for the non-default PCR list or bank.
    @@ docs/grub.texi: either @var{expression1} or @var{expression2} is true
     +tweak the TPM Storage Root Key (SRK). The SRK can be either created at
     +runtime or stored in the non-volatile memory. When creating SRK at 
runtime,
     +GRUB provides the SRK template to TPM to create the key. There are two SRK
    -+templates, ECC and RSA, for the @option{-a} option and the default is ECC.
    ++templates for the @option{-a} option, ECC and RSA, and the default is ECC.
     +If the SRK is stored in a specific handle, e.g. @code{0x81000001}, the
     +@option{-s} option can be used to set the handle to notify GRUB to load
     +the SRK from the given handle.
     +
    -+The only nvindex-specific option is the option @option{-n} which is used 
to
    -+set the NV index containing the sealed key, so that GRUB can load the 
sealed
    ++The only NV index-specific option is the @option{-n} option which is used 
to
    ++set the NV index containing the sealed key. Then GRUB can load the sealed
     +key and unseal it with the given PCR list and bank.
     +@end deffn
     +
    @@ docs/grub.texi: be restricted and some operations/commands cannot be 
executed.
     +the disk key with a given set of PCR values. If the system state matches,
     +i.e. PCR values match the sealed PCR set, TPM2 key protector unseals the
     +disk key for @command{cryptomount} (@pxref{cryptomount}) to unlock the
    -+encrypted partition. (In case the unsealed key fails to unlock the
    -+partition, @command{cryptomount} falls back to the passphrase prompt.)
    ++encrypted partition. In case the unsealed key fails to unlock the
    ++partition, @command{cryptomount} falls back to the passphrase prompt.
     +
    -+There are two supported modes to store the sealed key, SRK and NV index,
    -+and the details will be addressed in later sections.
    ++There are two supported modes to store the sealed key, SRK and NV index.
    ++The details will be addressed in later sections.
     +
     +TPM2 key protector is currently only supported on EFI and EMU platforms.
     +
    @@ docs/grub.texi: be restricted and some operations/commands cannot be 
executed.
     +
     +Since TPM2 key protector relies on PCRs to check the system state, it is
     +important to decide which PCRs to seal the key with. The following table
    -+shows the users of PCRs and the measured objects on EFI platforms.
    ++lists uses of PCRs and the measured objects on EFI platforms.
     +
     +@multitable @columnfractions 0.1 0.2 0.7
     +@headitem PCR @tab Used by @tab Measured Objects
    @@ docs/grub.texi: be restricted and some operations/commands cannot be 
executed.
     +unseal the disk key with SRK mode and supply it to @command{cryptomount}.
     +
     +@example
    -+@kbd{tpm2_key_protector_init --keyfile=(hd0,gpt1)/efi/grub/sealed.tpm}
    -+@kbd{cryptomount -u <UUID> -P tpm2}
    ++grub> @kbd{tpm2_key_protector_init 
--keyfile=(hd0,gpt1)/efi/grub/sealed.tpm}
    ++grub> @kbd{cryptomount -u <UUID> -P tpm2}
     +@end example
     +
     +There are two programs to create the sealed key for SRK mode: 
@command{grub-protect}
     +and @command{pcr-oracle} (@url{https://github.com/okirch/pcr-oracle}).
     +
     +The following sample command uses @command{grub-protect} to seal the 
random
    -+key, @file{luks.key}, with PCR 0, 2, 4 and 7 in TPM 2.0 Key File.
    ++key, @file{luks.key}, with PCR 0, 2, 4 and 7 in TPM 2.0 Key File format.
     +
     +@example
     +@group
    @@ docs/grub.texi: be restricted and some operations/commands cannot be 
executed.
     +command.
     +
     +@example
    -+@kbd{tpm2_key_protector_init --mode=nv --nvindex=0x81000000 
--pcrs=0,2,4,7}
    -+@kbd{cryptomount -u <UUID> --protector tpm2}
    ++grub> @kbd{tpm2_key_protector_init --mode=nv --nvindex=0x81000000 
--pcrs=0,2,4,7}
    ++grub> @kbd{cryptomount -u <UUID> --protector tpm2}
     +@end example
     +
     +@subsection Setting up software TPM for EMU platform
    @@ docs/grub.texi: Print verbose messages.
     +@item --version
     +Print the version number of GRUB and exit.
     +
    -+@item -a
    ++@item -a add|remove
     +@itemx --action=add|remove
     +Add or remove a key protector to or from a key.
     +
    @@ docs/grub.texi: Print verbose messages.
     +Set the SRK handle, e.g. @samp{0x81000000}, if the SRK is to be made 
persistent.
     +
     +@item --tpm2key
    -+Use TPM 2.0 Key File instead of the raw format.
    ++Use TPM 2.0 Key File format.
     +
     +@end table
     +
    @@ docs/grub.texi: Print verbose messages.
     +Then, GRUB can unlock the target partition with the following commands:
     +
     +@example
    -+@kbd{tpm2_key_protector_init --keyfile=(hd0,gpt1)/efi/grub/sealed.tpm}
    -+@kbd{cryptomount -u <UUID> -P tpm2}
    ++grub> @kbd{tpm2_key_protector_init 
--keyfile=(hd0,gpt1)/efi/grub/sealed.tpm}
    ++grub> @kbd{cryptomount -u <UUID> -P tpm2}
     +@end example
     +
     +In most of cases, the user only needs to create the key with the `add' 
action.
    -+If auto-unlocking is unwanted, just remove the file and restore the GRUB
    -+commands.
    ++If auto-unlocking is unwanted, just remove the file and the
    ++@command{tpm2_key_protector_init} command and invoke the 
@command{cryptomount}
    ++command without @kbd{-P tpm2}.
     +
     +The only case for the `remove' action is when the SRK is made persistent.
     +
    @@ docs/grub.texi: Print verbose messages.
     +informs the TPM2 key protector to fetch the SRK from @samp{0x81000000}.
     +
     +@example
    -+@kbd{tpm2_key_protector_init -s 0x81000000 
--keyfile=(hd0,gpt1)/efi/grub/sealed.tpm}
    -+@kbd{cryptomount -u <UUID> -P tpm2}
    ++grub> @kbd{tpm2_key_protector_init -s 0x81000000 
--keyfile=(hd0,gpt1)/efi/grub/sealed.tpm}
    ++grub> @kbd{cryptomount -u <UUID> -P tpm2}
     +@end example
     +
     +After making the SRK handle persistent, we can check the status of the
    @@ docs/grub.texi: Print verbose messages.
     +@end group
     +@end example
     +
    -+In case the user doesn't want to use the TPM2 key protector anymore, 
besides
    -+removing the sealed key file, here is the command to remove the persistent
    -+
    -+The sealed key can be remove once the user does not want to use the TPM2 
key
    ++The sealed key can be removed once the user does not want to use the TPM2 
key
     +protector anymore. Here is the command to remove the persistent SRK handle
     +(@samp{0x81000000}) with @kbd{--tpm2-srk} and @kbd{--tpm2-evict}.
     +
-- 
2.43.0




reply via email to

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