Add sha1sum utils, to be used in plugin scanning

Signed-off-by: falkTX <falktx@falktx.com>
This commit is contained in:
falkTX 2023-05-20 00:11:58 +02:00
parent aa85fae43a
commit eb164c6920
No known key found for this signature in database
GPG Key ID: CDBAA37ABC74FBA0
1 changed files with 198 additions and 0 deletions

View File

@ -0,0 +1,198 @@
/*
* Carla sha1 utils
* Based on libcrypt placed in the public domain by Wei Dai and other contributors
* Copyright (C) 2023 Filipe Coelho <falktx@falktx.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the doc/GPL.txt file.
*/
#ifndef CARLA_SHA1_UTILS_HPP_INCLUDED
#define CARLA_SHA1_UTILS_HPP_INCLUDED
#include "CarlaUtils.hpp"
#ifdef __BIG_ENDIAN__
# define CARLA_SHA1_BIG_ENDIAN
#elif defined __LITTLE_ENDIAN__
/* override */
#elif defined __BYTE_ORDER
# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
# define CARLA_SHA1_BIG_ENDIAN
# endif
#else // ! defined __LITTLE_ENDIAN__
# include <endian.h> // machine/endian.h
# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
# define CARLA_SHA1_BIG_ENDIAN
# endif
#endif
class CarlaSha1 {
static constexpr const size_t BLOCK_LENGTH = 64;
union {
uint8_t u8[BLOCK_LENGTH];
uint32_t u32[BLOCK_LENGTH/sizeof(uint32_t)];
} buffer;
uint32_t state[5];
uint32_t byteCount;
uint8_t bufferOffset;
char resultstr[41];
static_assert(sizeof(buffer.u8) == sizeof(buffer.u32), "valid size");
public:
CarlaSha1()
: byteCount(0),
bufferOffset(0)
{
state[0] = 0x67452301;
state[1] = 0xefcdab89;
state[2] = 0x98badcfe;
state[3] = 0x10325476;
state[4] = 0xc3d2e1f0;
}
void writeByte(const uint8_t data)
{
++byteCount;
_addUncounted(data);
}
void write(const uint8_t* data, size_t len)
{
while (len--)
writeByte(*data++);
}
// Return hash array (20 characters)
const uint8_t* resultAsHash()
{
// Pad to complete the last block
_pad();
#ifndef CARLA_SHA1_BIG_ENDIAN
// Swap byte order back
for (int i=0; i<5; ++i)
{
state[i] = ((state[i] << 24) & 0xff000000)
| ((state[i] << 8) & 0x00ff0000)
| ((state[i] >> 8) & 0x0000ff00)
| ((state[i] >> 24) & 0x000000ff);
}
#endif
return static_cast<uint8_t*>(static_cast<void*>(state));
}
const char* resultAsString()
{
const uint8_t* const hash = resultAsHash();
for (int i=0; i<20; ++i)
std::snprintf(resultstr + (i * 2), 3, "%02x", hash[i]);
resultstr[40] = '\0';
return resultstr;
}
private:
void _addUncounted(const uint8_t data)
{
#ifdef CARLA_SHA1_BIG_ENDIAN
buffer.u8[bufferOffset] = data;
#else
buffer.u8[bufferOffset ^ 3] = data;
#endif
if (++bufferOffset == BLOCK_LENGTH)
{
bufferOffset = 0;
_hashBlock();
}
}
void _hashBlock()
{
uint32_t a = state[0];
uint32_t b = state[1];
uint32_t c = state[2];
uint32_t d = state[3];
uint32_t e = state[4];
uint32_t t;
for (uint8_t i=0; i<80; ++i)
{
if (i >= 16)
{
t = buffer.u32[(i + 13) & 15]
^ buffer.u32[(i + 8) & 15]
^ buffer.u32[(i + 2) & 15]
^ buffer.u32[i & 15];
buffer.u32[i & 15] = _rol32(t, 1);
}
if (i < 20)
{
t = (d ^ (b & (c ^ d))) + 0x5a827999;
}
else if (i < 40)
{
t = (b ^ c ^ d) + 0x6ed9eba1;
}
else if (i < 60)
{
t = ((b & c) | (d & (b | c))) + 0x8f1bbcdc;
}
else
{
t = (b ^ c ^ d) + 0xca62c1d6;
}
t += _rol32(a, 5) + e + buffer.u32[i & 15];
e = d;
d = c;
c = _rol32(b, 30);
b = a;
a = t;
}
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
state[4] += e;
}
// Implement SHA-1 padding (fips180-2 §5.1.1)
void _pad()
{
// Pad with 0x80 followed by 0x00 until the end of the block
_addUncounted(0x80);
while (bufferOffset != 56) _addUncounted(0x00);
// Append length in the last 8 bytes
_addUncounted(0); // We're only using 32 bit lengths
_addUncounted(0); // But SHA-1 supports 64 bit lengths
_addUncounted(0); // So zero pad the top bits
_addUncounted(byteCount >> 29); // Shifting to multiply by 8
_addUncounted(byteCount >> 21); // as SHA-1 supports bitstreams as well as
_addUncounted(byteCount >> 13); // byte.
_addUncounted(byteCount >> 5);
_addUncounted(byteCount << 3);
}
static uint32_t _rol32(const uint32_t number, const uint8_t bits)
{
return (number << bits) | (number >> (32 - bits));
}
};
#endif // CARLA_SHA1_UTILS_HPP_INCLUDED