Reece Wilson
8a2947ffc5
[*] Refactor bcrypt api: HashPW[Ex] -> HashPassword[Ex] [+] ByteBuffer::GetOrAllocateLinearWriteable [+] ByteBuffer::Can[Read/Write](n) [+] ByteBuffer::GetLinear[Read/Writable]able(n) [*] Split RNG.cpp into two files [+] EHashType::eSHA2_48 (_32, _64 was already in place. missed 48/384 bit) [+] AuCrypto::HMAC and IHMACContext (AuHashing) [+] EHashType::eSHA3_28 [+] EHashType::eSHA3_32 [+] EHashType::eSHA3_48 [+] EHashType::eSHA3_64 (AuCrypto) [+] EHashType::eSHA2_48_384 [+] EHashType::eSHA2_64_512 [+] EHashType::eSHA3_28_224 [+] EHashType::eSHA3_32_256 [+] EHashType::eSHA3_48_384 [+] EHashType::eSHA3_64_512 [*] (IRandomDevice) class -> struct [*] Bugfix: cast in Promise<SuccessValue_t, ErrorValue_t>::WriteIntoError [+] Missing AuHashing namespace alias [*] Time util: pad ms when fraction of a second to 3 digits
433 lines
12 KiB
C++
433 lines
12 KiB
C++
/***
|
|
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
|
|
|
File: HashStream.cpp
|
|
Date: 2021-6-12
|
|
Author: Reece
|
|
***/
|
|
#include <Source/RuntimeInternal.hpp>
|
|
#include <tomcrypt.h>
|
|
#include "HashStream.hpp"
|
|
|
|
namespace Aurora::Hashing
|
|
{
|
|
HashStream::HashStream(EHashType type) : type_(type)
|
|
{
|
|
Init();
|
|
}
|
|
|
|
void HashStream::Ingest(const Memory::MemoryViewRead &input)
|
|
{
|
|
if (this->bFinished_)
|
|
{
|
|
return;
|
|
}
|
|
|
|
auto buffer = reinterpret_cast<const unsigned char *>(input.ptr);
|
|
auto len = input.length;
|
|
|
|
switch (this->type_)
|
|
{
|
|
case EHashType::eMD4:
|
|
md4_process(&this->state_, buffer, len);
|
|
break;
|
|
case EHashType::eMD5:
|
|
md5_process(&this->state_, buffer, len);
|
|
break;
|
|
case EHashType::eSHA1:
|
|
sha1_process(&this->state_, buffer, len);
|
|
break;
|
|
case EHashType::eSHA2_32:
|
|
sha256_process(&this->state_, buffer, len);
|
|
break;
|
|
case EHashType::eSHA2_48:
|
|
sha384_process(&this->state_, buffer, len);
|
|
break;
|
|
case EHashType::eSHA2_64:
|
|
sha512_process(&this->state_, buffer, len);
|
|
break;
|
|
case EHashType::eSHA3_28:
|
|
case EHashType::eSHA3_48:
|
|
case EHashType::eSHA3_32:
|
|
case EHashType::eSHA3_64:
|
|
sha3_process(&this->state_, buffer, len);
|
|
break;
|
|
case EHashType::eTiger:
|
|
tiger_process(&this->state_, buffer, len);
|
|
break;
|
|
case EHashType::eRMD128:
|
|
rmd128_process(&this->state_, buffer, len);
|
|
break;
|
|
case EHashType::eRMD160:
|
|
rmd160_process(&this->state_, buffer, len);
|
|
break;
|
|
case EHashType::eRMD256:
|
|
rmd256_process(&this->state_, buffer, len);
|
|
break;
|
|
case EHashType::eRMD320:
|
|
rmd320_process(&this->state_, buffer, len);
|
|
break;
|
|
}
|
|
}
|
|
|
|
AuUInt8 const* HashStream::GetBytes(AuUInt32 &length)
|
|
{
|
|
switch (this->type_)
|
|
{
|
|
case EHashType::eMD4:
|
|
length = 16;
|
|
if (!AuExchange(this->bFinished_, true))
|
|
{
|
|
md4_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
|
|
}
|
|
return this->buffer_;
|
|
|
|
case EHashType::eMD5:
|
|
length = 16;
|
|
if (!AuExchange(this->bFinished_, true))
|
|
{
|
|
md5_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
|
|
}
|
|
return this->buffer_;
|
|
|
|
case EHashType::eSHA1:
|
|
length = 20;
|
|
if (!AuExchange(this->bFinished_, true))
|
|
{
|
|
sha1_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
|
|
}
|
|
return this->buffer_;
|
|
|
|
case EHashType::eSHA2_48:
|
|
length = 48;
|
|
if (!AuExchange(this->bFinished_, true))
|
|
{
|
|
sha384_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
|
|
}
|
|
return this->buffer_;
|
|
|
|
case EHashType::eSHA2_32:
|
|
length = 32;
|
|
if (!AuExchange(this->bFinished_, true))
|
|
{
|
|
sha256_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
|
|
}
|
|
return this->buffer_;
|
|
|
|
case EHashType::eSHA2_64:
|
|
length = 64;
|
|
if (!AuExchange(this->bFinished_, true))
|
|
{
|
|
sha512_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
|
|
}
|
|
return this->buffer_;
|
|
|
|
case EHashType::eSHA3_28:
|
|
length = 28;
|
|
if (!AuExchange(this->bFinished_, true))
|
|
{
|
|
sha3_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
|
|
}
|
|
return this->buffer_;
|
|
|
|
case EHashType::eSHA3_48:
|
|
length = 48;
|
|
if (!AuExchange(this->bFinished_, true))
|
|
{
|
|
sha3_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
|
|
}
|
|
return this->buffer_;
|
|
|
|
case EHashType::eSHA3_32:
|
|
length = 32;
|
|
if (!AuExchange(this->bFinished_, true))
|
|
{
|
|
sha3_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
|
|
}
|
|
return this->buffer_;
|
|
|
|
case EHashType::eSHA3_64:
|
|
length = 64;
|
|
if (!AuExchange(this->bFinished_, true))
|
|
{
|
|
sha3_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
|
|
}
|
|
return this->buffer_;
|
|
|
|
case EHashType::eTiger:
|
|
length = 24;
|
|
if (!AuExchange(this->bFinished_, true))
|
|
{
|
|
tiger_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
|
|
}
|
|
return this->buffer_;
|
|
|
|
case EHashType::eRMD128:
|
|
length = 16;
|
|
if (!AuExchange(this->bFinished_, true))
|
|
{
|
|
rmd128_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
|
|
}
|
|
return this->buffer_;
|
|
|
|
case EHashType::eRMD160:
|
|
length = 20;
|
|
if (!AuExchange(this->bFinished_, true))
|
|
{
|
|
rmd160_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
|
|
}
|
|
return this->buffer_;
|
|
|
|
case EHashType::eRMD256:
|
|
length = 32;
|
|
if (!AuExchange(this->bFinished_, true))
|
|
{
|
|
rmd256_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
|
|
}
|
|
return this->buffer_;
|
|
|
|
case EHashType::eRMD320:
|
|
length = 40;
|
|
|
|
if (!AuExchange(this->bFinished_, true))
|
|
{
|
|
rmd256_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
|
|
}
|
|
return this->buffer_;
|
|
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
AuMemoryViewRead HashStream::Finalize()
|
|
{
|
|
AuUInt32 length;
|
|
auto begin = GetBytes(length);
|
|
return AuMemoryViewRead(begin, length);
|
|
}
|
|
|
|
Memory::MemoryViewRead HashStream::PeekFinalize()
|
|
{
|
|
if (this->bFinished_)
|
|
{
|
|
return this->Finalize();
|
|
}
|
|
|
|
hash_state state;
|
|
AuMemcpy(&state, &this->state_, sizeof(state));
|
|
auto view = this->Finalize();
|
|
AuMemcpy(&this->state_, &state, sizeof(state));
|
|
this->bFinished_ = false;
|
|
|
|
return view;
|
|
}
|
|
|
|
AuResult<AuMemoryViewRead> HashStream::Export()
|
|
{
|
|
// Defer to HASH_PROCESS defined in the private libtomcrypt header
|
|
|
|
//this->state_.name.length | bits processed
|
|
|
|
#define ADD_EXPORT(name) \
|
|
if (this->state_.name.curlen) \
|
|
{ \
|
|
return {}; \
|
|
} \
|
|
return AuMemoryViewRead {this->state_.name.state, sizeof(this->state_.name.state)};
|
|
|
|
switch (this->type_)
|
|
{
|
|
case EHashType::eMD4:
|
|
ADD_EXPORT(md4);
|
|
|
|
case EHashType::eMD5:
|
|
ADD_EXPORT(md5);
|
|
|
|
case EHashType::eSHA1:
|
|
ADD_EXPORT(sha1);
|
|
|
|
case EHashType::eSHA2_32:
|
|
ADD_EXPORT(sha256);
|
|
|
|
case EHashType::eSHA2_48:
|
|
case EHashType::eSHA2_64:
|
|
ADD_EXPORT(sha512);
|
|
|
|
case EHashType::eSHA3_28:
|
|
case EHashType::eSHA3_48:
|
|
case EHashType::eSHA3_32:
|
|
case EHashType::eSHA3_64:
|
|
{
|
|
if (this->state_.sha3.byte_index)
|
|
{
|
|
return {};
|
|
}
|
|
|
|
return AuMemoryViewRead(this->state_.sha3.s, this->state_.sha3.s + (8 * this->state_.sha3.word_index));
|
|
}
|
|
|
|
case EHashType::eTiger:
|
|
ADD_EXPORT(tiger);
|
|
|
|
case EHashType::eRMD128:
|
|
ADD_EXPORT(rmd128);
|
|
|
|
case EHashType::eRMD160:
|
|
ADD_EXPORT(rmd160);
|
|
|
|
case EHashType::eRMD256:
|
|
ADD_EXPORT(rmd256);
|
|
|
|
case EHashType::eRMD320:
|
|
ADD_EXPORT(rmd320);
|
|
|
|
default:
|
|
return {};
|
|
}
|
|
#undef ADD_EXPORT
|
|
}
|
|
|
|
bool HashStream::Import(const Memory::MemoryViewRead &view)
|
|
{
|
|
this->bFinished_ = false;
|
|
|
|
#define ADD_IMPORT(name) \
|
|
if (sizeof(this->state_.name.state) != view.length) \
|
|
{ \
|
|
SysPushErrorCrypt("Invalid hash state length -> mixed ciphers?"); \
|
|
return false; \
|
|
} \
|
|
AuMemset(&this->state_, 0, sizeof(this->state_)); \
|
|
AuMemcpy(this->state_.name.state, view.ptr, sizeof(this->state_.name.state)); \
|
|
return true;
|
|
|
|
switch (this->type_)
|
|
{
|
|
case EHashType::eMD4:
|
|
ADD_IMPORT(md4);
|
|
|
|
case EHashType::eMD5:
|
|
ADD_IMPORT(md5);
|
|
|
|
case EHashType::eSHA1:
|
|
ADD_IMPORT(sha1);
|
|
|
|
case EHashType::eSHA2_32:
|
|
ADD_IMPORT(sha256);
|
|
|
|
case EHashType::eSHA2_48:
|
|
case EHashType::eSHA2_64:
|
|
ADD_IMPORT(sha512);
|
|
|
|
case EHashType::eSHA3_28:
|
|
case EHashType::eSHA3_48:
|
|
case EHashType::eSHA3_32:
|
|
case EHashType::eSHA3_64:
|
|
{
|
|
if (this->state_.sha3.byte_index)
|
|
{
|
|
return {};
|
|
}
|
|
|
|
if (sizeof(this->state_.sha3.s) < view.length)
|
|
{
|
|
return {};
|
|
}
|
|
|
|
AuMemcpy(this->state_.sha3.s, view.ptr, view.length);
|
|
this->state_.sha3.word_index = view.length / 8;
|
|
return true;
|
|
}
|
|
|
|
case EHashType::eTiger:
|
|
ADD_IMPORT(tiger);
|
|
|
|
case EHashType::eRMD128:
|
|
ADD_IMPORT(rmd128);
|
|
|
|
case EHashType::eRMD160:
|
|
ADD_IMPORT(rmd160);
|
|
|
|
case EHashType::eRMD256:
|
|
ADD_IMPORT(rmd256);
|
|
|
|
case EHashType::eRMD320:
|
|
ADD_IMPORT(rmd320);
|
|
|
|
default:
|
|
return false;
|
|
}
|
|
|
|
#undef ADD_IMPORT
|
|
}
|
|
|
|
void HashStream::Reset()
|
|
{
|
|
Init();
|
|
}
|
|
|
|
void HashStream::Init()
|
|
{
|
|
this->bFinished_ = false;
|
|
AuMemset(&this->state_, 0, sizeof(this->state_));
|
|
|
|
switch (this->type_)
|
|
{
|
|
case EHashType::eMD4:
|
|
md4_init(&this->state_);
|
|
break;
|
|
case EHashType::eMD5:
|
|
md5_init(&this->state_);
|
|
break;
|
|
case EHashType::eSHA1:
|
|
sha1_init(&this->state_);
|
|
break;
|
|
case EHashType::eSHA2_32:
|
|
sha256_init(&this->state_);
|
|
break;
|
|
case EHashType::eSHA2_48:
|
|
sha384_init(&this->state_);
|
|
break;
|
|
case EHashType::eSHA2_64:
|
|
sha512_init(&this->state_);
|
|
break;
|
|
case EHashType::eSHA3_28:
|
|
sha3_224_init(&this->state_);
|
|
break;
|
|
case EHashType::eSHA3_32:
|
|
sha3_256_init(&this->state_);
|
|
break;
|
|
case EHashType::eSHA3_48:
|
|
sha3_384_init(&this->state_);
|
|
break;
|
|
case EHashType::eSHA3_64:
|
|
sha3_512_init(&this->state_);
|
|
break;
|
|
case EHashType::eTiger:
|
|
tiger_init(&this->state_);
|
|
break;
|
|
case EHashType::eRMD128:
|
|
rmd128_init(&this->state_);
|
|
break;
|
|
case EHashType::eRMD160:
|
|
rmd160_init(&this->state_);
|
|
break;
|
|
case EHashType::eRMD256:
|
|
rmd256_init(&this->state_);
|
|
break;
|
|
case EHashType::eRMD320:
|
|
rmd320_init(&this->state_);
|
|
break;
|
|
}
|
|
}
|
|
|
|
AUKN_SYM IHashStream *HashStreamNew(EHashType type)
|
|
{
|
|
return _new HashStream(type);
|
|
}
|
|
|
|
AUKN_SYM void HashStreamRelease(IHashStream *stream)
|
|
{
|
|
AuSafeDelete<HashStream*>(stream);
|
|
}
|
|
} |