318 lines
8.9 KiB
C++
318 lines
8.9 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->finished_)
|
|
{
|
|
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_64:
|
|
sha512_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->finished_, true))
|
|
{
|
|
md4_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
|
|
}
|
|
return this->buffer_;
|
|
|
|
case EHashType::eMD5:
|
|
length = 16;
|
|
if (!AuExchange(this->finished_, true))
|
|
{
|
|
md5_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
|
|
}
|
|
return this->buffer_;
|
|
|
|
case EHashType::eSHA1:
|
|
length = 20;
|
|
if (!AuExchange(this->finished_, true))
|
|
{
|
|
sha1_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
|
|
}
|
|
return this->buffer_;
|
|
|
|
case EHashType::eSHA2_32:
|
|
length = 32;
|
|
if (!AuExchange(this->finished_, true))
|
|
{
|
|
sha256_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
|
|
}
|
|
return this->buffer_;
|
|
|
|
case EHashType::eSHA2_64:
|
|
length = 64;
|
|
if (!AuExchange(this->finished_, true))
|
|
{
|
|
sha512_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
|
|
}
|
|
return this->buffer_;
|
|
|
|
case EHashType::eTiger:
|
|
length = 24;
|
|
if (!AuExchange(this->finished_, true))
|
|
{
|
|
tiger_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
|
|
}
|
|
return this->buffer_;
|
|
|
|
case EHashType::eRMD128:
|
|
length = 16;
|
|
if (!AuExchange(this->finished_, true))
|
|
{
|
|
rmd128_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
|
|
}
|
|
return this->buffer_;
|
|
|
|
case EHashType::eRMD160:
|
|
length = 20;
|
|
if (!AuExchange(this->finished_, true))
|
|
{
|
|
rmd160_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
|
|
}
|
|
return this->buffer_;
|
|
|
|
case EHashType::eRMD256:
|
|
length = 32;
|
|
if (!AuExchange(this->finished_, true))
|
|
{
|
|
rmd256_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
|
|
}
|
|
return this->buffer_;
|
|
|
|
case EHashType::eRMD320:
|
|
length = 40;
|
|
|
|
if (!AuExchange(this->finished_, 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);
|
|
}
|
|
|
|
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_64:
|
|
ADD_EXPORT(sha512);
|
|
|
|
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->finished_ = 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_64:
|
|
ADD_IMPORT(sha512);
|
|
|
|
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->finished_ = 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_64:
|
|
sha512_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);
|
|
}
|
|
} |