diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2024-07-11 23:48:53 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2024-07-11 23:53:47 +0200 |
commit | d745852f136bac4646e50a4f03565273e687b28b (patch) | |
tree | 89903febac5b621cd88fa3e25f314ba14dc3bd9f | |
parent | a3c50683069c797ef328f6e32c6282d5d3243c98 (diff) | |
download | busybox-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.c | 39 |
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__) |
426 | static void sp_256_sub_8_p256_mod(sp_digit* r) | 426 | static 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 |
450 | static void sp_256_sub_8_p256_mod(sp_digit* r) | 469 | static void sp_256_sub_8_p256_mod(sp_digit* r) |