|
| 1 | +/* |
| 2 | + * SHA-256 hash in C |
| 3 | + * |
| 4 | + * Copyright (c) 2023 Project Nayuki. (MIT License) |
| 5 | + * https://www.nayuki.io/page/fast-sha2-hashes-in-x86-assembly |
| 6 | + * |
| 7 | + * Permission is hereby granted, free of charge, to any person obtaining a copy of |
| 8 | + * this software and associated documentation files (the "Software"), to deal in |
| 9 | + * the Software without restriction, including without limitation the rights to |
| 10 | + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of |
| 11 | + * the Software, and to permit persons to whom the Software is furnished to do so, |
| 12 | + * subject to the following conditions: |
| 13 | + * - The above copyright notice and this permission notice shall be included in |
| 14 | + * all copies or substantial portions of the Software. |
| 15 | + * - The Software is provided "as is", without warranty of any kind, express or |
| 16 | + * implied, including but not limited to the warranties of merchantability, |
| 17 | + * fitness for a particular purpose and noninfringement. In no event shall the |
| 18 | + * authors or copyright holders be liable for any claim, damages or other |
| 19 | + * liability, whether in an action of contract, tort or otherwise, arising from, |
| 20 | + * out of or in connection with the Software or the use or other dealings in the |
| 21 | + * Software. |
| 22 | + */ |
| 23 | + |
| 24 | +#include <xen/string.h> |
| 25 | +#include <xen/types.h> |
| 26 | + |
| 27 | +#define UINT32_C(v) v ## U |
| 28 | + |
| 29 | +#define BLOCK_LEN 64 // In bytes |
| 30 | +#define STATE_LEN 8 // In words |
| 31 | + |
| 32 | +static void sha256_compress(const uint8_t block[static 64], uint32_t state[static 8]) { |
| 33 | + #define ROTR32(x, n) (((0U + (x)) << (32 - (n))) | ((x) >> (n))) // Assumes that x is uint32_t and 0 < n < 32 |
| 34 | + |
| 35 | + #define LOADSCHEDULE(i) \ |
| 36 | + schedule[i] = (uint32_t)block[i * 4 + 0] << 24 \ |
| 37 | + | (uint32_t)block[i * 4 + 1] << 16 \ |
| 38 | + | (uint32_t)block[i * 4 + 2] << 8 \ |
| 39 | + | (uint32_t)block[i * 4 + 3] << 0; |
| 40 | + |
| 41 | + #define SCHEDULE(i) \ |
| 42 | + schedule[i] = 0U + schedule[i - 16] + schedule[i - 7] \ |
| 43 | + + (ROTR32(schedule[i - 15], 7) ^ ROTR32(schedule[i - 15], 18) ^ (schedule[i - 15] >> 3)) \ |
| 44 | + + (ROTR32(schedule[i - 2], 17) ^ ROTR32(schedule[i - 2], 19) ^ (schedule[i - 2] >> 10)); |
| 45 | + |
| 46 | + #define ROUND(a, b, c, d, e, f, g, h, i, k) \ |
| 47 | + h = 0U + h + (ROTR32(e, 6) ^ ROTR32(e, 11) ^ ROTR32(e, 25)) + (g ^ (e & (f ^ g))) + UINT32_C(k) + schedule[i]; \ |
| 48 | + d = 0U + d + h; \ |
| 49 | + h = 0U + h + (ROTR32(a, 2) ^ ROTR32(a, 13) ^ ROTR32(a, 22)) + ((a & (b | c)) | (b & c)); |
| 50 | + |
| 51 | + uint32_t schedule[64]; |
| 52 | + |
| 53 | + uint32_t a = state[0]; |
| 54 | + uint32_t b = state[1]; |
| 55 | + uint32_t c = state[2]; |
| 56 | + uint32_t d = state[3]; |
| 57 | + uint32_t e = state[4]; |
| 58 | + uint32_t f = state[5]; |
| 59 | + uint32_t g = state[6]; |
| 60 | + uint32_t h = state[7]; |
| 61 | + |
| 62 | + LOADSCHEDULE( 0) |
| 63 | + LOADSCHEDULE( 1) |
| 64 | + LOADSCHEDULE( 2) |
| 65 | + LOADSCHEDULE( 3) |
| 66 | + LOADSCHEDULE( 4) |
| 67 | + LOADSCHEDULE( 5) |
| 68 | + LOADSCHEDULE( 6) |
| 69 | + LOADSCHEDULE( 7) |
| 70 | + LOADSCHEDULE( 8) |
| 71 | + LOADSCHEDULE( 9) |
| 72 | + LOADSCHEDULE(10) |
| 73 | + LOADSCHEDULE(11) |
| 74 | + LOADSCHEDULE(12) |
| 75 | + LOADSCHEDULE(13) |
| 76 | + LOADSCHEDULE(14) |
| 77 | + LOADSCHEDULE(15) |
| 78 | + SCHEDULE(16) |
| 79 | + SCHEDULE(17) |
| 80 | + SCHEDULE(18) |
| 81 | + SCHEDULE(19) |
| 82 | + SCHEDULE(20) |
| 83 | + SCHEDULE(21) |
| 84 | + SCHEDULE(22) |
| 85 | + SCHEDULE(23) |
| 86 | + SCHEDULE(24) |
| 87 | + SCHEDULE(25) |
| 88 | + SCHEDULE(26) |
| 89 | + SCHEDULE(27) |
| 90 | + SCHEDULE(28) |
| 91 | + SCHEDULE(29) |
| 92 | + SCHEDULE(30) |
| 93 | + SCHEDULE(31) |
| 94 | + SCHEDULE(32) |
| 95 | + SCHEDULE(33) |
| 96 | + SCHEDULE(34) |
| 97 | + SCHEDULE(35) |
| 98 | + SCHEDULE(36) |
| 99 | + SCHEDULE(37) |
| 100 | + SCHEDULE(38) |
| 101 | + SCHEDULE(39) |
| 102 | + SCHEDULE(40) |
| 103 | + SCHEDULE(41) |
| 104 | + SCHEDULE(42) |
| 105 | + SCHEDULE(43) |
| 106 | + SCHEDULE(44) |
| 107 | + SCHEDULE(45) |
| 108 | + SCHEDULE(46) |
| 109 | + SCHEDULE(47) |
| 110 | + SCHEDULE(48) |
| 111 | + SCHEDULE(49) |
| 112 | + SCHEDULE(50) |
| 113 | + SCHEDULE(51) |
| 114 | + SCHEDULE(52) |
| 115 | + SCHEDULE(53) |
| 116 | + SCHEDULE(54) |
| 117 | + SCHEDULE(55) |
| 118 | + SCHEDULE(56) |
| 119 | + SCHEDULE(57) |
| 120 | + SCHEDULE(58) |
| 121 | + SCHEDULE(59) |
| 122 | + SCHEDULE(60) |
| 123 | + SCHEDULE(61) |
| 124 | + SCHEDULE(62) |
| 125 | + SCHEDULE(63) |
| 126 | + |
| 127 | + ROUND(a, b, c, d, e, f, g, h, 0, 0x428A2F98) |
| 128 | + ROUND(h, a, b, c, d, e, f, g, 1, 0x71374491) |
| 129 | + ROUND(g, h, a, b, c, d, e, f, 2, 0xB5C0FBCF) |
| 130 | + ROUND(f, g, h, a, b, c, d, e, 3, 0xE9B5DBA5) |
| 131 | + ROUND(e, f, g, h, a, b, c, d, 4, 0x3956C25B) |
| 132 | + ROUND(d, e, f, g, h, a, b, c, 5, 0x59F111F1) |
| 133 | + ROUND(c, d, e, f, g, h, a, b, 6, 0x923F82A4) |
| 134 | + ROUND(b, c, d, e, f, g, h, a, 7, 0xAB1C5ED5) |
| 135 | + ROUND(a, b, c, d, e, f, g, h, 8, 0xD807AA98) |
| 136 | + ROUND(h, a, b, c, d, e, f, g, 9, 0x12835B01) |
| 137 | + ROUND(g, h, a, b, c, d, e, f, 10, 0x243185BE) |
| 138 | + ROUND(f, g, h, a, b, c, d, e, 11, 0x550C7DC3) |
| 139 | + ROUND(e, f, g, h, a, b, c, d, 12, 0x72BE5D74) |
| 140 | + ROUND(d, e, f, g, h, a, b, c, 13, 0x80DEB1FE) |
| 141 | + ROUND(c, d, e, f, g, h, a, b, 14, 0x9BDC06A7) |
| 142 | + ROUND(b, c, d, e, f, g, h, a, 15, 0xC19BF174) |
| 143 | + ROUND(a, b, c, d, e, f, g, h, 16, 0xE49B69C1) |
| 144 | + ROUND(h, a, b, c, d, e, f, g, 17, 0xEFBE4786) |
| 145 | + ROUND(g, h, a, b, c, d, e, f, 18, 0x0FC19DC6) |
| 146 | + ROUND(f, g, h, a, b, c, d, e, 19, 0x240CA1CC) |
| 147 | + ROUND(e, f, g, h, a, b, c, d, 20, 0x2DE92C6F) |
| 148 | + ROUND(d, e, f, g, h, a, b, c, 21, 0x4A7484AA) |
| 149 | + ROUND(c, d, e, f, g, h, a, b, 22, 0x5CB0A9DC) |
| 150 | + ROUND(b, c, d, e, f, g, h, a, 23, 0x76F988DA) |
| 151 | + ROUND(a, b, c, d, e, f, g, h, 24, 0x983E5152) |
| 152 | + ROUND(h, a, b, c, d, e, f, g, 25, 0xA831C66D) |
| 153 | + ROUND(g, h, a, b, c, d, e, f, 26, 0xB00327C8) |
| 154 | + ROUND(f, g, h, a, b, c, d, e, 27, 0xBF597FC7) |
| 155 | + ROUND(e, f, g, h, a, b, c, d, 28, 0xC6E00BF3) |
| 156 | + ROUND(d, e, f, g, h, a, b, c, 29, 0xD5A79147) |
| 157 | + ROUND(c, d, e, f, g, h, a, b, 30, 0x06CA6351) |
| 158 | + ROUND(b, c, d, e, f, g, h, a, 31, 0x14292967) |
| 159 | + ROUND(a, b, c, d, e, f, g, h, 32, 0x27B70A85) |
| 160 | + ROUND(h, a, b, c, d, e, f, g, 33, 0x2E1B2138) |
| 161 | + ROUND(g, h, a, b, c, d, e, f, 34, 0x4D2C6DFC) |
| 162 | + ROUND(f, g, h, a, b, c, d, e, 35, 0x53380D13) |
| 163 | + ROUND(e, f, g, h, a, b, c, d, 36, 0x650A7354) |
| 164 | + ROUND(d, e, f, g, h, a, b, c, 37, 0x766A0ABB) |
| 165 | + ROUND(c, d, e, f, g, h, a, b, 38, 0x81C2C92E) |
| 166 | + ROUND(b, c, d, e, f, g, h, a, 39, 0x92722C85) |
| 167 | + ROUND(a, b, c, d, e, f, g, h, 40, 0xA2BFE8A1) |
| 168 | + ROUND(h, a, b, c, d, e, f, g, 41, 0xA81A664B) |
| 169 | + ROUND(g, h, a, b, c, d, e, f, 42, 0xC24B8B70) |
| 170 | + ROUND(f, g, h, a, b, c, d, e, 43, 0xC76C51A3) |
| 171 | + ROUND(e, f, g, h, a, b, c, d, 44, 0xD192E819) |
| 172 | + ROUND(d, e, f, g, h, a, b, c, 45, 0xD6990624) |
| 173 | + ROUND(c, d, e, f, g, h, a, b, 46, 0xF40E3585) |
| 174 | + ROUND(b, c, d, e, f, g, h, a, 47, 0x106AA070) |
| 175 | + ROUND(a, b, c, d, e, f, g, h, 48, 0x19A4C116) |
| 176 | + ROUND(h, a, b, c, d, e, f, g, 49, 0x1E376C08) |
| 177 | + ROUND(g, h, a, b, c, d, e, f, 50, 0x2748774C) |
| 178 | + ROUND(f, g, h, a, b, c, d, e, 51, 0x34B0BCB5) |
| 179 | + ROUND(e, f, g, h, a, b, c, d, 52, 0x391C0CB3) |
| 180 | + ROUND(d, e, f, g, h, a, b, c, 53, 0x4ED8AA4A) |
| 181 | + ROUND(c, d, e, f, g, h, a, b, 54, 0x5B9CCA4F) |
| 182 | + ROUND(b, c, d, e, f, g, h, a, 55, 0x682E6FF3) |
| 183 | + ROUND(a, b, c, d, e, f, g, h, 56, 0x748F82EE) |
| 184 | + ROUND(h, a, b, c, d, e, f, g, 57, 0x78A5636F) |
| 185 | + ROUND(g, h, a, b, c, d, e, f, 58, 0x84C87814) |
| 186 | + ROUND(f, g, h, a, b, c, d, e, 59, 0x8CC70208) |
| 187 | + ROUND(e, f, g, h, a, b, c, d, 60, 0x90BEFFFA) |
| 188 | + ROUND(d, e, f, g, h, a, b, c, 61, 0xA4506CEB) |
| 189 | + ROUND(c, d, e, f, g, h, a, b, 62, 0xBEF9A3F7) |
| 190 | + ROUND(b, c, d, e, f, g, h, a, 63, 0xC67178F2) |
| 191 | + |
| 192 | + state[0] = 0U + state[0] + a; |
| 193 | + state[1] = 0U + state[1] + b; |
| 194 | + state[2] = 0U + state[2] + c; |
| 195 | + state[3] = 0U + state[3] + d; |
| 196 | + state[4] = 0U + state[4] + e; |
| 197 | + state[5] = 0U + state[5] + f; |
| 198 | + state[6] = 0U + state[6] + g; |
| 199 | + state[7] = 0U + state[7] + h; |
| 200 | +} |
| 201 | + |
| 202 | +/* Full message hasher */ |
| 203 | + |
| 204 | +void sha256_hash(const uint8_t message[], size_t len, uint32_t hash[static STATE_LEN]) { |
| 205 | + uint8_t block[BLOCK_LEN] = {0}; |
| 206 | + size_t off; |
| 207 | + size_t rem; |
| 208 | + |
| 209 | + hash[0] = UINT32_C(0x6A09E667); |
| 210 | + hash[1] = UINT32_C(0xBB67AE85); |
| 211 | + hash[2] = UINT32_C(0x3C6EF372); |
| 212 | + hash[3] = UINT32_C(0xA54FF53A); |
| 213 | + hash[4] = UINT32_C(0x510E527F); |
| 214 | + hash[5] = UINT32_C(0x9B05688C); |
| 215 | + hash[6] = UINT32_C(0x1F83D9AB); |
| 216 | + hash[7] = UINT32_C(0x5BE0CD19); |
| 217 | + |
| 218 | + #define LENGTH_SIZE 8 // In bytes |
| 219 | + |
| 220 | + for (off = 0; len - off >= BLOCK_LEN; off += BLOCK_LEN) |
| 221 | + sha256_compress(&message[off], hash); |
| 222 | + |
| 223 | + rem = len - off; |
| 224 | + if (rem > 0) |
| 225 | + memcpy(block, &message[off], rem); |
| 226 | + |
| 227 | + block[rem] = 0x80; |
| 228 | + rem++; |
| 229 | + if (BLOCK_LEN - rem < LENGTH_SIZE) { |
| 230 | + sha256_compress(block, hash); |
| 231 | + memset(block, 0, sizeof(block)); |
| 232 | + } |
| 233 | + |
| 234 | + block[BLOCK_LEN - 1] = (uint8_t)((len & 0x1FU) << 3); |
| 235 | + len >>= 5; |
| 236 | + for (int i = 1; i < LENGTH_SIZE; i++, len >>= 8) |
| 237 | + block[BLOCK_LEN - 1 - i] = (uint8_t)(len & 0xFFU); |
| 238 | + sha256_compress(block, hash); |
| 239 | + |
| 240 | + hash[0] = __builtin_bswap32(hash[0]); |
| 241 | + hash[1] = __builtin_bswap32(hash[1]); |
| 242 | + hash[2] = __builtin_bswap32(hash[2]); |
| 243 | + hash[3] = __builtin_bswap32(hash[3]); |
| 244 | + hash[4] = __builtin_bswap32(hash[4]); |
| 245 | + hash[5] = __builtin_bswap32(hash[5]); |
| 246 | + hash[6] = __builtin_bswap32(hash[6]); |
| 247 | + hash[7] = __builtin_bswap32(hash[7]); |
| 248 | +} |
0 commit comments