8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-02-02 10:00:38 +01:00

Moved cryptographic hashes to separate function crypt_hash(), crc32 - into function hash()

This commit is contained in:
AlexPeshkoff 2020-08-26 18:46:53 +03:00
parent 9900e56cbc
commit e9f3eb360d
8 changed files with 164 additions and 121 deletions

View File

@ -361,18 +361,26 @@ Example:
select cot(x) from y; select cot(x) from y;
----- ----------
CRC32 CRYPT_HASH
----- ----------
Function: Function:
Returns CRC-32 with the polynomial 0x04C11DB7. Accepts argument of any type. Returns a cryptograpic hash of an argument using a specified algorithm.
Format: Format:
CRC32( <any value> ) CRYPT_HASH( <any value> USING <algorithm> )
algorithm ::= { MD5 | SHA1 | SHA256 | SHA512 }
Important:
- This function returns VARCHAR strings with OCTETS charset with length depended on algorithm.
- MD5 and SHA1 algorithms are not recommended for use due to known severe issues, that algorithms
are provided ONLY for backward compatibility.
Example: Example:
select crc32(job_title) from job; select crypt_hash(x using sha256) from y;
------- -------
@ -560,21 +568,25 @@ HASH
---- ----
Function: Function:
Returns a HASH of a string using a specified algorithm. Returns a hash of an argument using a specified algorithm.
Format: Format:
HASH( <string> [ USING <algorithm> ] ) HASH( <any value> [ USING <algorithm> ] )
algorithm ::= { MD5 | SHA1 | SHA256 | SHA512 } algorithm ::= { CRC32 }
Important: Important:
- The syntax without USING is very discouraged and maintained for backward compatibility. - The syntax without USING is very discouraged and maintained for backward compatibility.
It returns a 64 bit integer and produces very bad hashes that easily result in collisions. It returns a 64 bit integer and produces very bad hashes that easily result in collisions.
- The syntax with USING is introduced in FB 4.0 and returns VARCHAR strings with OCTETS charset.
- The syntax with USING is introduced in FB 4.0 and returns an integer of appropriate size.
- Implemented in firebird CRC32 is using polynomial 0x04C11DB7.
Example: Example:
select hash(x) from y; select hash(x) from y;
select hash(x using sha256) from y; select hash(x using crc32) from y;
----------------------------- -----------------------------

View File

@ -22,6 +22,7 @@
#include "firebird.h" #include "firebird.h"
#include "../common/classes/Hash.h" #include "../common/classes/Hash.h"
#include "../common/dsc.h"
#if defined(_M_IX86) || defined(_M_X64) || defined(__x86_64__) || defined(__i386__) #if defined(_M_IX86) || defined(_M_X64) || defined(__x86_64__) || defined(__i386__)
#ifdef _MSC_VER #ifdef _MSC_VER
@ -126,8 +127,7 @@ void WeakHashContext::update(const void* data, FB_SIZE_T length)
} }
} }
void WeakHashContext::finish(Buffer& result) void WeakHashContext::finish(dsc& result)
{ {
UCHAR* resultBuffer = result.getBuffer(sizeof(hashNumber)); result.makeInt64(0, &hashNumber);
memcpy(resultBuffer, &hashNumber, sizeof(hashNumber));
} }

View File

