ppad-sha256-0.3.2: cbits/sha256_arm.c
#include <stdint.h>
#include <string.h>
#if defined(__aarch64__) && defined(__ARM_FEATURE_SHA2)
#include <arm_neon.h>
static const uint32_t K[64] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};
/*
* Process one 64-byte block using ARM SHA256 crypto instructions.
*
* state: pointer to 8 uint32_t words (a,b,c,d,e,f,g,h)
* block: pointer to 16 uint32_t words (already native endian)
*
* The state is updated in place.
*/
void sha256_block_arm(uint32_t *state, const uint32_t *block) {
/* Load current hash state */
uint32x4_t abcd = vld1q_u32(&state[0]);
uint32x4_t efgh = vld1q_u32(&state[4]);
/* Save original for final addition */
uint32x4_t abcd_orig = abcd;
uint32x4_t efgh_orig = efgh;
/* Load message (already native endian) */
uint32x4_t m0 = vld1q_u32(&block[0]);
uint32x4_t m1 = vld1q_u32(&block[4]);
uint32x4_t m2 = vld1q_u32(&block[8]);
uint32x4_t m3 = vld1q_u32(&block[12]);
uint32x4_t tmp, tmp2;
/* Rounds 0-3 */
tmp = vaddq_u32(m0, vld1q_u32(&K[0]));
tmp2 = abcd;
abcd = vsha256hq_u32(abcd, efgh, tmp);
efgh = vsha256h2q_u32(efgh, tmp2, tmp);
m0 = vsha256su1q_u32(vsha256su0q_u32(m0, m1), m2, m3);
/* Rounds 4-7 */
tmp = vaddq_u32(m1, vld1q_u32(&K[4]));
tmp2 = abcd;
abcd = vsha256hq_u32(abcd, efgh, tmp);
efgh = vsha256h2q_u32(efgh, tmp2, tmp);
m1 = vsha256su1q_u32(vsha256su0q_u32(m1, m2), m3, m0);
/* Rounds 8-11 */
tmp = vaddq_u32(m2, vld1q_u32(&K[8]));
tmp2 = abcd;
abcd = vsha256hq_u32(abcd, efgh, tmp);
efgh = vsha256h2q_u32(efgh, tmp2, tmp);
m2 = vsha256su1q_u32(vsha256su0q_u32(m2, m3), m0, m1);
/* Rounds 12-15 */
tmp = vaddq_u32(m3, vld1q_u32(&K[12]));
tmp2 = abcd;
abcd = vsha256hq_u32(abcd, efgh, tmp);
efgh = vsha256h2q_u32(efgh, tmp2, tmp);
m3 = vsha256su1q_u32(vsha256su0q_u32(m3, m0), m1, m2);
/* Rounds 16-19 */
tmp = vaddq_u32(m0, vld1q_u32(&K[16]));
tmp2 = abcd;
abcd = vsha256hq_u32(abcd, efgh, tmp);
efgh = vsha256h2q_u32(efgh, tmp2, tmp);
m0 = vsha256su1q_u32(vsha256su0q_u32(m0, m1), m2, m3);
/* Rounds 20-23 */
tmp = vaddq_u32(m1, vld1q_u32(&K[20]));
tmp2 = abcd;
abcd = vsha256hq_u32(abcd, efgh, tmp);
efgh = vsha256h2q_u32(efgh, tmp2, tmp);
m1 = vsha256su1q_u32(vsha256su0q_u32(m1, m2), m3, m0);
/* Rounds 24-27 */
tmp = vaddq_u32(m2, vld1q_u32(&K[24]));
tmp2 = abcd;
abcd = vsha256hq_u32(abcd, efgh, tmp);
efgh = vsha256h2q_u32(efgh, tmp2, tmp);
m2 = vsha256su1q_u32(vsha256su0q_u32(m2, m3), m0, m1);
/* Rounds 28-31 */
tmp = vaddq_u32(m3, vld1q_u32(&K[28]));
tmp2 = abcd;
abcd = vsha256hq_u32(abcd, efgh, tmp);
efgh = vsha256h2q_u32(efgh, tmp2, tmp);
m3 = vsha256su1q_u32(vsha256su0q_u32(m3, m0), m1, m2);
/* Rounds 32-35 */
tmp = vaddq_u32(m0, vld1q_u32(&K[32]));
tmp2 = abcd;
abcd = vsha256hq_u32(abcd, efgh, tmp);
efgh = vsha256h2q_u32(efgh, tmp2, tmp);
m0 = vsha256su1q_u32(vsha256su0q_u32(m0, m1), m2, m3);
/* Rounds 36-39 */
tmp = vaddq_u32(m1, vld1q_u32(&K[36]));
tmp2 = abcd;
abcd = vsha256hq_u32(abcd, efgh, tmp);
efgh = vsha256h2q_u32(efgh, tmp2, tmp);
m1 = vsha256su1q_u32(vsha256su0q_u32(m1, m2), m3, m0);
/* Rounds 40-43 */
tmp = vaddq_u32(m2, vld1q_u32(&K[40]));
tmp2 = abcd;
abcd = vsha256hq_u32(abcd, efgh, tmp);
efgh = vsha256h2q_u32(efgh, tmp2, tmp);
m2 = vsha256su1q_u32(vsha256su0q_u32(m2, m3), m0, m1);
/* Rounds 44-47 */
tmp = vaddq_u32(m3, vld1q_u32(&K[44]));
tmp2 = abcd;
abcd = vsha256hq_u32(abcd, efgh, tmp);
efgh = vsha256h2q_u32(efgh, tmp2, tmp);
m3 = vsha256su1q_u32(vsha256su0q_u32(m3, m0), m1, m2);
/* Rounds 48-51 */
tmp = vaddq_u32(m0, vld1q_u32(&K[48]));
tmp2 = abcd;
abcd = vsha256hq_u32(abcd, efgh, tmp);
efgh = vsha256h2q_u32(efgh, tmp2, tmp);
/* Rounds 52-55 */
tmp = vaddq_u32(m1, vld1q_u32(&K[52]));
tmp2 = abcd;
abcd = vsha256hq_u32(abcd, efgh, tmp);
efgh = vsha256h2q_u32(efgh, tmp2, tmp);
/* Rounds 56-59 */
tmp = vaddq_u32(m2, vld1q_u32(&K[56]));
tmp2 = abcd;
abcd = vsha256hq_u32(abcd, efgh, tmp);
efgh = vsha256h2q_u32(efgh, tmp2, tmp);
/* Rounds 60-63 */
tmp = vaddq_u32(m3, vld1q_u32(&K[60]));
tmp2 = abcd;
abcd = vsha256hq_u32(abcd, efgh, tmp);
efgh = vsha256h2q_u32(efgh, tmp2, tmp);
/* Add original state back */
abcd = vaddq_u32(abcd, abcd_orig);
efgh = vaddq_u32(efgh, efgh_orig);
/* Store result */
vst1q_u32(&state[0], abcd);
vst1q_u32(&state[4], efgh);
}
/* Return 1 if ARM SHA2 is available, 0 otherwise */
int sha256_arm_available(void) {
return 1;
}
#else
/* Stub implementations when ARM SHA2 is not available */
void sha256_block_arm(uint32_t *state, const uint32_t *block) {
(void)state;
(void)block;
/* Should never be called - use pure Haskell fallback */
}
int sha256_arm_available(void) {
return 0;
}
#endif