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]>