@ -30,6 +30,8 @@
#include "../common/classes/array.h" #include "../common/classes/array.h"
struct dsc;
namespace Firebird namespace Firebird
{ {
template <typename K> template <typename K>
@ -341,12 +343,8 @@ namespace Firebird
} }
}; };
class HashContext class HashContext
{ {
public:
typedef HalfStaticArray<UCHAR, 256> Buffer;
public: public:
virtual ~HashContext() virtual ~HashContext()
{ {
@ -354,14 +352,14 @@ namespace Firebird
public: public:
virtual void update(const void* data, FB_SIZE_T length) = 0; virtual void update(const void* data, FB_SIZE_T length) = 0;
virtual void finish(Buffer& result) = 0; virtual void finish(dsc& result) = 0;
}; };
class WeakHashContext FB_FINAL : public HashContext class WeakHashContext FB_FINAL : public HashContext
{ {
public: public:
virtual void update(const void* data, FB_SIZE_T length); virtual void update(const void* data, FB_SIZE_T length);
virtual void finish(Buffer& result); virtual void finish(dsc& result);
private: private:
SINT64 hashNumber = 0; SINT64 hashNumber = 0;
@ -383,11 +381,12 @@ namespace Firebird
public: public:
virtual void update(const void* data, FB_SIZE_T length); virtual void update(const void* data, FB_SIZE_T length);
virtual void finish(Buffer& result); virtual void finish(dsc& result);
private: private:
const Descriptor* descriptor; const Descriptor* descriptor;
State* statePtr; State* statePtr;
UCharBuffer buffer;
}; };
class Md5HashContext FB_FINAL : public LibTomCryptHashContext class Md5HashContext FB_FINAL : public LibTomCryptHashContext
@ -413,6 +412,22 @@ namespace Firebird
public: public:
Sha512HashContext(MemoryPool& pool); Sha512HashContext(MemoryPool& pool);
}; };
class Crc32HashContext FB_FINAL : public HashContext
{
public:
Crc32HashContext(MemoryPool& pool);
~Crc32HashContext();
virtual void update(const void* data, FB_SIZE_T length);
virtual void finish(dsc& result);
private:
struct State;
State* statePtr;
SLONG hash;
};
} // namespace Firebird } // namespace Firebird
#endif // CLASSES_HASH_H #endif // CLASSES_HASH_H

View File

@ -24,6 +24,8 @@
#include "firebird.h" #include "firebird.h"
#include "../common/classes/Hash.h" #include "../common/classes/Hash.h"
#include "../common/dsc.h"
#include "../intl/charsets.h"
#if !defined(__GNUC__) || defined(__clang__) #if !defined(__GNUC__) || defined(__clang__)
#define LTC_NO_ASM // disable ASM in tomcrypt headers #define LTC_NO_ASM // disable ASM in tomcrypt headers
@ -45,9 +47,10 @@ struct LibTomCryptHashContext::State
LibTomCryptHashContext::LibTomCryptHashContext(MemoryPool& pool, const Descriptor* aDescriptor) LibTomCryptHashContext::LibTomCryptHashContext(MemoryPool& pool, const Descriptor* aDescriptor)
: descriptor(aDescriptor) : descriptor(aDescriptor),
statePtr(FB_NEW_POOL(pool) State),
buffer(pool)
{ {
statePtr = FB_NEW_POOL(pool) State();
descriptor->tcDesc->init(&statePtr->tcState); descriptor->tcDesc->init(&statePtr->tcState);
} }
@ -61,10 +64,11 @@ void LibTomCryptHashContext::update(const void* data, FB_SIZE_T length)
descriptor->tcDesc->process(&statePtr->tcState, static_cast<const UCHAR*>(data), length); descriptor->tcDesc->process(&statePtr->tcState, static_cast<const UCHAR*>(data), length);
} }
void LibTomCryptHashContext::finish(Buffer& result) void LibTomCryptHashContext::finish(dsc& result)
{ {
unsigned char* hashResult = result.getBuffer(descriptor->tcDesc->hashsize); unsigned char* hashResult = buffer.getBuffer(descriptor->tcDesc->hashsize);
descriptor->tcDesc->done(&statePtr->tcState, hashResult); descriptor->tcDesc->done(&statePtr->tcState, hashResult);
result.makeText(descriptor->tcDesc->hashsize, CS_BINARY, hashResult);
} }
@ -98,3 +102,37 @@ Sha512HashContext::Sha512HashContext(MemoryPool& pool)
: LibTomCryptHashContext(pool, &sha512Descriptor) : LibTomCryptHashContext(pool, &sha512Descriptor)
{ {
} }
struct Crc32HashContext::State
{
State()
{
crc32_init(&ctx);
}
crc32_state ctx;
};
Crc32HashContext::Crc32HashContext(MemoryPool& pool)
{
statePtr = FB_NEW_POOL(pool) State();
}
Crc32HashContext::~Crc32HashContext()
{
delete statePtr;
}
void Crc32HashContext::update(const void* data, FB_SIZE_T length)
{
crc32_update(&statePtr->ctx, static_cast<const UCHAR*>(data), length);
}
void Crc32HashContext::finish(dsc& result)
{
crc32_finish(&statePtr->ctx, &hash, sizeof hash);
result.makeLong(0, &hash);
}

View File

@ -145,9 +145,9 @@ static const TOK tokens[] =
{TOK_COUNTER, "COUNTER", true}, {TOK_COUNTER, "COUNTER", true},
{TOK_COVAR_POP, "COVAR_POP", false}, {TOK_COVAR_POP, "COVAR_POP", false},
{TOK_COVAR_SAMP, "COVAR_SAMP", false}, {TOK_COVAR_SAMP, "COVAR_SAMP", false},
{TOK_CRC32, "CRC32", true},
{TOK_CREATE, "CREATE", false}, {TOK_CREATE, "CREATE", false},
{TOK_CROSS, "CROSS", false}, {TOK_CROSS, "CROSS", false},
{TOK_CRYPT_HASH, "CRYPT_HASH", true},
{TOK_CSTRING, "CSTRING", true}, {TOK_CSTRING, "CSTRING", true},
{TOK_CTR_BIG_ENDIAN, "CTR_BIG_ENDIAN", true}, {TOK_CTR_BIG_ENDIAN, "CTR_BIG_ENDIAN", true},
{TOK_CTR_LENGTH, "CTR_LENGTH", true}, {TOK_CTR_LENGTH, "CTR_LENGTH", true},

View File

@ -1 +1 @@
60 shift/reduce conflicts, 17 reduce/reduce conflicts. 61 shift/reduce conflicts, 17 reduce/reduce conflicts.

View File

@ -457,7 +457,6 @@ using namespace Firebird;
%token <metaNamePtr> COS %token <metaNamePtr> COS
%token <metaNamePtr> COSH %token <metaNamePtr> COSH
%token <metaNamePtr> COT %token <metaNamePtr> COT
%token <metaNamePtr> CRC32
%token <metaNamePtr> DATEADD %token <metaNamePtr> DATEADD
%token <metaNamePtr> DATEDIFF %token <metaNamePtr> DATEDIFF
%token <metaNamePtr> DECODE %token <metaNamePtr> DECODE
@ -599,6 +598,7 @@ using namespace Firebird;
%token <metaNamePtr> COMPARE_DECFLOAT %token <metaNamePtr> COMPARE_DECFLOAT
%token <metaNamePtr> CONSISTENCY %token <metaNamePtr> CONSISTENCY
%token <metaNamePtr> COUNTER %token <metaNamePtr> COUNTER
%token <metaNamePtr> CRYPT_HASH
%token <metaNamePtr> CTR_BIG_ENDIAN %token <metaNamePtr> CTR_BIG_ENDIAN
%token <metaNamePtr> CTR_LENGTH %token <metaNamePtr> CTR_LENGTH
%token <metaNamePtr> CTR_LITTLE_ENDIAN %token <metaNamePtr> CTR_LITTLE_ENDIAN
@ -8067,7 +8067,6 @@ system_function_std_syntax
| COS | COS
| COSH | COSH
| COT | COT
| CRC32
| EXP | EXP
| FLOOR | FLOOR
| GEN_UUID | GEN_UUID
@ -8152,7 +8151,7 @@ system_function_special_syntax
} }
| HASH '(' value ')' | HASH '(' value ')'
{ $$ = newNode<SysFuncCallNode>(*$1, newNode<ValueListNode>($3)); } { $$ = newNode<SysFuncCallNode>(*$1, newNode<ValueListNode>($3)); }
| HASH '(' value USING valid_symbol_name ')' | hash_func '(' value USING valid_symbol_name ')'
{ {
$$ = newNode<SysFuncCallNode>(*$1, $$ = newNode<SysFuncCallNode>(*$1,
newNode<ValueListNode>($3)->add(MAKE_str_constant(newIntlString($5->c_str()), CS_ASCII))); newNode<ValueListNode>($3)->add(MAKE_str_constant(newIntlString($5->c_str()), CS_ASCII)));
@ -8211,6 +8210,11 @@ system_function_special_syntax
} }
; ;
%type <metaNamePtr> hash_func
hash_func
: HASH | CRYPT_HASH
;
%type <metaNamePtr> rsa_encrypt_decrypt %type <metaNamePtr> rsa_encrypt_decrypt
rsa_encrypt_decrypt rsa_encrypt_decrypt
: RSA_DECRYPT | RSA_ENCRYPT : RSA_DECRYPT | RSA_ENCRYPT
@ -8948,7 +8952,7 @@ non_reserved_word
| COMPARE_DECFLOAT | COMPARE_DECFLOAT
| CONNECTIONS | CONNECTIONS
| CONSISTENCY | CONSISTENCY
| CRC32 | CRYPT_HASH
| CTR_BIG_ENDIAN | CTR_BIG_ENDIAN
| CTR_LENGTH | CTR_LENGTH
| CTR_LITTLE_ENDIAN | CTR_LITTLE_ENDIAN

View File

@ -125,7 +125,7 @@ struct HashAlgorithmDescriptor
USHORT length; USHORT length;
HashContext* (*create)(MemoryPool&); HashContext* (*create)(MemoryPool&);
static const HashAlgorithmDescriptor* find(const char* name); static const HashAlgorithmDescriptor* find(const HashAlgorithmDescriptor** hashDescriptor, const MetaName name);
}; };
template <typename T> template <typename T>
@ -149,21 +149,25 @@ struct HashAlgorithmDescriptorFactory
template <typename T> HashAlgorithmDescriptor HashAlgorithmDescriptorFactory<T>::desc; template <typename T> HashAlgorithmDescriptor HashAlgorithmDescriptorFactory<T>::desc;
static const HashAlgorithmDescriptor* hashAlgorithmDescriptors[] = { static const HashAlgorithmDescriptor* cryptHashAlgorithmDescriptors[] = {
HashAlgorithmDescriptorFactory<Md5HashContext>::getInstance("MD5", 16), HashAlgorithmDescriptorFactory<Md5HashContext>::getInstance("MD5", 16),
HashAlgorithmDescriptorFactory<Sha1HashContext>::getInstance("SHA1", 20), HashAlgorithmDescriptorFactory<Sha1HashContext>::getInstance("SHA1", 20),
HashAlgorithmDescriptorFactory<Sha256HashContext>::getInstance("SHA256", 32), HashAlgorithmDescriptorFactory<Sha256HashContext>::getInstance("SHA256", 32),
HashAlgorithmDescriptorFactory<Sha512HashContext>::getInstance("SHA512", 64) HashAlgorithmDescriptorFactory<Sha512HashContext>::getInstance("SHA512", 64),
nullptr
}; };
const HashAlgorithmDescriptor* HashAlgorithmDescriptor::find(const char* name) static const HashAlgorithmDescriptor* hashAlgorithmDescriptors[] = {
{ HashAlgorithmDescriptorFactory<Crc32HashContext>::getInstance("CRC32", 4),
unsigned count = FB_NELEM(hashAlgorithmDescriptors); nullptr
};
for (unsigned i = 0; i < count; ++i) const HashAlgorithmDescriptor* HashAlgorithmDescriptor::find(const HashAlgorithmDescriptor** hashDescriptor, const MetaName name)
{
for (; *hashDescriptor; hashDescriptor++)
{ {
if (strcmp(name, hashAlgorithmDescriptors[i]->name) == 0) if (name == (*hashDescriptor)->name)
return hashAlgorithmDescriptors[i]; return *hashDescriptor;
} }
status_exception::raise(Arg::Gds(isc_sysf_invalid_hash_algorithm) << name); status_exception::raise(Arg::Gds(isc_sysf_invalid_hash_algorithm) << name);
@ -171,6 +175,22 @@ const HashAlgorithmDescriptor* HashAlgorithmDescriptor::find(const char* name)
} }
const HashAlgorithmDescriptor* getHashAlgorithmDesc(thread_db* tdbb, const SysFunction* function, const dsc* algDsc, bool* cHash = nullptr)
{
bool cryptHash = (strcmp(function->name, "CRYPT_HASH") == 0);
if (cHash)
*cHash = cryptHash;
if (!algDsc->dsc_address || !algDsc->isText())
status_exception::raise(Arg::Gds(isc_sysf_invalid_hash_algorithm) << "<not a string constant>");
MetaName algorithmName;
MOV_get_metaname(tdbb, algDsc, algorithmName);
return HashAlgorithmDescriptor::find(cryptHash ? cryptHashAlgorithmDescriptors : hashAlgorithmDescriptors, algorithmName);
}
// constants // constants
const int oneDay = 86400; const int oneDay = 86400;
const unsigned getContextLen = 255; const unsigned getContextLen = 255;
@ -200,6 +220,7 @@ void setParamsDateDiff(DataTypeUtilBase* dataTypeUtil, const SysFunction* functi
void setParamsEncrypt(DataTypeUtilBase*, const SysFunction*, int argsCount, dsc** args); void setParamsEncrypt(DataTypeUtilBase*, const SysFunction*, int argsCount, dsc** args);
void setParamsFirstLastDay(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, int argsCount, dsc** args); void setParamsFirstLastDay(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, int argsCount, dsc** args);
void setParamsGetSetContext(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, int argsCount, dsc** args); void setParamsGetSetContext(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, int argsCount, dsc** args);
void setParamsHash(DataTypeUtilBase*, const SysFunction*, int argsCount, dsc** args);
void setParamsMakeDbkey(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, int argsCount, dsc** args); void setParamsMakeDbkey(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, int argsCount, dsc** args);
void setParamsOverlay(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, int argsCount, dsc** args); void setParamsOverlay(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, int argsCount, dsc** args);
void setParamsPosition(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, int argsCount, dsc** args); void setParamsPosition(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, int argsCount, dsc** args);
@ -268,7 +289,6 @@ dsc* evlBin(thread_db* tdbb, const SysFunction* function, const NestValueArray&
dsc* evlBinShift(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure); dsc* evlBinShift(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure);
dsc* evlCeil(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure); dsc* evlCeil(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure);
dsc* evlCharToUuid(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure); dsc* evlCharToUuid(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure);
dsc* evlCrc32(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure);
dsc* evlDateAdd(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure); dsc* evlDateAdd(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure);
dsc* evlDateDiff(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure); dsc* evlDateDiff(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure);
dsc* evlDecode64(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure); dsc* evlDecode64(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure);
@ -761,6 +781,14 @@ void setParamsGetSetContext(DataTypeUtilBase*, const SysFunction*, int argsCount
} }
void setParamsHash(DataTypeUtilBase*, const SysFunction*, int argsCount, dsc** args)
{
fb_assert(argsCount == 1 || argsCount == 2);
setParamVarying(args[0], ttype_binary);
}
void setParamsMakeDbkey(DataTypeUtilBase*, const SysFunction*, int argsCount, dsc** args) void setParamsMakeDbkey(DataTypeUtilBase*, const SysFunction*, int argsCount, dsc** args)
{ {
// MAKE_DBKEY ( REL_NAME | REL_ID, RECNUM [, DPNUM [, PPNUM] ] ) // MAKE_DBKEY ( REL_NAME | REL_ID, RECNUM [, DPNUM [, PPNUM] ] )
@ -1275,13 +1303,22 @@ void makeHash(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc*
makeInt64Result(dataTypeUtil, function, result, argsCount, args); makeInt64Result(dataTypeUtil, function, result, argsCount, args);
else if (argsCount >= 2) else if (argsCount >= 2)
{ {
if (!args[1]->dsc_address || !args[1]->isText()) // not a constant bool cryptHash;
status_exception::raise(Arg::Gds(isc_sysf_invalid_hash_algorithm) << "<not a string constant>"); const HashAlgorithmDescriptor* d = getHashAlgorithmDesc(JRD_get_thread_data(), function, args[1], &cryptHash);
MetaName algorithmName; if (cryptHash)
MOV_get_metaname(JRD_get_thread_data(), args[1], algorithmName); result->makeVarying(d->length, ttype_binary);
else
result->makeVarying(HashAlgorithmDescriptor::find(algorithmName.c_str())->length, ttype_binary); {
switch(d->length)
{
case 4:
result->makeLong(0);
break;
default:
fb_assert(false);
}
}
result->setNullable(args[0]->isNullable()); result->setNullable(args[0]->isNullable());
} }
} }
@ -3330,50 +3367,6 @@ dsc* evlEncodeHex(thread_db* tdbb, const SysFunction* function, const NestValueA
return evlEncodeDecodeHex(tdbb, true, function, args, impure); return evlEncodeDecodeHex(tdbb, true, function, args, impure);
} }
dsc* evlCrc32(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, impure_value* impure)
{
crc32_state ctx;
crc32_init(&ctx);
const dsc* arg = EVL_expr(tdbb, tdbb->getRequest(), args[0]);
if (!arg) // return NULL if value is NULL
return NULL;
if (arg->isBlob())
{
blb* blob = blb::open2(tdbb, tdbb->getRequest()->req_transaction, reinterpret_cast<const bid*>(arg->dsc_address),
sizeof(streamBpb), streamBpb);
UCHAR buf[4096];
for(;;)
{
const unsigned l = blob->BLB_get_data(tdbb, buf, sizeof buf, false);
if (!l)
break;
crc32_update(&ctx, buf, l);
}
blob->BLB_close(tdbb);
}
else
{
unsigned len;
const UCHAR* ptr = CVT_get_bytes(arg, len);
crc32_update(&ctx, ptr, len);
}
SLONG hash;
crc32_finish(&ctx, &hash, sizeof hash);
dsc result;
result.makeLong(0, &hash);
EVL_make_value(tdbb, &result, impure);
return &impure->vlu_desc;
}
dsc* evlRsaEncryptDecrypt(thread_db* tdbb, const SysFunction* function, const NestValueArray& args, dsc* evlRsaEncryptDecrypt(thread_db* tdbb, const SysFunction* function, const NestValueArray& args,
impure_value* impure, bool encryptFlag) impure_value* impure, bool encryptFlag)
{ {
@ -4558,7 +4551,7 @@ dsc* evlGetTranCN(thread_db* tdbb, const SysFunction* function, const NestValueA
} }
dsc* evlHash(thread_db* tdbb, const SysFunction*, const NestValueArray& args, dsc* evlHash(thread_db* tdbb, const SysFunction* function, const NestValueArray& args,
impure_value* impure) impure_value* impure)
{ {
fb_assert(args.getCount() >= 1); fb_assert(args.getCount() >= 1);
@ -4578,12 +4571,8 @@ dsc* evlHash(thread_db* tdbb, const SysFunction*, const NestValueArray& args,
if (request->req_flags & req_null) // return NULL if algorithm is NULL if (request->req_flags & req_null) // return NULL if algorithm is NULL
return NULL; return NULL;
if (!algorithmDesc->isText()) const HashAlgorithmDescriptor* d = getHashAlgorithmDesc(tdbb, function, algorithmDesc);
status_exception::raise(Arg::Gds(isc_sysf_invalid_hash_algorithm) << "<not a string constant>"); hashContext.reset(d->create(pool));
MetaName algorithmName;
MOV_get_metaname(tdbb, algorithmDesc, algorithmName);
hashContext.reset(HashAlgorithmDescriptor::find(algorithmName.c_str())->create(pool));
} }
else else
{ {
@ -4607,29 +4596,14 @@ dsc* evlHash(thread_db* tdbb, const SysFunction*, const NestValueArray& args,
} }
else else
{ {
UCHAR* address; unsigned len;
MoveBuffer buffer; const UCHAR* ptr = CVT_get_bytes(value, len);
const ULONG length = MOV_make_string2(tdbb, value, value->getTextType(), &address, buffer, false); hashContext->update(ptr, len);
hashContext->update(address, length);
} }
HashContext::Buffer resultBuffer; dsc result;
hashContext->finish(resultBuffer); hashContext->finish(result);
EVL_make_value(tdbb, &result, impure);
if (args.getCount() >= 2)
{
dsc result;
result.makeText(resultBuffer.getCount(), ttype_binary, resultBuffer.begin());
EVL_make_value(tdbb, &result, impure);
}
else
{
fb_assert(resultBuffer.getCount() == sizeof(SINT64));
memcpy(&impure->vlu_misc.vlu_int64, resultBuffer.begin(), sizeof(SINT64));
// make descriptor for return value
impure->vlu_desc.makeInt64(0, &impure->vlu_misc.vlu_int64);
}
return &impure->vlu_desc; return &impure->vlu_desc;
} }
@ -6369,7 +6343,6 @@ const SysFunction SysFunction::functions[] =
{"ATAN2", 2, 2, setParamsDouble, makeDoubleResult, evlAtan2, NULL}, {"ATAN2", 2, 2, setParamsDouble, makeDoubleResult, evlAtan2, NULL},
{"BASE64_DECODE", 1, 1, NULL, makeDecode64, evlDecode64, NULL}, {"BASE64_DECODE", 1, 1, NULL, makeDecode64, evlDecode64, NULL},
{"BASE64_ENCODE", 1, 1, NULL, makeEncode64, evlEncode64, NULL}, {"BASE64_ENCODE", 1, 1, NULL, makeEncode64, evlEncode64, NULL},
{"CRC32", 1, 1, NULL, makeLongResult, evlCrc32, NULL},
{"BIN_AND", 2, -1, setParamsBin, makeBin, evlBin, (void*) funBinAnd}, {"BIN_AND", 2, -1, setParamsBin, makeBin, evlBin, (void*) funBinAnd},
{"BIN_NOT", 1, 1, setParamsBin, makeBin, evlBin, (void*) funBinNot}, {"BIN_NOT", 1, 1, setParamsBin, makeBin, evlBin, (void*) funBinNot},
{"BIN_OR", 2, -1, setParamsBin, makeBin, evlBin, (void*) funBinOr}, {"BIN_OR", 2, -1, setParamsBin, makeBin, evlBin, (void*) funBinOr},
@ -6385,6 +6358,7 @@ const SysFunction SysFunction::functions[] =
{"COS", 1, 1, setParamsDouble, makeDoubleResult, evlStdMath, (void*) trfCos}, {"COS", 1, 1, setParamsDouble, makeDoubleResult, evlStdMath, (void*) trfCos},
{"COSH", 1, 1, setParamsDouble, makeDoubleResult, evlStdMath, (void*) trfCosh}, {"COSH", 1, 1, setParamsDouble, makeDoubleResult, evlStdMath, (void*) trfCosh},
{"COT", 1, 1, setParamsDouble, makeDoubleResult, evlStdMath, (void*) trfCot}, {"COT", 1, 1, setParamsDouble, makeDoubleResult, evlStdMath, (void*) trfCot},
{"CRYPT_HASH", 2, 2, setParamsHash, makeHash, evlHash, NULL},
{"DATEADD", 3, 3, setParamsDateAdd, makeDateAdd, evlDateAdd, NULL}, {"DATEADD", 3, 3, setParamsDateAdd, makeDateAdd, evlDateAdd, NULL},
{"DATEDIFF", 3, 3, setParamsDateDiff, makeInt64Result, evlDateDiff, NULL}, {"DATEDIFF", 3, 3, setParamsDateDiff, makeInt64Result, evlDateDiff, NULL},
{"DECRYPT", 7, 7, setParamsEncrypt, makeDecrypt, evlDecrypt, NULL}, {"DECRYPT", 7, 7, setParamsEncrypt, makeDecrypt, evlDecrypt, NULL},
@ -6393,7 +6367,7 @@ const SysFunction SysFunction::functions[] =
{"FIRST_DAY", 2, 2, setParamsFirstLastDay, makeFirstLastDayResult, evlFirstLastDay, (void*) funFirstDay}, {"FIRST_DAY", 2, 2, setParamsFirstLastDay, makeFirstLastDayResult, evlFirstLastDay, (void*) funFirstDay},
{"FLOOR", 1, 1, setParamsDblDec, makeCeilFloor, evlFloor, NULL}, {"FLOOR", 1, 1, setParamsDblDec, makeCeilFloor, evlFloor, NULL},
{"GEN_UUID", 0, 0, NULL, makeUuid, evlGenUuid, NULL}, {"GEN_UUID", 0, 0, NULL, makeUuid, evlGenUuid, NULL},
{"HASH", 1, 2, NULL, makeHash, evlHash, NULL}, {"HASH", 1, 2, setParamsHash, makeHash, evlHash, NULL},
{"HEX_DECODE", 1, 1, NULL, makeDecodeHex, evlDecodeHex, NULL}, {"HEX_DECODE", 1, 1, NULL, makeDecodeHex, evlDecodeHex, NULL},
{"HEX_ENCODE", 1, 1, NULL, makeEncodeHex, evlEncodeHex, NULL}, {"HEX_ENCODE", 1, 1, NULL, makeEncodeHex, evlEncodeHex, NULL},
{"LAST_DAY", 2, 2, setParamsFirstLastDay, makeFirstLastDayResult, evlFirstLastDay, (void*) funLastDay}, {"LAST_DAY", 2, 2, setParamsFirstLastDay, makeFirstLastDayResult, evlFirstLastDay, (void*) funLastDay},