Hi,

On 20/10/26 16:55, Stian Halseth wrote:
Implement the SHA1, SHA256 and SHA512 instructions according
to OSA (Oracle SPARC Architecture) 2011 section 7.115,
using the algorithms defined in FIPS 180-4.

Read and update the fixed floating-point registers and mark the
lower FPR bank dirty. Share the SHA-2 Boolean functions between
the SHA256 and SHA512 helpers.

Gated behind the crypto CPU feature and disabled for sparc32.

Signed-off-by: Stian Halseth <[email protected]>
---
  target/sparc/crypto_helper.c | 272 +++++++++++++++++++++++++++++++++++
  target/sparc/helper.h        |   3 +
  target/sparc/insns.decode    |   4 +
  target/sparc/translate.c     |  18 +++
  4 files changed, 297 insertions(+)

(Bonus for TCG tests, later).

+/* Compress 16 numeric message words into the supplied SHA-256 state. */
+static void sha256_compress(uint32_t state[8], const uint32_t block[16])
+{
+    uint32_t a = state[0], b = state[1], c = state[2], d = state[3];
+    uint32_t e = state[4], f = state[5], g = state[6], h = state[7];
+    uint32_t w[64];
+
+    /* Expand the message into the 64-word round schedule. */
+    memcpy(w, block, 16 * sizeof(*w));
+    for (int i = 16; i < 64; i++) {
+        uint32_t x = w[i - 15], y = w[i - 2];
+        uint32_t s0 = ror32(x, 7) ^ ror32(x, 18) ^ (x >> 3);
+        uint32_t s1 = ror32(y, 17) ^ ror32(y, 19) ^ (y >> 10);
+
+        w[i] = w[i - 16] + s0 + w[i - 7] + s1;
+    }
+
+    /* Perform 64 rounds with arithmetic modulo 2^32. */
+    for (int i = 0; i < 64; i++) {
+        uint32_t s0 = ror32(a, 2) ^ ror32(a, 13) ^ ror32(a, 22);
+        uint32_t s1 = ror32(e, 6) ^ ror32(e, 11) ^ ror32(e, 25);

The explicit narrowing casts below are a bit awkward, let's precise:

       /* sha_ch/sha_maj are shared with SHA-512; narrow to 32 bits. */

+        uint32_t t1 = h + s1 + (uint32_t)sha_ch(e, f, g) +
+                      sha256_k[i] + w[i];
+        uint32_t t2 = s0 + (uint32_t)sha_maj(a, b, c);
+
+        h = g;
+        g = f;
+        f = e;
+        e = d + t1;
+        d = c;
+        c = b;
+        b = a;
+        a = t1 + t2;
+    }
+
+    /* Add the working words to the original state. */
+    state[0] += a;
+    state[1] += b;
+    state[2] += c;
+    state[3] += d;
+    state[4] += e;
+    state[5] += f;
+    state[6] += g;
+    state[7] += h;
+}
+
+/* Compress 16 numeric message words into the supplied SHA-512 state. */
+static void sha512_compress(uint64_t state[8], const uint64_t block[16])
+{
+    uint64_t a = state[0], b = state[1], c = state[2], d = state[3];
+    uint64_t e = state[4], f = state[5], g = state[6], h = state[7];
+    uint64_t w[80];
+
+    /* Expand the message into the 80-word round schedule. */
+    memcpy(w, block, 16 * sizeof(*w));
+    for (int i = 16; i < 80; i++) {
+        uint64_t x = w[i - 15], y = w[i - 2];
+        uint64_t s0 = ror64(x, 1) ^ ror64(x, 8) ^ (x >> 7);
+        uint64_t s1 = ror64(y, 19) ^ ror64(y, 61) ^ (y >> 6);
+
+        w[i] = w[i - 16] + s0 + w[i - 7] + s1;
+    }
+
+    /* Perform 80 rounds with arithmetic modulo 2^64. */
+    for (int i = 0; i < 80; i++) {
+        uint64_t s0 = ror64(a, 28) ^ ror64(a, 34) ^ ror64(a, 39);
+        uint64_t s1 = ror64(e, 14) ^ ror64(e, 18) ^ ror64(e, 41);
+        uint64_t t1 = h + s1 + sha_ch(e, f, g) + sha512_k[i] + w[i];
+        uint64_t t2 = s0 + sha_maj(a, b, c);
+
+        h = g;
+        g = f;
+        f = e;
+        e = d + t1;
+        d = c;
+        c = b;
+        b = a;
+        a = t1 + t2;
+    }
+
+    /* Add the working words to the original state. */
+    state[0] += a;
+    state[1] += b;
+    state[2] += c;
+    state[3] += d;
+    state[4] += e;
+    state[5] += f;
+    state[6] += g;
+    state[7] += h;
+}


diff --git a/target/sparc/helper.h b/target/sparc/helper.h
index 1320f5ebba..4be84622c8 100644
--- a/target/sparc/helper.h
+++ b/target/sparc/helper.h
@@ -134,6 +134,9 @@ DEF_HELPER_FLAGS_2(aes_kexpand0, TCG_CALL_NO_RWG_SE, i64, 
i64, i64)
  DEF_HELPER_FLAGS_3(aes_kexpand1, TCG_CALL_NO_RWG_SE, i64, i64, i64, i32)
  DEF_HELPER_FLAGS_2(aes_kexpand2, TCG_CALL_NO_RWG_SE, i64, i64, i64)
  DEF_HELPER_FLAGS_2(crc32c, TCG_CALL_NO_RWG_SE, i64, i64, i64)
+DEF_HELPER_FLAGS_1(sha1, TCG_CALL_NO_RWG, void, env)
+DEF_HELPER_FLAGS_1(sha256, TCG_CALL_NO_RWG, void, env)
+DEF_HELPER_FLAGS_1(sha512, TCG_CALL_NO_RWG, void, env)

Hmm you set TCG_CALL_NO_RWG but the helper do read env->fpr[].
While benign in practice because fpr[] aren't tracked as global
TCG regs, the correct declaration is using no flag at all:

DEF_HELPER_1(sha1, void, env)
DEF_HELPER_1(sha256, void, env)
DEF_HELPER_1(sha512, void, env)

Otherwise:
Reviewed-by: Philippe Mathieu-Daudé <[email protected]>
Tested-by: Philippe Mathieu-Daudé <[email protected]>

Reply via email to