Browse Source

Add sha1sum utils, to be used in plugin scanning

Signed-off-by: falkTX <falktx@falktx.com>
pull/1780/head
falkTX 1 year ago
parent
commit
eb164c6920
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
1 changed files with 198 additions and 0 deletions
  1. +198
    -0
      source/utils/CarlaSha1Utils.hpp

+ 198
- 0
source/utils/CarlaSha1Utils.hpp 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

Loading…
Cancel
Save