[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v22 00/33] Automatic Disk Unlock with TPM2
From: |
Gary Lin |
Subject: |
[PATCH v22 00/33] Automatic Disk Unlock with TPM2 |
Date: |
Mon, 11 Nov 2024 15:44:34 +0800 |
GIT repo for v22: https://github.com/lcp/grub2/tree/tpm2-unlock-v22
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
v22:
- Changing TPM_MAX_PCRS from 32 to 24 since most of TPM 2.0
implementations have 24 PCRs
- Fixing the PCR number check
- Fixing the types of tpm2_evict and tpm2_tpm2key in protect_args_t
- Removing SeaBIOS from the document since there is no plan to support
SeaBIOS yet
- Fixing an error message and a coding style error in grub-protect
- Updating the document
- Various typo fixes
- Addressing that the TPM2 key protector doesn't expect the password
protection for the owner hierarchy
v21:
- https://lists.gnu.org/archive/html/grub-devel/2024-11/msg00019.html
- GIT repo: https://github.com/lcp/grub2/tree/tpm2-unlock-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 | 537 +++-
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, 21856 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 v21:
-: --------- > 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
-: --------- > 15: 96d7d0998 asn1_test: enable the testcase only when
GRUB_LONG_MAX is larger than GRUB_INT_MAX
-: --------- > 16: 53ccf29c3 libtasn1: compile into asn1 module
-: --------- > 17: 6501acba8 asn1_test: test module for libtasn1
-: --------- > 18: 5fb816190 libtasn1: Add the documentation
-: --------- > 19: 1bc53f8fc key_protector: Add key protectors framework
-: --------- > 20: b1a31f22e tss2: Add TPM2 buffer handling functions
1: 7bc8ac87b ! 21: 47f0b938d tss2: Add TPM2 types and Marshal/Unmarshal
functions
@@ Commit message
functions are also added to handle the data structure to be submitted
to
TPM2 commands and to be received from the response.
- Cc: Stefan Berger <stefanb@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>
+ Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
## grub-core/lib/tss2/tss2_mu.c (new) ##
@@
@@ grub-core/lib/tss2/tss2_types.h (new)
+#define TPM_MAX_RSA_KEY_BYTES 512
+
+/* Buffer Size Constants */
-+#define TPM_MAX_PCRS 32
++#define TPM_MAX_PCRS 24
+#define TPM_NUM_PCR_BANKS 16
+#define TPM_PCR_SELECT_MAX ((TPM_MAX_PCRS + 7) / 8)
+#define TPM_MAX_DIGEST_BUFFER 1024
2: 531c8ed6a ! 22: 50a5ff62f tss2: Add TPM2 Software Stack (TSS2) support
@@ Commit message
* grub_tpm2_policyauthorize()
* grub_tpm2_testparms()
- Cc: Stefan Berger <stefanb@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>
+ Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
## grub-core/Makefile.core.def ##
@@ grub-core/Makefile.core.def: module = {
3: 7f2bf1675 ! 23: 00dcaa44f key_protector: Add TPM2 Key Protector
@@ Commit message
command set will be extended to support advanced features, such as
authorized policy, in the later commits.
- Cc: Stefan Berger <stefanb@linux.ibm.com>
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>
+ Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
## grub-core/Makefile.core.def ##
@@ grub-core/Makefile.core.def: module = {
@@ grub-core/commands/tpm2_key_protector/args.c (new)
+ if (*current_pcr == '\0' || *pcr_end != '\0')
+ 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, 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);
++ if (pcr > TPM_MAX_PCRS - 1)
++ 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 - 1);
+
+ pcrs[i] = (grub_uint8_t) pcr;
+ ++(*pcr_count);
4: 3347a97c5 = 24: b84af502c cryptodisk: Support key protectors
5: 12c7c467b ! 25: efaca9fb0 util/grub-protect: Add new tool
@@ Commit message
written in the key file, so there is no need to specify PCRs when
invoking tpm2_key_protector_init.
- Cc: Stefan Berger <stefanb@linux.ibm.com>
Signed-off-by: Hernan Gatta <hegatta@linux.microsoft.com>
Signed-off-by: Gary Lin <glin@suse.com>
+ Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
+ Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
## .gitignore ##
@@ .gitignore: widthspec.bin
@@ util/grub-protect.c (new)
+ TPM_HANDLE_t tpm2_srk;
+ const char *tpm2_keyfile;
+ const char *tpm2_outfile;
-+ int tpm2_evict;
-+ int tpm2_tpm2key;
++ bool tpm2_evict;
++ bool tpm2_tpm2key;
+} protect_args_t;
+
+static struct argp_option protect_options[] =
@@ util/grub-protect.c (new)
+ "e.g., '7,11'. Please be aware that PCR 0~7 are used by the "
+ "firmware and the measurement result may change after a "
+ "firmware update (for baremetal systems) or a package "
-+ "(OVMF/SeaBIOS/SLOF) update in the VM host. This may lead to "
++ "(OVMF/SLOF) update in the VM host. This may lead to "
+ "the failure of key unsealing. (default: 7)"),
+ .group = 0
+ },
@@ 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, N_("PCR concatenation buffer not enough.\n"));
++ fprintf (stderr, N_("PCR concatenation buffer not big enough.\n"));
+ return GRUB_ERR_OUT_OF_RANGE;
+ }
+
@@ util/grub-protect.c (new)
+ return EINVAL;
+ }
+
-+ args->tpm2_device = xstrdup(arg);
++ args->tpm2_device = xstrdup (arg);
+ args->args |= PROTECT_ARG_TPM2_DEVICE;
+ break;
+
6: 677a1b1e9 = 26: 7ef1b9b35 tpm2_key_protector: Support authorized policy
7: 760c80f9e = 27: 53e246625 tpm2_key_protector: Implement NV index
8: d230994a3 = 28: c695fb7fe cryptodisk: Fallback to passphrase
9: 3a649ca7c = 29: a2a348083 cryptodisk: wipe out the cached keys from
protectors
10: dc727ed5d = 30: 6c50cdb38 diskfilter: look up cryptodisk devices first
11: 1e3f55837 = 31: 432faf87c tpm2_key_protector: Add grub-emu support
12: 882f52384 = 32: 50d891bf7 tests: Add tpm2_key_protector_test
13: 0f690174d ! 33: 10e5ad171 docs: Document TPM2 key protector
@@ Commit message
and the user-space utility: grub-protect.
Signed-off-by: Gary Lin <glin@suse.com>
+ Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
## docs/grub.texi ##
@@ docs/grub.texi: you forget a command, you can run the command
@command{help}
@@ docs/grub.texi: either @var{expression1} or @var{expression2} is true
+bank is chosen by selecting a hash algorithm. The current supported PCR
banks
+are SHA1, SHA256, SHA384, and SHA512, and the default is SHA256.
+
-+There are some options only available for the specific mode. The
SRK-specific
++Some options are only available for the specific mode. The SRK-specific
+options are @option{-T}, @option{-k}, @option{-a}, and @option{-s}. On the
+other hand, the NV index-specific option is @option{-n}.
+
@@ docs/grub.texi: either @var{expression1} or @var{expression2} is true
+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.
++options are necessary for the non-default PCR list or bank. In general,
++TPM 2.0 Key File format is preferred due to the simplified GRUB command
++options and the authorized policy support
+
+Besides the key file, there are two options, @option{-a} and @option{-s},
to
+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
++GRUB provides the SRK template to the TPM to create the key. There are
two SRK
+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
@@ docs/grub.texi: be restricted and some operations/commands cannot be
executed.
+encrypted partition. In case the unsealed key fails to unlock the
+partition, @command{cryptomount} falls back to the passphrase prompt.
+
++Please note that TPM2 key protector uses the SRK in the owner hierarchy
++@emph{without} authorization. If the owner hierarchy is
password-protected,
++TPM2 key protector may fail to unseal the key due to the absence of the
++password. For the systems that already enable the password protection for
the
++owner hierarchy, the following command removes the password protection
with
++the existing password stored in @file{passfile}.
++
++@example
++# @kbd{tpm2_changeauth -c owner -p passfile}
++@end example
++
+There are two supported modes to store the sealed key, SRK and NV index.
+The details will be addressed in later sections.
+
@@ 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
-+grub> @kbd{tpm2_key_protector_init
--keyfile=(hd0,gpt1)/efi/grub/sealed.tpm}
++grub> @kbd{tpm2_key_protector_init -T (hd0,gpt1)/efi/grub/sealed.tpm}
+grub> @kbd{cryptomount -u <UUID> -P tpm2}
+@end example
+
@@ docs/grub.texi: be restricted and some operations/commands cannot be
executed.
+
+@command{grub-protect} only seals the key with the current PCR values.
+Therefore, when a boot component, such as shim or GRUB, is updated, it is
-+neccessary to reboot the system to update the measurement results and seal
++necessary to reboot the system to update the measurement results and seal
+the key again. That means the random disk key has to be stored in
cleartext
+for the next key sealing. Besides this, the measurement result of some
PCRs
+may differ between boot time and OS runtime. For example, PCR 9 measures
the
@@ docs/grub.texi: be restricted and some operations/commands cannot be
executed.
+PCR policy to be updated with a valid signature, so that the user only
seals
+the random disk key once. If at some later time the PCR values change due
to
+an update of the system firmware, bootloader, or config file, the user
just
-+needs to update the signature of PCR policy.
++needs to update the signature of the PCR policy.
+
+To seal the key with the authorized policy, the first thing is to generate
+the RSA policy key, @file{policy-key.pem}, and the authorized policy file,
@@ docs/grub.texi: be restricted and some operations/commands cannot be
executed.
+@end example
+
+Since we now have the sealed key, we can remove the random disk key file
-+@file{lukes.key}.
++@file{luks.key}.
+
+The last step is to sign the predicted PCR policy and save the final key
+file, @file{sealed.tpm}.
@@ docs/grub.texi: be restricted and some operations/commands cannot be
executed.
+@kbd{--stop-event grub-file=grub.cfg --after}, @command{pcr-oracle} stops
+the calculation of PCR values right after GRUB loads @file{grub.cfg}.
+
-+When shim or GRUB updates, it only requires to run the last
@command{pcr-oracle}
-+command to update the predicted PCR policy.
++When/After the shim or GRUB are updated, it only requires to run the last
++@command{pcr-oracle} command to update the predicted PCR policy.
+
+@subsection NV index mode
+
@@ docs/grub.texi: be restricted and some operations/commands cannot be
executed.
+# @kbd{tpm2_evictcontrol -C o -c sealing.ctx 0x81000000}
+@end example
+
-+To unseal the key, we have to specify the mode, @kbd{nv}, the NV index,
-+@kbd{0x81000000}, and the PCRs, @kbd{0,2,4,7} for
@command{tpm2_key_protector_init}
++To unseal the key, we have to specify the mode @kbd{nv}, the NV index
++@kbd{0x81000000}, and the PCRs @kbd{0,2,4,7} for the
@command{tpm2_key_protector_init}
+command.
+
+@example
@@ docs/grub.texi: be restricted and some operations/commands cannot be
executed.
+@subsection Setting up software TPM for EMU platform
+
+In order to test TPM2 key protector and TPM2 Software Stack (TSS2), it is
-+handy to set up a software TPM (swtpm) instance and run the commands on
the
++useful to set up a software TPM (swtpm) instance and run the commands on
the
+EMU platform.
+
+Here are the commands to start a swtpm instance which provides a character
@@ docs/grub.texi: Print verbose messages.
+@itemx --action=add|remove
+Add or remove a key protector to or from a key.
+
-+@item -p
++@item -p @var{protector}
+@itemx --protector=@var{protector}
+Set the key protector. Currently, @samp{tpm2} is the only supported key
+protector.
@@ docs/grub.texi: Print verbose messages.
+Set a comma-separated list of PCRs used to authorize key release e.g.,
@samp{7,11}.
+Please be aware that PCR 0~7 are used by the firmware and the measurement
result
+may change after a firmware update (for baremetal systems) or a package
-+(OVMF/SeaBIOS/SLOF) update in the VM host. This may lead to the failure
of key
++(OVMF/SLOF) update in the VM host. This may lead to the failure of key
+unsealing. (default: @samp{7})
+
+@item --tpm2-srk=@var{handle}
@@ docs/grub.texi: Print verbose messages.
+Then, GRUB can unlock the target partition with the following commands:
+
+@example
-+grub> @kbd{tpm2_key_protector_init
--keyfile=(hd0,gpt1)/efi/grub/sealed.tpm}
++grub> @kbd{tpm2_key_protector_init -T (hd0,gpt1)/efi/grub/sealed.tpm}
+grub> @kbd{cryptomount -u <UUID> -P tpm2}
+@end example
+
@@ docs/grub.texi: Print verbose messages.
+@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.
++The only use case for the `remove' action is when the SRK is made
persistent.
+
+There are two supported SRKs in @command{grub-protect}: @samp{RSA} and
@samp{ECC}.
-+Due to slower key generation, some users of the @samp{RSA} SRK would
prefer
++Due to slower key generation, some users of the @samp{RSA} SRK may prefer
+making it persistent so that the TPM can skip the SRK generation when
GRUB tries
+to unseal the key.
+
@@ docs/grub.texi: Print verbose messages.
+informs the TPM2 key protector to fetch the SRK from @samp{0x81000000}.
+
+@example
-+grub> @kbd{tpm2_key_protector_init -s 0x81000000
--keyfile=(hd0,gpt1)/efi/grub/sealed.tpm}
++grub> @kbd{tpm2_key_protector_init -s 0x81000000 -T
(hd0,gpt1)/efi/grub/sealed.tpm}
+grub> @kbd{cryptomount -u <UUID> -P tpm2}
+@end example
+
--
2.43.0
- [PATCH v22 00/33] Automatic Disk Unlock with TPM2,
Gary Lin <=
- [PATCH v22 01/33] posix_wrap: tweaks in preparation for libtasn1, Gary Lin, 2024/11/11
- [PATCH v22 02/33] libtasn1: import libtasn1-4.19.0, Gary Lin, 2024/11/11
- [PATCH v22 03/33] libtasn1: disable code not needed in grub, Gary Lin, 2024/11/11
- [PATCH v22 07/33] libtasn1: Use grub_divmod64() for division, Gary Lin, 2024/11/11
- [PATCH v22 10/33] asn1_test: rename the main functions to the test names, Gary Lin, 2024/11/11
- [PATCH v22 04/33] libtasn1: replace strcat() with strcpy() in _asn1_str_cat(), Gary Lin, 2024/11/11
- [PATCH v22 05/33] libtasn1: replace strcat() with _asn1_str_cat(), Gary Lin, 2024/11/11
- [PATCH v22 08/33] libtasn1: fix the potential buffer overrun, Gary Lin, 2024/11/11
- [PATCH v22 11/33] asn1_test: return either 0 or 1 to reflect the results, Gary Lin, 2024/11/11
- [PATCH v22 06/33] libtasn1: adjust the header paths in libtasn1.h, Gary Lin, 2024/11/11