From ed89abfb6ed9c7a57f5781080cf78eec895c1006 Mon Sep 17 00:00:00 2001 From: Dakoda Greaves Date: Tue, 23 Apr 2024 14:33:37 -0700 Subject: [PATCH] crypto: add multiblock support for armv8/armv82 sha256 --- src/crypto/sha256.cpp | 283 +++++++++++++++++++++--------------------- 1 file changed, 142 insertions(+), 141 deletions(-) diff --git a/src/crypto/sha256.cpp b/src/crypto/sha256.cpp index 60a79262c08..eea4ddf7d50 100644 --- a/src/crypto/sha256.cpp +++ b/src/crypto/sha256.cpp @@ -93,7 +93,6 @@ void inline Initialize(uint32_t* s) /** Perform one SHA-256 transformation, processing a 64-byte chunk. (ARMv8) */ void Transform_ARMV8(uint32_t* s, const unsigned char* chunk, size_t blocks) { - (void)blocks; #if defined(USE_ARMV8) || defined(USE_ARMV82) // entire block is experimental EXPERIMENTAL_FEATURE @@ -106,147 +105,149 @@ void Transform_ARMV8(uint32_t* s, const unsigned char* chunk, size_t blocks) STATE0 = vld1q_u32(&s[0]); STATE1 = vld1q_u32(&s[4]); - /** Save state */ - ABEF_SAVE = STATE0; - CDGH_SAVE = STATE1; - - /** Load message */ - MSG0 = vld1q_u32((const uint32_t *)(chunk + 0)); - MSG1 = vld1q_u32((const uint32_t *)(chunk + 16)); - MSG2 = vld1q_u32((const uint32_t *)(chunk + 32)); - MSG3 = vld1q_u32((const uint32_t *)(chunk + 48)); - - /** Reverse for little endian */ - MSG0 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(MSG0))); - MSG1 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(MSG1))); - MSG2 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(MSG2))); - MSG3 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(MSG3))); - - TMP0 = vaddq_u32(MSG0, vld1q_u32(&K[0x00])); - - /** Rounds 0-3 */ - MSG0 = vsha256su0q_u32(MSG0, MSG1); - TMP2 = STATE0; - TMP1 = vaddq_u32(MSG1, vld1q_u32(&K[0x04])); - STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0); - STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0); - MSG0 = vsha256su1q_u32(MSG0, MSG2, MSG3); - - /** Rounds 4-7 */ - MSG1 = vsha256su0q_u32(MSG1, MSG2); - TMP2 = STATE0; - TMP0 = vaddq_u32(MSG2, vld1q_u32(&K[0x08])); - STATE0 = vsha256hq_u32(STATE0, STATE1, TMP1); - STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP1); - MSG1 = vsha256su1q_u32(MSG1, MSG3, MSG0); - - /** Rounds 8-11 */ - MSG2 = vsha256su0q_u32(MSG2, MSG3); - TMP2 = STATE0; - TMP1 = vaddq_u32(MSG3, vld1q_u32(&K[0x0c])); - STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0); - STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0); - MSG2 = vsha256su1q_u32(MSG2, MSG0, MSG1); - - /** Rounds 12-15 */ - MSG3 = vsha256su0q_u32(MSG3, MSG0); - TMP2 = STATE0; - TMP0 = vaddq_u32(MSG0, vld1q_u32(&K[0x10])); - STATE0 = vsha256hq_u32(STATE0, STATE1, TMP1); - STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP1); - MSG3 = vsha256su1q_u32(MSG3, MSG1, MSG2); - - /** Rounds 16-19 */ - MSG0 = vsha256su0q_u32(MSG0, MSG1); - TMP2 = STATE0; - TMP1 = vaddq_u32(MSG1, vld1q_u32(&K[0x14])); - STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0); - STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0); - MSG0 = vsha256su1q_u32(MSG0, MSG2, MSG3); - - /** Rounds 20-23 */ - MSG1 = vsha256su0q_u32(MSG1, MSG2); - TMP2 = STATE0; - TMP0 = vaddq_u32(MSG2, vld1q_u32(&K[0x18])); - STATE0 = vsha256hq_u32(STATE0, STATE1, TMP1); - STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP1); - MSG1 = vsha256su1q_u32(MSG1, MSG3, MSG0); - - /** Rounds 24-27 */ - MSG2 = vsha256su0q_u32(MSG2, MSG3); - TMP2 = STATE0; - TMP1 = vaddq_u32(MSG3, vld1q_u32(&K[0x1c])); - STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0); - STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0); - MSG2 = vsha256su1q_u32(MSG2, MSG0, MSG1); - - /** Rounds 28-31 */ - MSG3 = vsha256su0q_u32(MSG3, MSG0); - TMP2 = STATE0; - TMP0 = vaddq_u32(MSG0, vld1q_u32(&K[0x20])); - STATE0 = vsha256hq_u32(STATE0, STATE1, TMP1); - STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP1); - MSG3 = vsha256su1q_u32(MSG3, MSG1, MSG2); - - /** Rounds 32-35 */ - MSG0 = vsha256su0q_u32(MSG0, MSG1); - TMP2 = STATE0; - TMP1 = vaddq_u32(MSG1, vld1q_u32(&K[0x24])); - STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0); - STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0); - MSG0 = vsha256su1q_u32(MSG0, MSG2, MSG3); - - /** Rounds 36-39 */ - MSG1 = vsha256su0q_u32(MSG1, MSG2); - TMP2 = STATE0; - TMP0 = vaddq_u32(MSG2, vld1q_u32(&K[0x28])); - STATE0 = vsha256hq_u32(STATE0, STATE1, TMP1); - STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP1); - MSG1 = vsha256su1q_u32(MSG1, MSG3, MSG0); - - /** Rounds 40-43 */ - MSG2 = vsha256su0q_u32(MSG2, MSG3); - TMP2 = STATE0; - TMP1 = vaddq_u32(MSG3, vld1q_u32(&K[0x2c])); - STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0); - STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0); - MSG2 = vsha256su1q_u32(MSG2, MSG0, MSG1); - - /** Rounds 44-47 */ - MSG3 = vsha256su0q_u32(MSG3, MSG0); - TMP2 = STATE0; - TMP0 = vaddq_u32(MSG0, vld1q_u32(&K[0x30])); - STATE0 = vsha256hq_u32(STATE0, STATE1, TMP1); - STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP1); - MSG3 = vsha256su1q_u32(MSG3, MSG1, MSG2); - - /** Rounds 48-51 */ - TMP2 = STATE0; - TMP1 = vaddq_u32(MSG1, vld1q_u32(&K[0x34])); - STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0); - STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0); - - /** Rounds 52-55 */ - TMP2 = STATE0; - TMP0 = vaddq_u32(MSG2, vld1q_u32(&K[0x38])); - STATE0 = vsha256hq_u32(STATE0, STATE1, TMP1); - STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP1); - - /** Rounds 56-59 */ - TMP2 = STATE0; - TMP1 = vaddq_u32(MSG3, vld1q_u32(&K[0x3c])); - STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0); - STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0); - - /** Rounds 60-63 */ - TMP2 = STATE0; - STATE0 = vsha256hq_u32(STATE0, STATE1, TMP1); - STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP1); - - /** Combine state */ - STATE0 = vaddq_u32(STATE0, ABEF_SAVE); - STATE1 = vaddq_u32(STATE1, CDGH_SAVE); + while (blocks--) { + /** Save state */ + ABEF_SAVE = STATE0; + CDGH_SAVE = STATE1; + + /** Load message */ + MSG0 = vld1q_u32((const uint32_t *)(chunk + 0)); + MSG1 = vld1q_u32((const uint32_t *)(chunk + 16)); + MSG2 = vld1q_u32((const uint32_t *)(chunk + 32)); + MSG3 = vld1q_u32((const uint32_t *)(chunk + 48)); + + /** Reverse for little endian */ + MSG0 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(MSG0))); + MSG1 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(MSG1))); + MSG2 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(MSG2))); + MSG3 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(MSG3))); + chunk += 64; + TMP0 = vaddq_u32(MSG0, vld1q_u32(&K[0x00])); // consider commenting out or removing + + /** Rounds 0-3 */ + MSG0 = vsha256su0q_u32(MSG0, MSG1); + TMP2 = STATE0; + TMP1 = vaddq_u32(MSG1, vld1q_u32(&K[0x04])); + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0); + MSG0 = vsha256su1q_u32(MSG0, MSG2, MSG3); + + /** Rounds 4-7 */ + MSG1 = vsha256su0q_u32(MSG1, MSG2); + TMP2 = STATE0; + TMP0 = vaddq_u32(MSG2, vld1q_u32(&K[0x08])); + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP1); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP1); + MSG1 = vsha256su1q_u32(MSG1, MSG3, MSG0); + + /** Rounds 8-11 */ + MSG2 = vsha256su0q_u32(MSG2, MSG3); + TMP2 = STATE0; + TMP1 = vaddq_u32(MSG3, vld1q_u32(&K[0x0c])); + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0); + MSG2 = vsha256su1q_u32(MSG2, MSG0, MSG1); + + /** Rounds 12-15 */ + MSG3 = vsha256su0q_u32(MSG3, MSG0); + TMP2 = STATE0; + TMP0 = vaddq_u32(MSG0, vld1q_u32(&K[0x10])); + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP1); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP1); + MSG3 = vsha256su1q_u32(MSG3, MSG1, MSG2); + + /** Rounds 16-19 */ + MSG0 = vsha256su0q_u32(MSG0, MSG1); + TMP2 = STATE0; + TMP1 = vaddq_u32(MSG1, vld1q_u32(&K[0x14])); + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0); + MSG0 = vsha256su1q_u32(MSG0, MSG2, MSG3); + + /** Rounds 20-23 */ + MSG1 = vsha256su0q_u32(MSG1, MSG2); + TMP2 = STATE0; + TMP0 = vaddq_u32(MSG2, vld1q_u32(&K[0x18])); + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP1); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP1); + MSG1 = vsha256su1q_u32(MSG1, MSG3, MSG0); + + /** Rounds 24-27 */ + MSG2 = vsha256su0q_u32(MSG2, MSG3); + TMP2 = STATE0; + TMP1 = vaddq_u32(MSG3, vld1q_u32(&K[0x1c])); + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0); + MSG2 = vsha256su1q_u32(MSG2, MSG0, MSG1); + + /** Rounds 28-31 */ + MSG3 = vsha256su0q_u32(MSG3, MSG0); + TMP2 = STATE0; + TMP0 = vaddq_u32(MSG0, vld1q_u32(&K[0x20])); + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP1); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP1); + MSG3 = vsha256su1q_u32(MSG3, MSG1, MSG2); + + /** Rounds 32-35 */ + MSG0 = vsha256su0q_u32(MSG0, MSG1); + TMP2 = STATE0; + TMP1 = vaddq_u32(MSG1, vld1q_u32(&K[0x24])); + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0); + MSG0 = vsha256su1q_u32(MSG0, MSG2, MSG3); + + /** Rounds 36-39 */ + MSG1 = vsha256su0q_u32(MSG1, MSG2); + TMP2 = STATE0; + TMP0 = vaddq_u32(MSG2, vld1q_u32(&K[0x28])); + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP1); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP1); + MSG1 = vsha256su1q_u32(MSG1, MSG3, MSG0); + + /** Rounds 40-43 */ + MSG2 = vsha256su0q_u32(MSG2, MSG3); + TMP2 = STATE0; + TMP1 = vaddq_u32(MSG3, vld1q_u32(&K[0x2c])); + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0); + MSG2 = vsha256su1q_u32(MSG2, MSG0, MSG1); + + /** Rounds 44-47 */ + MSG3 = vsha256su0q_u32(MSG3, MSG0); + TMP2 = STATE0; + TMP0 = vaddq_u32(MSG0, vld1q_u32(&K[0x30])); + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP1); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP1); + MSG3 = vsha256su1q_u32(MSG3, MSG1, MSG2); + + /** Rounds 48-51 */ + TMP2 = STATE0; + TMP1 = vaddq_u32(MSG1, vld1q_u32(&K[0x34])); + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0); + + /** Rounds 52-55 */ + TMP2 = STATE0; + TMP0 = vaddq_u32(MSG2, vld1q_u32(&K[0x38])); + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP1); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP1); + + /** Rounds 56-59 */ + TMP2 = STATE0; + TMP1 = vaddq_u32(MSG3, vld1q_u32(&K[0x3c])); + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0); + + /** Rounds 60-63 */ + TMP2 = STATE0; + STATE0 = vsha256hq_u32(STATE0, STATE1, TMP1); + STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP1); + + /** Combine state */ + STATE0 = vaddq_u32(STATE0, ABEF_SAVE); + STATE1 = vaddq_u32(STATE1, CDGH_SAVE); + } /** Save state */ vst1q_u32(&s[0], STATE0);