diff options
| author | Igor Pavlov <87184205+ip7z@users.noreply.github.com> | 2025-07-05 00:00:00 +0000 |
|---|---|---|
| committer | Igor Pavlov <87184205+ip7z@users.noreply.github.com> | 2025-07-05 19:27:33 +0500 |
| commit | 395149956d696e6e3099d8b76d797437f94a6942 (patch) | |
| tree | 6ed5013a637078ae2dfdc4acf1ad93bf29cea356 /C/Sha512.c | |
| parent | e5431fa6f5505e385c6f9367260717e9c47dc2ee (diff) | |
| download | 7zip-25.00.tar.gz 7zip-25.00.tar.bz2 7zip-25.00.zip | |
25.0025.00
Diffstat (limited to 'C/Sha512.c')
| -rw-r--r-- | C/Sha512.c | 167 |
1 files changed, 130 insertions, 37 deletions
| @@ -439,26 +439,78 @@ void Sha512_Final(CSha512 *p, Byte *digest, unsigned digestSize) | |||
| 439 | 439 | ||
| 440 | 440 | ||
| 441 | 441 | ||
| 442 | // #define Z7_SHA512_PROBE_DEBUG // for debug | ||
| 442 | 443 | ||
| 443 | #if defined(_WIN32) && defined(Z7_COMPILER_SHA512_SUPPORTED) \ | 444 | #if defined(Z7_SHA512_PROBE_DEBUG) || defined(Z7_COMPILER_SHA512_SUPPORTED) |
| 444 | && defined(MY_CPU_ARM64) // we can disable this check to debug in x64 | ||
| 445 | 445 | ||
| 446 | #if 1 // 0 for debug | 446 | #if defined(Z7_SHA512_PROBE_DEBUG) \ |
| 447 | || defined(_WIN32) && defined(MY_CPU_ARM64) | ||
| 448 | #ifndef Z7_SHA512_USE_PROBE | ||
| 449 | #define Z7_SHA512_USE_PROBE | ||
| 450 | #endif | ||
| 451 | #endif | ||
| 447 | 452 | ||
| 448 | #include "7zWindows.h" | 453 | #ifdef Z7_SHA512_USE_PROBE |
| 449 | // #include <stdio.h> | 454 | |
| 450 | #if 0 && defined(MY_CPU_X86_OR_AMD64) | 455 | #ifdef Z7_SHA512_PROBE_DEBUG |
| 451 | #include <intrin.h> // for debug : for __ud2() | 456 | #include <stdio.h> |
| 457 | #define PRF(x) x | ||
| 458 | #else | ||
| 459 | #define PRF(x) | ||
| 452 | #endif | 460 | #endif |
| 453 | 461 | ||
| 454 | BoolInt CPU_IsSupported_SHA512(void) | 462 | #if 0 || !defined(_MSC_VER) // 1 || : for debug LONGJMP mode |
| 463 | // MINGW doesn't support __try. So we use signal() / longjmp(). | ||
| 464 | // Note: signal() / longjmp() probably is not thread-safe. | ||
| 465 | // So we must call Sha512Prepare() from main thread at program start. | ||
| 466 | #ifndef Z7_SHA512_USE_LONGJMP | ||
| 467 | #define Z7_SHA512_USE_LONGJMP | ||
| 468 | #endif | ||
| 469 | #endif | ||
| 470 | |||
| 471 | #ifdef Z7_SHA512_USE_LONGJMP | ||
| 472 | #include <signal.h> | ||
| 473 | #include <setjmp.h> | ||
| 474 | static jmp_buf g_Sha512_jmp_buf; | ||
| 475 | // static int g_Sha512_Unsupported; | ||
| 476 | |||
| 477 | #if defined(__GNUC__) && (__GNUC__ >= 8) \ | ||
| 478 | || defined(__clang__) && (__clang_major__ >= 3) | ||
| 479 | __attribute__((noreturn)) | ||
| 480 | #endif | ||
| 481 | static void Z7_CDECL Sha512_signal_Handler(int v) | ||
| 455 | { | 482 | { |
| 483 | PRF(printf("======== Sha512_signal_Handler = %x\n", (unsigned)v);) | ||
| 484 | // g_Sha512_Unsupported = 1; | ||
| 485 | longjmp(g_Sha512_jmp_buf, 1); | ||
| 486 | } | ||
| 487 | #endif // Z7_SHA512_USE_LONGJMP | ||
| 488 | |||
| 489 | |||
| 490 | #if defined(_WIN32) | ||
| 491 | #include "7zWindows.h" | ||
| 492 | #endif | ||
| 493 | |||
| 456 | #if defined(MY_CPU_ARM64) | 494 | #if defined(MY_CPU_ARM64) |
| 495 | // #define Z7_SHA512_USE_SIMPLIFIED_PROBE // for debug | ||
| 496 | #endif | ||
| 497 | |||
| 498 | #ifdef Z7_SHA512_USE_SIMPLIFIED_PROBE | ||
| 499 | #include <arm_neon.h> | ||
| 500 | #if defined(__clang__) | ||
| 501 | __attribute__((__target__("sha3"))) | ||
| 502 | #elif !defined(_MSC_VER) | ||
| 503 | __attribute__((__target__("arch=armv8.2-a+sha3"))) | ||
| 504 | #endif | ||
| 505 | #endif | ||
| 506 | static BoolInt CPU_IsSupported_SHA512_Probe(void) | ||
| 507 | { | ||
| 508 | PRF(printf("\n== CPU_IsSupported_SHA512_Probe\n");) | ||
| 509 | #if defined(_WIN32) && defined(MY_CPU_ARM64) | ||
| 457 | // we have no SHA512 flag for IsProcessorFeaturePresent() still. | 510 | // we have no SHA512 flag for IsProcessorFeaturePresent() still. |
| 458 | if (!CPU_IsSupported_CRYPTO()) | 511 | if (!CPU_IsSupported_CRYPTO()) |
| 459 | return False; | 512 | return False; |
| 460 | #endif | 513 | PRF(printf("==== Registry check\n");) |
| 461 | // printf("\nCPU_IsSupported_SHA512\n"); | ||
| 462 | { | 514 | { |
| 463 | // we can't read ID_AA64ISAR0_EL1 register from application. | 515 | // we can't read ID_AA64ISAR0_EL1 register from application. |
| 464 | // but ID_AA64ISAR0_EL1 register is mapped to "CP 4030" registry value. | 516 | // but ID_AA64ISAR0_EL1 register is mapped to "CP 4030" registry value. |
| @@ -486,6 +538,7 @@ BoolInt CPU_IsSupported_SHA512(void) | |||
| 486 | // 2 : SHA256 and SHA512 implemented | 538 | // 2 : SHA256 and SHA512 implemented |
| 487 | } | 539 | } |
| 488 | } | 540 | } |
| 541 | #endif // defined(_WIN32) && defined(MY_CPU_ARM64) | ||
| 489 | 542 | ||
| 490 | 543 | ||
| 491 | #if 1 // 0 for debug to disable SHA512 PROBE code | 544 | #if 1 // 0 for debug to disable SHA512 PROBE code |
| @@ -509,59 +562,97 @@ Does this PROBE code work in native Windows-arm64 (with/without sha512 hw instru | |||
| 509 | Are there any ways to fix the problems with arm64-wine and x64-SDE cases? | 562 | Are there any ways to fix the problems with arm64-wine and x64-SDE cases? |
| 510 | */ | 563 | */ |
| 511 | 564 | ||
| 512 | // printf("\n========== CPU_IsSupported_SHA512 PROBE ========\n"); | 565 | PRF(printf("==== CPU_IsSupported_SHA512 PROBE\n");) |
| 513 | { | 566 | { |
| 567 | BoolInt isSupported = False; | ||
| 568 | #ifdef Z7_SHA512_USE_LONGJMP | ||
| 569 | void (Z7_CDECL *signal_prev)(int); | ||
| 570 | /* | ||
| 571 | if (g_Sha512_Unsupported) | ||
| 572 | { | ||
| 573 | PRF(printf("==== g_Sha512_Unsupported\n");) | ||
| 574 | return False; | ||
| 575 | } | ||
| 576 | */ | ||
| 577 | printf("====== signal(SIGILL)\n"); | ||
| 578 | signal_prev = signal(SIGILL, Sha512_signal_Handler); | ||
| 579 | if (signal_prev == SIG_ERR) | ||
| 580 | { | ||
| 581 | PRF(printf("====== signal fail\n");) | ||
| 582 | return False; | ||
| 583 | } | ||
| 584 | // PRF(printf("==== signal_prev = %p\n", (void *)signal_prev);) | ||
| 585 | // docs: Before the specified function is executed, | ||
| 586 | // the value of func is set to SIG_DFL. | ||
| 587 | // So we can exit if (setjmp(g_Sha512_jmp_buf) != 0). | ||
| 588 | PRF(printf("====== setjmp\n");) | ||
| 589 | if (!setjmp(g_Sha512_jmp_buf)) | ||
| 590 | #else // Z7_SHA512_USE_LONGJMP | ||
| 591 | |||
| 592 | #ifdef _MSC_VER | ||
| 514 | #ifdef __clang_major__ | 593 | #ifdef __clang_major__ |
| 515 | #pragma GCC diagnostic ignored "-Wlanguage-extension-token" | 594 | #pragma GCC diagnostic ignored "-Wlanguage-extension-token" |
| 516 | #endif | 595 | #endif |
| 517 | __try | 596 | __try |
| 597 | #endif | ||
| 598 | #endif // Z7_SHA512_USE_LONGJMP | ||
| 599 | |||
| 518 | { | 600 | { |
| 519 | #if 0 // 1 : for debug (reduced version to detect sha512) | 601 | #if defined(Z7_COMPILER_SHA512_SUPPORTED) |
| 602 | #ifdef Z7_SHA512_USE_SIMPLIFIED_PROBE | ||
| 603 | // simplified sha512 check for arm64: | ||
| 520 | const uint64x2_t a = vdupq_n_u64(1); | 604 | const uint64x2_t a = vdupq_n_u64(1); |
| 521 | const uint64x2_t b = vsha512hq_u64(a, a, a); | 605 | const uint64x2_t b = vsha512hq_u64(a, a, a); |
| 606 | PRF(printf("======== vsha512hq_u64 probe\n");) | ||
| 522 | if ((UInt32)vgetq_lane_u64(b, 0) == 0x11800002) | 607 | if ((UInt32)vgetq_lane_u64(b, 0) == 0x11800002) |
| 523 | return True; | ||
| 524 | #else | 608 | #else |
| 525 | MY_ALIGN(16) | 609 | MY_ALIGN(16) |
| 526 | UInt64 temp[SHA512_NUM_DIGEST_WORDS + SHA512_NUM_BLOCK_WORDS]; | 610 | UInt64 temp[SHA512_NUM_DIGEST_WORDS + SHA512_NUM_BLOCK_WORDS]; |
| 527 | memset(temp, 0x5a, sizeof(temp)); | 611 | memset(temp, 0x5a, sizeof(temp)); |
| 528 | #if 0 && defined(MY_CPU_X86_OR_AMD64) | 612 | PRF(printf("======== Sha512_UpdateBlocks_HW\n");) |
| 529 | __ud2(); // for debug : that exception is not problem for SDE | ||
| 530 | #endif | ||
| 531 | #if 1 | ||
| 532 | Sha512_UpdateBlocks_HW(temp, | 613 | Sha512_UpdateBlocks_HW(temp, |
| 533 | (const Byte *)(const void *)(temp + SHA512_NUM_DIGEST_WORDS), 1); | 614 | (const Byte *)(const void *)(temp + SHA512_NUM_DIGEST_WORDS), 1); |
| 534 | // printf("\n==== t = %x\n", (UInt32)temp[0]); | 615 | // PRF(printf("======== t = %x\n", (UInt32)temp[0]);) |
| 535 | if ((UInt32)temp[0] == 0xa33cfdf7) | 616 | if ((UInt32)temp[0] == 0xa33cfdf7) |
| 617 | #endif | ||
| 536 | { | 618 | { |
| 537 | // printf("\n=== PROBE SHA512: SHA512 supported\n"); | 619 | PRF(printf("======== PROBE SHA512: SHA512 is supported\n");) |
| 538 | return True; | 620 | isSupported = True; |
| 539 | } | 621 | } |
| 622 | #else // Z7_COMPILER_SHA512_SUPPORTED | ||
| 623 | // for debug : we generate bad instrction or raise exception. | ||
| 624 | // __except() doesn't catch raise() calls. | ||
| 625 | #ifdef Z7_SHA512_USE_LONGJMP | ||
| 626 | PRF(printf("====== raise(SIGILL)\n");) | ||
| 627 | raise(SIGILL); | ||
| 628 | #else | ||
| 629 | #if defined(_MSC_VER) && defined(MY_CPU_X86) | ||
| 630 | __asm ud2 | ||
| 540 | #endif | 631 | #endif |
| 541 | #endif | 632 | #endif // Z7_SHA512_USE_LONGJMP |
| 633 | #endif // Z7_COMPILER_SHA512_SUPPORTED | ||
| 542 | } | 634 | } |
| 635 | |||
| 636 | #ifdef Z7_SHA512_USE_LONGJMP | ||
| 637 | PRF(printf("====== restore signal SIGILL\n");) | ||
| 638 | signal(SIGILL, signal_prev); | ||
| 639 | #elif _MSC_VER | ||
| 543 | __except (EXCEPTION_EXECUTE_HANDLER) | 640 | __except (EXCEPTION_EXECUTE_HANDLER) |
| 544 | { | 641 | { |
| 545 | // printf("\n==== CPU_IsSupported_SHA512 EXCEPTION_EXECUTE_HANDLER\n"); | 642 | PRF(printf("==== CPU_IsSupported_SHA512 __except(EXCEPTION_EXECUTE_HANDLER)\n");) |
| 546 | } | 643 | } |
| 644 | #endif | ||
| 645 | PRF(printf("== return (sha512 supported) = %d\n", isSupported);) | ||
| 646 | return isSupported; | ||
| 547 | } | 647 | } |
| 548 | return False; | ||
| 549 | #else | 648 | #else |
| 550 | // without SHA512 PROBE code | 649 | // without SHA512 PROBE code |
| 551 | return True; | 650 | return True; |
| 552 | #endif | 651 | #endif |
| 553 | |||
| 554 | } | 652 | } |
| 555 | 653 | ||
| 556 | #else | 654 | #endif // Z7_SHA512_USE_PROBE |
| 557 | 655 | #endif // defined(Z7_SHA512_PROBE_DEBUG) || defined(Z7_COMPILER_SHA512_SUPPORTED) | |
| 558 | BoolInt CPU_IsSupported_SHA512(void) | ||
| 559 | { | ||
| 560 | return False; | ||
| 561 | } | ||
| 562 | |||
| 563 | #endif | ||
| 564 | #endif // WIN32 arm64 | ||
| 565 | 656 | ||
| 566 | 657 | ||
| 567 | void Sha512Prepare(void) | 658 | void Sha512Prepare(void) |
| @@ -570,10 +661,10 @@ void Sha512Prepare(void) | |||
| 570 | SHA512_FUNC_UPDATE_BLOCKS f, f_hw; | 661 | SHA512_FUNC_UPDATE_BLOCKS f, f_hw; |
| 571 | f = Sha512_UpdateBlocks; | 662 | f = Sha512_UpdateBlocks; |
| 572 | f_hw = NULL; | 663 | f_hw = NULL; |
| 573 | #ifdef MY_CPU_X86_OR_AMD64 | 664 | #ifdef Z7_SHA512_USE_PROBE |
| 574 | if (CPU_IsSupported_SHA512() | 665 | if (CPU_IsSupported_SHA512_Probe()) |
| 575 | && CPU_IsSupported_AVX2() | 666 | #elif defined(MY_CPU_X86_OR_AMD64) |
| 576 | ) | 667 | if (CPU_IsSupported_SHA512() && CPU_IsSupported_AVX2()) |
| 577 | #else | 668 | #else |
| 578 | if (CPU_IsSupported_SHA512()) | 669 | if (CPU_IsSupported_SHA512()) |
| 579 | #endif | 670 | #endif |
| @@ -583,6 +674,8 @@ void Sha512Prepare(void) | |||
| 583 | } | 674 | } |
| 584 | g_SHA512_FUNC_UPDATE_BLOCKS = f; | 675 | g_SHA512_FUNC_UPDATE_BLOCKS = f; |
| 585 | g_SHA512_FUNC_UPDATE_BLOCKS_HW = f_hw; | 676 | g_SHA512_FUNC_UPDATE_BLOCKS_HW = f_hw; |
| 677 | #elif defined(Z7_SHA512_PROBE_DEBUG) | ||
| 678 | CPU_IsSupported_SHA512_Probe(); // for debug | ||
| 586 | #endif | 679 | #endif |
| 587 | } | 680 | } |
| 588 | 681 | ||
