On Wed, Aug 14, 2024 at 05:34:52PM +0200, Daniel Kiper wrote: > On Fri, Jun 28, 2024 at 04:18:43PM +0800, Gary Lin via Grub-devel wrote: > > GIT repo for v18: https://github.com/lcp/grub2/tree/tpm2-unlock-v18 > > > > This patch series is based on "Automatic TPM Disk Unlock"(*1) posted by > > Hernan Gatta to introduce the key protector framework and TPM2 stack > > to GRUB2, and this could be a useful feature for the systems to > > implement full disk encryption. > > > > To support TPM 2.0 Key File format(*2), patch 1~6,8-10 are grabbed from > > Daniel Axtens's "appended signature secure boot support" (*3) to import > > libtasn1 into grub2. Besides, the libtasn1 version is upgraded to > > 4.19.0 instead of 4.16.0 in the original patch. > > Build of this version fails in the following way: > > arm-linux-gnueabihf-gcc -DHAVE_CONFIG_H -I. -I.. -Wall -W > -DGRUB_MACHINE_EFI=1 -DGRUB_MACHINE=ARM_EFI -mword-relocations -nostdinc > -isystem /usr/lib/gcc-cross/arm-linux-gnueabihf/6/include -I../include > -I../include -DGRUB_FILE=\"commands/tpm2_key_protector/args.c\" -I. -I. -I.. > -I.. -I../include -I../include -I../grub-core/lib/libgcrypt-grub/src/ > -I./lib/tss2 -I./lib/libtasn1-grub -D_FILE_OFFSET_BITS=64 -std=gnu99 > -fno-common -Os -Wall -W -Wshadow -Wpointer-arith -Wundef -Wchar-subscripts > -Wcomment -Wdeprecated-declarations -Wdisabled-optimization -Wdiv-by-zero > -Wfloat-equal -Wformat-extra-args -Wformat-security -Wformat-y2k -Wimplicit > -Wimplicit-function-declaration -Wimplicit-int -Wmain -Wmissing-braces > -Wmissing-format-attribute -Wmultichar -Wparentheses -Wreturn-type > -Wsequence-point -Wshadow -Wsign-compare -Wswitch -Wtrigraphs > -Wunknown-pragmas -Wunused -Wunused-function -Wunused-label > -Wunused-parameter -Wunused-value -Wunused-variable -Wwrite-strings > -Wnested-externs -Wstrict-prototypes -g -Wredundant-decls > -Wmissing-prototypes -Wmissing-declarations -Wcast-align -Wextra > -Wattributes -Wendif-labels -Winit-self -Wint-to-pointer-cast -Winvalid-pch > -Wmissing-field-initializers -Wnonnull -Woverflow -Wvla -Wpointer-to-int-cast > -Wstrict-aliasing -Wvariadic-macros -Wvolatile-register-var -Wpointer-sign > -Wmissing-include-dirs -Wmissing-prototypes -Wmissing-declarations -Wformat=2 > -freg-struct-return -msoft-float -fno-omit-frame-pointer -fno-dwarf2-cfi-asm > -fno-asynchronous-unwind-tables -fno-unwind-tables -fno-ident > -mthumb-interwork -fno-PIE -fno-pie -fno-stack-protector > -mno-unaligned-access -Wtrampolines -Werror -ffreestanding -MT > commands/tpm2_key_protector/tpm2_key_protector_module-args.o -MD -MP -MF > commands/tpm2_key_protector/.deps-core/tpm2_key_protector_module-args.Tpo -c > -o commands/tpm2_key_protector/tpm2_key_protector_module-args.o `test -f > 'commands/tpm2_key_protector/args.c' || echo > './'`commands/tpm2_key_protector/args.c > In file included from ../include/grub/misc.h:27:0, > from commands/tpm2_key_protector/args.c:22: > commands/tpm2_key_protector/args.c: In function > ‘grub_tpm2_protector_parse_pcrs’: > commands/tpm2_key_protector/args.c:54:47: error: format ‘%lu’ expects > argument of type ‘long unsigned int’, but argument 3 has type ‘grub_uint64_t > {aka long long unsigned int}’ [-Werror=format=] > return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("Entry %lu in PCR list is > too large to be a PCR number, PCR numbers range from 0 to %u"), pcr, > TPM_MAX_PCRS); > ^ > ../include/grub/i18n.h:66:17: note: in definition of macro ‘N_’ > #define N_(str) str > ^~~ > commands/tpm2_key_protector/args.c: In function > ‘grub_tpm2_protector_parse_tpm_handle’: > commands/tpm2_key_protector/args.c:125:50: error: format ‘%lu’ expects > argument of type ‘long unsigned int’, but argument 3 has type ‘grub_uint64_t > {aka long long unsigned int}’ [-Werror=format=] > return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("Value %lu is too large > to be a TPM handle, TPM handles are unsigned 32-bit integers"), num); > ^ > ../include/grub/i18n.h:66:17: note: in definition of macro ‘N_’ > #define N_(str) str > ^~~ > > I think you can drop N_() macros here and use PRIuGRUB_UINT64_T instead of > "%lu". > The N_() marcors are dropped in my WIP branch per Vladimir's comment. I'll fix the type error in the next version.
> [...] > > > == > > 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 false positive. > > Here are the analyses: > > > > ________________________________________________________________________________________________________ > > *** 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: > > > > #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)" of > > 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, thus '(val) < 0 >> (7)' is always > > false. > > Besides, '(val) < 0' is false, so "(max) >> (b) < (a))" becomes the only > > valid > > statement to check if 'a' overflows after left shift. > > ... but this final statement does not explain why the CID can be ignored. > AIUI simply we do not care about second operand of "?:" in this case... > I'll updatet the statement for all CIDs in the next version. Gary Lin > > ________________________________________________________________________________________________________ > > *** 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: > > > > #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)' > > > > Since 'EXPR_SIGNED' is to test if the given expression is signed or not. For > > 'uint64_t val0', it's expected to be false, and '_GL_INT_MINIMUM' returns > > the > > minimum value of 'uint64_t' while '_GL_INT_MAXIMUM' returns the maximum > > value of 'uint64_t'. > > This explanation is missing final statement why this CID can be ignored. > Please fix this. > > > ________________________________________________________________________________________________________ > > *** 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: > > > > #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)' > > > > Since 'ris' is 'unsigned int', the compiler treats 128 as 'unsigned int' > > too. > > 'EXPR_SIGNED' is designed to check if the given expression is signed or not. > > Thus, the result is expected to be false and '_GL_INT_MINIMUM' returns the > > minimum value of 'unsigned int' while '_GL_INT_MAXIMUM' returns the maximum > > value of 'unsigned int'. > > Ditto. In general I have a feeling that your descriptions require some > rephrasing to make them clear. Same comment applies to descriptions > below... > > > ________________________________________________________________________________________________________ > > *** 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 "?:". > > [...] > > Daniel _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel