tls: P256: fix obscure x86_64 asm misbehavior, closes 15679

gcc does not necessarily clear upper bits in
64-bit regs if you ask it to load a 32-bit constant.

Cast it to unsigned long. Better yet, hand-write loading
of the constant with a smaller instruction.

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2024-07-11 23:48:53 +02:00
parent a3c5068306
commit d745852f13

View file

@ -425,26 +425,45 @@ static void sp_256_sub_8_p256_mod(sp_digit* r)
#elif ALLOW_ASM && defined(__GNUC__) && defined(__x86_64__)
static void sp_256_sub_8_p256_mod(sp_digit* r)
{
//p256_mod[3..0] = ffffffff00000001 0000000000000000 00000000ffffffff ffffffffffffffff
# if 0
// gcc -Oz bug (?) https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115875
// uses buggy "push $-1; pop %rax" insns to load 00000000ffffffff
uint64_t reg;
uint64_t ooff;
//p256_mod[3..0] = ffffffff00000001 0000000000000000 00000000ffffffff ffffffffffffffff
asm volatile (
"\n addq $1, (%0)" // adding 1 is the same as subtracting ffffffffffffffff
"\n cmc" // only carry bit needs inverting
"\n"
"\n sbbq %1, 1*8(%0)" // %1 holds 00000000ffffffff
"\n"
"\n subq $0xffffffffffffffff, (%0)"
"\n sbbq %1, 1*8(%0)"
"\n sbbq $0, 2*8(%0)"
"\n"
"\n movq 3*8(%0), %2"
"\n sbbq $0, %2" // adding 00000000ffffffff (in %1)
"\n addq %1, %2" // is the same as subtracting ffffffff00000001
"\n sbbq $0, %2" // subtract carry
"\n addq %1, %2" // adding 00000000ffffffff (in %1)
"\n" // is the same as subtracting ffffffff00000001
"\n movq %2, 3*8(%0)"
"\n"
: "=r" (r), "=r" (ooff), "=r" (reg)
: "0" (r), "1" (0x00000000ffffffff)
: "0" (r), "1" (0x00000000ffffffffUL) /* UL is important! */
: "memory"
);
# else // let's do it by hand:
uint64_t reg;
uint64_t rax;
asm volatile (
"\n orl $0xffffffff, %%eax" // %1 (rax) = 00000000ffffffff
"\n subq $0xffffffffffffffff, (%0)"
"\n sbbq %1, 1*8(%0)"
"\n sbbq $0, 2*8(%0)"
"\n movq 3*8(%0), %2"
"\n sbbq $0, %2" // subtract carry
"\n addq %1, %2" // adding 00000000ffffffff (in %1)
"\n" // is the same as subtracting ffffffff00000001
"\n movq %2, 3*8(%0)"
"\n"
: "=r" (r), "=&a" (rax), "=r" (reg)
: "0" (r)
: "memory"
);
# endif
}
#else
static void sp_256_sub_8_p256_mod(sp_digit* r)