/* * LITLS -- SHA-1 (FIPS 180-4 / RFC 3174) * * WARNING: SHA-1 is cryptographically broken for collision resistance. * This implementation is provided only for git metadata parsing and * legacy protocol support. Do NOT use for production cryptography. */ #include "litls.h" #include #define LITLS_SHA1_DIGEST_SIZE 20 #define ROTL32(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) static void sha1_transform(uint32_t state[5], const uint8_t block[64]) { uint32_t w[80]; for (int i = 0; i < 16; i++) { w[i] = ((uint32_t)block[i * 4] << 24) | ((uint32_t)block[i * 4 + 1] << 16) | ((uint32_t)block[i * 4 + 2] << 8) | (uint32_t)block[i * 4 + 3]; } for (int i = 16; i < 80; i++) { w[i] = ROTL32(w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16], 1); } uint32_t a = state[0], b = state[1], c = state[2], d = state[3], e = state[4]; for (int i = 0; i < 80; i++) { uint32_t f, k; if (i < 20) { f = (b & c) | (~b & d); k = 0x5A827999; } else if (i < 40) { f = b ^ c ^ d; k = 0x6ED9EBA1; } else if (i < 60) { f = (b & c) | (b & d) | (c & d); k = 0x8F1BBCDC; } else { f = b ^ c ^ d; k = 0xCA62C1D6; } uint32_t t = ROTL32(a, 5) + f + e + k + w[i]; e = d; d = c; c = ROTL32(b, 30); b = a; a = t; } state[0] += a; state[1] += b; state[2] += c; state[3] += d; state[4] += e; } void litls_sha1(const uint8_t *data, size_t len, uint8_t out[20]) { uint32_t state[5] = {0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0}; uint8_t block[64]; size_t i = 0; /* Process full blocks */ while (i + 64 <= len) { sha1_transform(state, data + i); i += 64; } /* Final block with padding */ size_t remain = len - i; memcpy(block, data + i, remain); block[remain++] = 0x80; if (remain > 56) { memset(block + remain, 0, 64 - remain); sha1_transform(state, block); remain = 0; } memset(block + remain, 0, 56 - remain); uint64_t bitlen = (uint64_t)len * 8; block[56] = (uint8_t)(bitlen >> 56); block[57] = (uint8_t)(bitlen >> 48); block[58] = (uint8_t)(bitlen >> 40); block[59] = (uint8_t)(bitlen >> 32); block[60] = (uint8_t)(bitlen >> 24); block[61] = (uint8_t)(bitlen >> 16); block[62] = (uint8_t)(bitlen >> 8); block[63] = (uint8_t)(bitlen); sha1_transform(state, block); for (int j = 0; j < 5; j++) { out[j * 4] = (uint8_t)(state[j] >> 24); out[j * 4 + 1] = (uint8_t)(state[j] >> 16); out[j * 4 + 2] = (uint8_t)(state[j] >> 8); out[j * 4 + 3] = (uint8_t)(state[j]); } }