55 lines
1.6 KiB
C
55 lines
1.6 KiB
C
#include <stdbool.h>
|
|
#include "common.h"
|
|
|
|
__attribute__((visibility("default")))
|
|
crc32_func BizCalcCrcFunc(void) {
|
|
x86_check_features();
|
|
return (x86_cpu_has_pclmulqdq && x86_cpu_has_sse41) ? &crc32_pclmulqdq : &crc32_braid;
|
|
}
|
|
|
|
__attribute__((visibility("default")))
|
|
bool BizSupportsShaInstructions(void) {
|
|
x86_check_features();
|
|
return x86_cpu_has_sha && x86_cpu_has_sse41;
|
|
}
|
|
|
|
__attribute__((visibility("default")))
|
|
void BizCalcSha1(uint32_t state[5], const uint8_t data[], uint32_t length) {
|
|
x86_check_features();
|
|
|
|
uint64_t bit_length = length * 8ULL;
|
|
|
|
// hash most of the data, leaving at most 63 bytes left
|
|
sha1_sha(state, data, length);
|
|
data += length & ~0x3F;
|
|
length &= 0x3F;
|
|
|
|
// copy all remaining data to a buffer
|
|
uint8_t block[64] = {0};
|
|
memcpy(block, data, length);
|
|
|
|
// pad data with '1' bit
|
|
block[length++] = 0x80;
|
|
|
|
// the last 8 bytes in the last block contain the data length;
|
|
// if the current block is too full hash it and start a new one (here the old one is cleared and re-used)
|
|
if (__builtin_expect(length > 56, false)) {
|
|
sha1_sha(state, block, 64);
|
|
memset(block, 0, 56);
|
|
}
|
|
|
|
// fill the last 8 bytes in the last block with the data length in bits (big endian)
|
|
for (int i = 0; i != 8; i++) {
|
|
block[63 - i] = bit_length >> i * 8;
|
|
}
|
|
// hash the last block
|
|
sha1_sha(state, block, 64);
|
|
|
|
// byteswap state (to big endian format)
|
|
state[0] = __builtin_bswap32(state[0]);
|
|
state[1] = __builtin_bswap32(state[1]);
|
|
state[2] = __builtin_bswap32(state[2]);
|
|
state[3] = __builtin_bswap32(state[3]);
|
|
state[4] = __builtin_bswap32(state[4]);
|
|
}
|