Compute the SHA-256 hash, 'h', of the bitstring represented by 's'. * * Precondition: uint32_t h[8]; * '*s' is a valid bitstring; * 's->len < 2^64; */
| 155 | * 's->len < 2^64; |
| 156 | */ |
| 157 | void simplicity_sha256_bitstring(uint32_t* h, const bitstring* s) { |
| 158 | /* This static assert should never fail if uint32_t exists. |
| 159 | * But for more certainty, we note that the correctness of this implementation depends on CHAR_BIT being no more than 32. |
| 160 | */ |
| 161 | static_assert(CHAR_BIT <= 32, "CHAR_BIT has to be less than 32 for uint32_t to even exist."); |
| 162 | |
| 163 | uint32_t block[16] = { 0 }; |
| 164 | size_t count = 0; |
| 165 | sha256_iv(h); |
| 166 | if (s->len) { |
| 167 | block[0] = s->arr[s->offset / CHAR_BIT]; |
| 168 | if (s->len < CHAR_BIT - s->offset % CHAR_BIT) { |
| 169 | /* s->len is so short that we don't even use a whole char. |
| 170 | * Zero out the low bits. |
| 171 | */ |
| 172 | block[0] = block[0] >> (CHAR_BIT - s->offset % CHAR_BIT - s->len) |
| 173 | << (CHAR_BIT - s->offset % CHAR_BIT - s->len); |
| 174 | count = s->len; |
| 175 | } else { |
| 176 | count = CHAR_BIT - s->offset % CHAR_BIT; |
| 177 | } |
| 178 | block[0] = 1U * block[0] << (32 - CHAR_BIT + s->offset % CHAR_BIT); |
| 179 | |
| 180 | while (count < s->len) { |
| 181 | unsigned char ch = s->arr[(s->offset + count)/CHAR_BIT]; |
| 182 | size_t delta = CHAR_BIT; |
| 183 | if (s->len - count < CHAR_BIT) { |
| 184 | delta = s->len - count; |
| 185 | /* Zero out any extra low bits that 'ch' may have. */ |
| 186 | ch = (unsigned char)(ch >> (CHAR_BIT - delta) << (CHAR_BIT - delta)); |
| 187 | } |
| 188 | |
| 189 | if (count / 32 != (count + CHAR_BIT) / 32) { |
| 190 | /* The next character from s->arr straddles (or almost straddles) the boundary of two elements of the block array. */ |
| 191 | block[count / 32 % 16] |= (uint32_t)((uint_fast32_t)ch >> (count + CHAR_BIT) % 32); |
| 192 | if (count / 512 != (count + delta) / 512) { |
| 193 | simplicity_sha256_compression(h, block); |
| 194 | memset(block, 0, sizeof(uint32_t[16])); |
| 195 | } |
| 196 | } |
| 197 | if ((count + CHAR_BIT) % 32) { |
| 198 | block[(count + CHAR_BIT) / 32 % 16] |= (uint32_t)(1U * (uint_fast32_t)ch << (32 - (count + CHAR_BIT) % 32)); |
| 199 | } |
| 200 | count += delta; |
| 201 | } |
| 202 | } |
| 203 | simplicity_assert(count == s->len); |
| 204 | sha256_end(h, block, s->len); |
| 205 | } |
| 206 | |
| 207 | #ifndef NO_SHA_NI_FLAG |
| 208 | #include "sha256_x86.inc" |
no test coverage detected