aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2024-07-11 23:48:53 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2024-07-11 23:53:47 +0200
commitd745852f136bac4646e50a4f03565273e687b28b (patch)
tree89903febac5b621cd88fa3e25f314ba14dc3bd9f
parenta3c50683069c797ef328f6e32c6282d5d3243c98 (diff)
downloadbusybox-w32-d745852f136bac4646e50a4f03565273e687b28b.tar.gz
busybox-w32-d745852f136bac4646e50a4f03565273e687b28b.tar.bz2
busybox-w32-d745852f136bac4646e50a4f03565273e687b28b.zip
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>
-rw-r--r--networking/tls_sp_c32.c39
1 files changed, 29 insertions, 10 deletions
diff --git a/networking/tls_sp_c32.c b/networking/tls_sp_c32.c
index a593c5c40..9ab996f3b 100644
--- a/networking/tls_sp_c32.c
+++ b/networking/tls_sp_c32.c
@@ -425,26 +425,45 @@ static void sp_256_sub_8_p256_mod(sp_digit* r)
425#elif ALLOW_ASM && defined(__GNUC__) && defined(__x86_64__) 425#elif ALLOW_ASM && defined(__GNUC__) && defined(__x86_64__)
426static void sp_256_sub_8_p256_mod(sp_digit* r) 426static void sp_256_sub_8_p256_mod(sp_digit* r)
427{ 427{
428//p256_mod[3..0] = ffffffff00000001 0000000000000000 00000000ffffffff ffffffffffffffff
429# if 0
430 // gcc -Oz bug (?) https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115875
431 // uses buggy "push $-1; pop %rax" insns to load 00000000ffffffff
428 uint64_t reg; 432 uint64_t reg;
429 uint64_t ooff; 433 uint64_t ooff;
430//p256_mod[3..0] = ffffffff00000001 0000000000000000 00000000ffffffff ffffffffffffffff
431 asm volatile ( 434 asm volatile (
432"\n addq $1, (%0)" // adding 1 is the same as subtracting ffffffffffffffff 435"\n subq $0xffffffffffffffff, (%0)"
433"\n cmc" // only carry bit needs inverting 436"\n sbbq %1, 1*8(%0)"
434"\n"
435"\n sbbq %1, 1*8(%0)" // %1 holds 00000000ffffffff
436"\n"
437"\n sbbq $0, 2*8(%0)" 437"\n sbbq $0, 2*8(%0)"
438"\n"
439"\n movq 3*8(%0), %2" 438"\n movq 3*8(%0), %2"
440"\n sbbq $0, %2" // adding 00000000ffffffff (in %1) 439"\n sbbq $0, %2" // subtract carry
441"\n addq %1, %2" // is the same as subtracting ffffffff00000001 440"\n addq %1, %2" // adding 00000000ffffffff (in %1)
441"\n" // is the same as subtracting ffffffff00000001
442"\n movq %2, 3*8(%0)" 442"\n movq %2, 3*8(%0)"
443"\n" 443"\n"
444 : "=r" (r), "=r" (ooff), "=r" (reg) 444 : "=r" (r), "=r" (ooff), "=r" (reg)
445 : "0" (r), "1" (0x00000000ffffffff) 445 : "0" (r), "1" (0x00000000ffffffffUL) /* UL is important! */
446 : "memory"
447 );
448# else // let's do it by hand:
449 uint64_t reg;
450 uint64_t rax;
451 asm volatile (
452"\n orl $0xffffffff, %%eax" // %1 (rax) = 00000000ffffffff
453"\n subq $0xffffffffffffffff, (%0)"
454"\n sbbq %1, 1*8(%0)"
455"\n sbbq $0, 2*8(%0)"
456"\n movq 3*8(%0), %2"
457"\n sbbq $0, %2" // subtract carry
458"\n addq %1, %2" // adding 00000000ffffffff (in %1)
459"\n" // is the same as subtracting ffffffff00000001
460"\n movq %2, 3*8(%0)"
461"\n"
462 : "=r" (r), "=&a" (rax), "=r" (reg)
463 : "0" (r)
446 : "memory" 464 : "memory"
447 ); 465 );
466# endif
448} 467}
449#else 468#else
450static void sp_256_sub_8_p256_mod(sp_digit* r) 469static void sp_256_sub_8_p256_mod(sp_digit* r)