Skip to content

ppc64: regenerate SHA-256/SHA-512 crypto asm - #12009

Closed
yosuke-wolfssl wants to merge 1 commit into
wolfSSL:masterfrom
yosuke-wolfssl:fix/transform-sha
Closed

yosuke-wolfssl wants to merge 1 commit into
wolfSSL:masterfrom
yosuke-wolfssl:fix/transform-sha

Conversation

@yosuke-wolfssl

Copy link
Copy Markdown
Contributor

Summary

On ppc64le built with --enable-ppc64-asm=crypto, running on a CPU with vector crypto (POWER8+), Transform_Sha256_Len_crypto loads the message words with lxvw4x. On little-endian that instruction loads native (little-endian) words, but every caller passes the transform a big-endian byte stream, which the scalar Transform_Sha256_Len reads with lwbrx. So every SHA-224/256 digest is wrong.

Fix (wolfcrypt/src/port/ppc64/ppc64-sha256-asm.S)

The four files are regenerated from wolfSSL/scripts sha2/sha256.rb and sha2/sha512.rb (scripts PR: https://github.com/wolfSSL/scripts/pull/707). Under __LITTLE_ENDIAN__, both crypto transforms now:

  • Build a byte-reverse mask once per block: lvsl gives bytes 0..15, then XOR with 3 (SHA-256) or 7 (SHA-512).
  • vperm each message vector right after its lxvw4x/lxvd2x load.
#ifdef __LITTLE_ENDIAN__
	lvsl	9, 0, 8
	vspltisb	10, 3
	vxor	9, 9, 10
#endif /* __LITTLE_ENDIAN__ */
	lxvw4x	48, 0, 4
#ifdef __LITTLE_ENDIAN__
	vperm	16, 16, 16, 9
#endif /* __LITTLE_ENDIAN__ */

Not in this PR: wc_Sha256Transform (#11987) and wc_Sha512Transform on ppc64le are separate fixes. Adding ppc64le to the multi-arch CI is a follow-up.

Verification

  • The checked-in files match the generator output byte for byte, apart from the output path in the header comment.
  • qemu-user, testwolfcrypt:
Build CPU Before After
ppc64le --enable-ppc64-asm=crypto POWER9 SHA-256 test failed! error L=7557 pass
ppc64 BE --enable-ppc64-asm=crypto POWER8 pass pass

- ppc64-sha256-asm and ppc64-sha512-asm (.S and _c.c) byte-reverse
  each message word with vperm under __LITTLE_ENDIAN__ in the
  crypto transforms.
@yosuke-wolfssl yosuke-wolfssl self-assigned this Nov 5, 2026
Copilot AI balanced review requested due to automatic review settings November 5, 2026 01:05

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The architecture-specific cryptographic assembly requires human confirmation of PPC64 known-answer tests for standalone and inline variants, as inline execution and the inaccessible generator PR could not be independently validated.

No open issues 🎉

What changed in this PR

Regenerates wolfSSL’s PPC64 SHA-256 and SHA-512 crypto assembly to correct message byte order on little-endian POWER8+ systems, while leaving big-endian behavior unchanged.

Changes:

  • Builds byte-reversal masks and permutes loaded message vectors in both crypto transforms.
  • Applies matching changes to standalone assembly and C inline-assembly implementations.
  • Leaves the separate public Transform API fixes and PPC64LE CI coverage outside this PR.
File Description
wolfcrypt/​src/​port/​ppc64/​ppc64-sha512-asm.S Reverses bytes within loaded SHA-512 doublewords on little-endian systems.
wolfcrypt/​src/​port/​ppc64/​ppc64-sha512-asm_c.c Applies the SHA-512 correction to inline assembly.
wolfcrypt/​src/​port/​ppc64/​ppc64-sha256-asm.S Reverses bytes within loaded SHA-256 words on little-endian systems.
wolfcrypt/​src/​port/​ppc64/​ppc64-sha256-asm_c.c Applies the SHA-256 correction to inline assembly.

Review effort: Balanced

@github-actions

github-actions Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

@yosuke-wolfssl

Copy link
Copy Markdown
Contributor Author

@claude review

@wolfSSL-Fenrir-bot wolfSSL-Fenrir-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fenrir Automated Review — PR #12009

Scan targets checked: wolfcrypt-port-bugs
Not reviewed (no scan target covers them): wolfcrypt/src/port/ppc64/ppc64-sha256-asm.S, wolfcrypt/src/port/ppc64/ppc64-sha512-asm.S
Coverage: 2 of 2 in-scope changed file(s) opened by the reviewer

Fenrir result: Approved ✅

No new issues found in the changed files.

Advisory only — this automated result does not count as a GitHub approval.

Review tier: Lite

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Beyond the inline finding, I checked the new lvsl/vperm mask setup in all four files and ruled out a problem there. r8 is set by li 8, 16 before the block loop and is not changed afterward, so lvsl yields the identity 0..15 permute. In the _c.c versions, "8", "v9" and "v10" are already in both clobber lists. The .S and _c.c sequences match.

Extended reasoning...

The change adds little-endian-only byte-swap permutes to the message loads of the ppc64 SHA-256/SHA-512 hardware-crypto transforms, in both the .S and inline-asm files. I ruled out the register-usage concern raised in the change summary: the lvsl base register holds 16 (16-byte aligned), and the scratch registers are declared clobbers.

Comment on lines +3497 to +3504
#ifdef __LITTLE_ENDIAN__
lvsl 9, 0, 8
vspltisb 10, 3
vxor 9, 9, 10
#endif /* __LITTLE_ENDIAN__ */
lxvw4x 48, 0, 4
#ifdef __LITTLE_ENDIAN__
vperm 16, 16, 16, 9

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 On ppc64le POWER8+ crypto builds with OPENSSL_EXTRA, wc_Sha256Transform and wc_Sha512Transform now return wrong digests; on the base branch they are correct. The new vperm makes the crypto transforms read a big-endian byte stream. The single-block wrappers still pass little-endian native words. Fix: on PPC64 little-endian, have both wrappers give the asm a big-endian stream (byte-reverse into a temp buffer in sha256.c, and skip the ByteReverseWords64 in sha512.c), which covers the 2 sites listed. Same pattern at 2 sites (sha256.c:2616, sha512.c:2916).

Why this was flagged

wc_Sha256Transform (wolfcrypt/src/sha256.c:2616) passes the caller's block straight to Transform_Sha256 -> SHA256_TRANSFORM_LEN -> Transform_Sha256_Len_crypto (sha256.c:1350). On little-endian its contract is native 32-bit words: test_wc_Sha256Transform feeds "\x80\x63\x62\x61..." and expects SHA-256("abc"). Before this PR, lxvw4x loaded those words natively, so POWER8+ gave the right answer. After this PR the vperm at ppc64-sha256-asm.S:3504 (and its _c.c twin) byte-swaps every word, so the result is wrong. wc_Sha512Transform (sha512.c:2916) byte-reverses data with ByteReverseWords64 into native words and then calls Transform_Sha512 -> Transform_Sha512_Len_crypto (sha512.c:2928/1892). Before, lxvd2x consumed those words correctly. Now the new vperm in ppc64-sha512-asm.S reverses them a second time. The result: SHA256_Transform/SHA512_Transform (src/ssl_crypto.c:489, 629, 706, 785) and test_wc_Sha256Transform/test_wc_Sha512Transform fail on POWER8+ ppc64le. The PR description calls the wrappers a separate fix, but there the crypto path worked and this PR newly breaks it.

Verification: wc_Sha256Transform (wolfcrypt/src/sha256.c:2616) passes the caller's block as-is to Transform_Sha256_Len_crypto. On base, lxvw4x gives W0 = 0x61626380, so the result is correct. After the PR, vperm 16, 16, 16, 9 byte-swaps every word, so W0 becomes 0x80636261 and the digest is wrong. wc_Sha512Transform (sha512.c:2911-2928) regresses the same way.

@yosuke-wolfssl

Copy link
Copy Markdown
Contributor Author

It's covered by #11999

@yosuke-wolfssl
yosuke-wolfssl deleted the fix/transform-sha branch November 5, 2026 01:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants