0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-11-25 16:22:35 +01:00

ircd::crh: Add HMAC support.

This commit is contained in:
Jason Volk 2019-01-19 12:46:44 -08:00
parent 18091eeb46
commit 950f989cf0
2 changed files with 151 additions and 0 deletions

View file

@ -20,6 +20,7 @@ namespace ircd::crh
IRCD_EXCEPTION(ircd::error, error)
struct hash;
struct hmac;
struct sha1;
struct sha256;
struct ripemd160;
@ -28,6 +29,7 @@ namespace ircd::crh
// Export aliases down to ircd::
namespace ircd
{
using crh::hmac;
using crh::sha1;
using crh::sha256;
using crh::ripemd160;
@ -61,6 +63,29 @@ struct ircd::crh::hash
virtual ~hash() noexcept;
};
struct ircd::crh::hmac
{
struct ctx;
protected:
std::unique_ptr<ctx> ctx;
public:
/// Returns the byte length of the mutable_buffer for digests
size_t length() const;
/// Samples the digest and modifies the state (depending on impl)
const_buffer finalize(const mutable_buffer &b);
/// Appends to the message
void update(const const_buffer &);
hmac(const string_view &algorithm, const const_buffer &key);
hmac(hmac &&) = default;
hmac(const hmac &) = delete;
~hmac() noexcept;
};
/// SHA-1 hashing device.
struct ircd::crh::sha1
final

View file

@ -10,6 +10,7 @@
#include <openssl/err.h>
#include <openssl/sha.h>
#include <openssl/hmac.h>
#include <openssl/ssl.h>
#include <openssl/ec.h>
#include <openssl/rsa.h>
@ -1430,6 +1431,131 @@ ircd::openssl::init::~init()
// crh.h
//
//
// hmac
//
struct ircd::crh::hmac::ctx
:HMAC_CTX
{
static constexpr const size_t &MAX_CTXS {64};
static thread_local allocator::fixed<ctx, MAX_CTXS> ctxs;
static void *operator new(const size_t count);
static void operator delete(void *const ptr, const size_t count);
ctx(const string_view &algorithm, const const_buffer &key);
~ctx() noexcept;
};
decltype(ircd::crh::hmac::ctx::ctxs)
thread_local ircd::crh::hmac::ctx::ctxs
{};
void *
ircd::crh::hmac::ctx::operator new(const size_t bytes)
{
assert(bytes > 0);
assert(bytes % sizeof(ctx) == 0);
return ctxs().allocate(bytes / sizeof(ctx));
}
void
ircd::crh::hmac::ctx::operator delete(void *const ptr,
const size_t bytes)
{
if(!ptr)
return;
assert(bytes % sizeof(ctx) == 0);
ctxs().deallocate(reinterpret_cast<ctx *>(ptr), bytes / sizeof(ctx));
}
//
// hmac::ctx::ctx
//
ircd::crh::hmac::ctx::ctx(const string_view &algorithm,
const const_buffer &key)
:HMAC_CTX{0}
{
const EVP_MD *const md
{
iequals(algorithm, "sha1")?
EVP_sha1():
iequals(algorithm, "sha256")?
EVP_sha256():
nullptr
};
if(unlikely(!md))
throw error
{
"Algorithm '%s' not supported for HMAC", algorithm
};
HMAC_CTX_init(this);
openssl::call(::HMAC_Init_ex, this, data(key), size(key), md, nullptr);
}
ircd::crh::hmac::ctx::~ctx()
noexcept
{
HMAC_CTX_cleanup(this);
}
//
// hmac::hmac
//
ircd::crh::hmac::hmac(const string_view &algorithm,
const const_buffer &key)
:ctx
{
std::make_unique<struct ctx>(algorithm, key)
}
{
}
ircd::crh::hmac::~hmac()
noexcept
{
}
void
ircd::crh::hmac::update(const const_buffer &buf)
{
assert(bool(ctx));
const auto ptr
{
reinterpret_cast<const uint8_t *>(data(buf))
};
openssl::call(::HMAC_Update, ctx.get(), ptr, size(buf));
}
ircd::const_buffer
ircd::crh::hmac::finalize(const mutable_buffer &buf)
{
assert(bool(ctx));
const auto ptr
{
reinterpret_cast<uint8_t *>(data(buf))
};
uint len;
openssl::call(::HMAC_Final, ctx.get(), ptr, &len);
return {data(buf), len};
}
size_t
ircd::crh::hmac::length()
const
{
assert(bool(ctx));
return HMAC_size(ctx.get());
}
//
// sha1
//