A few more updates to the digest functions.

This builds upon the previous commit to make Zeek compile on FIPS
systems.

This patch makes the changes a bit more aggressive. Instead of having a
number of different hash functions with different return values, we now
standardize on EVP_MD_CTX and just have one set of functions, to which
the hash algorithm that is desired is passed.

On the positive side, this enables us to support a wider range of hash
algorithm (and to easily add to them in the future).

I reimplemented the internal_md5 function - we don't support ebdic
systems in any case.

The md5/sha1 serialization functions are now also tested (I don't think
they were before).
This commit is contained in:
Johanna Amann 2019-01-24 09:19:29 -08:00
parent ffa6756255
commit 86161c85c4
9 changed files with 149 additions and 143 deletions

View file

@ -2,8 +2,6 @@
#include "bro-config.h" #include "bro-config.h"
#include <openssl/md5.h>
#include "EquivClass.h" #include "EquivClass.h"
#include "DFA.h" #include "DFA.h"
#include "digest.h" #include "digest.h"

View file

@ -79,12 +79,14 @@ bool HashVal::DoUnserialize(UnserialInfo* info)
MD5Val::MD5Val() : HashVal(md5_type) MD5Val::MD5Val() : HashVal(md5_type)
{ {
if ( IsValid() )
// prevent leaks...
EVP_MD_CTX_free(ctx);
} }
void MD5Val::digest(val_list& vlist, u_char result[MD5_DIGEST_LENGTH]) void MD5Val::digest(val_list& vlist, u_char result[MD5_DIGEST_LENGTH])
{ {
EVP_MD_CTX *h; EVP_MD_CTX* h = hash_init(Hash_MD5);
md5_init(&h);
loop_over_list(vlist, i) loop_over_list(vlist, i)
{ {
@ -92,17 +94,17 @@ void MD5Val::digest(val_list& vlist, u_char result[MD5_DIGEST_LENGTH])
if ( v->Type()->Tag() == TYPE_STRING ) if ( v->Type()->Tag() == TYPE_STRING )
{ {
const BroString* str = v->AsString(); const BroString* str = v->AsString();
md5_update(h, str->Bytes(), str->Len()); hash_update(h, str->Bytes(), str->Len());
} }
else else
{ {
ODesc d(DESC_BINARY); ODesc d(DESC_BINARY);
v->Describe(&d); v->Describe(&d);
md5_update(h, (const u_char *) d.Bytes(), d.Len()); hash_update(h, (const u_char *) d.Bytes(), d.Len());
} }
} }
md5_final(h, result); hash_final(h, result);
} }
void MD5Val::hmac(val_list& vlist, void MD5Val::hmac(val_list& vlist,
@ -119,7 +121,7 @@ void MD5Val::hmac(val_list& vlist,
bool MD5Val::DoInit() bool MD5Val::DoInit()
{ {
assert(! IsValid()); assert(! IsValid());
md5_init(&ctx); ctx = hash_init(Hash_MD5);
return true; return true;
} }
@ -128,7 +130,7 @@ bool MD5Val::DoFeed(const void* data, size_t size)
if ( ! IsValid() ) if ( ! IsValid() )
return false; return false;
md5_update(ctx, data, size); hash_update(ctx, data, size);
return true; return true;
} }
@ -138,7 +140,7 @@ StringVal* MD5Val::DoGet()
return val_mgr->GetEmptyString(); return val_mgr->GetEmptyString();
u_char digest[MD5_DIGEST_LENGTH]; u_char digest[MD5_DIGEST_LENGTH];
md5_final(ctx, digest); hash_final(ctx, digest);
return new StringVal(md5_digest_print(digest)); return new StringVal(md5_digest_print(digest));
} }
@ -146,12 +148,13 @@ IMPLEMENT_SERIAL(MD5Val, SER_MD5_VAL);
bool MD5Val::DoSerialize(SerialInfo* info) const bool MD5Val::DoSerialize(SerialInfo* info) const
{ {
MD5_CTX *md = (MD5_CTX *) EVP_MD_CTX_md_data(ctx);
DO_SERIALIZE(SER_MD5_VAL, HashVal); DO_SERIALIZE(SER_MD5_VAL, HashVal);
if ( ! IsValid() ) if ( ! IsValid() )
return true; return true;
MD5_CTX *md = (MD5_CTX *) EVP_MD_CTX_md_data(ctx);
if ( ! (SERIALIZE(md->A) && if ( ! (SERIALIZE(md->A) &&
SERIALIZE(md->B) && SERIALIZE(md->B) &&
SERIALIZE(md->C) && SERIALIZE(md->C) &&
@ -174,12 +177,14 @@ bool MD5Val::DoSerialize(SerialInfo* info) const
bool MD5Val::DoUnserialize(UnserialInfo* info) bool MD5Val::DoUnserialize(UnserialInfo* info)
{ {
MD5_CTX *md = (MD5_CTX *) EVP_MD_CTX_md_data(ctx);
DO_UNSERIALIZE(HashVal); DO_UNSERIALIZE(HashVal);
if ( ! IsValid() ) if ( ! IsValid() )
return true; return true;
ctx = hash_init(Hash_MD5);
MD5_CTX *md = (MD5_CTX *) EVP_MD_CTX_md_data(ctx);
if ( ! (UNSERIALIZE(&md->A) && if ( ! (UNSERIALIZE(&md->A) &&
UNSERIALIZE(&md->B) && UNSERIALIZE(&md->B) &&
UNSERIALIZE(&md->C) && UNSERIALIZE(&md->C) &&
@ -202,12 +207,14 @@ bool MD5Val::DoUnserialize(UnserialInfo* info)
SHA1Val::SHA1Val() : HashVal(sha1_type) SHA1Val::SHA1Val() : HashVal(sha1_type)
{ {
if ( IsValid() )
// prevent leaks...
EVP_MD_CTX_free(ctx);
} }
void SHA1Val::digest(val_list& vlist, u_char result[SHA_DIGEST_LENGTH]) void SHA1Val::digest(val_list& vlist, u_char result[SHA_DIGEST_LENGTH])
{ {
SHA_CTX h; EVP_MD_CTX* h = hash_init(Hash_SHA1);
sha1_init(&h);
loop_over_list(vlist, i) loop_over_list(vlist, i)
{ {
@ -215,23 +222,23 @@ void SHA1Val::digest(val_list& vlist, u_char result[SHA_DIGEST_LENGTH])
if ( v->Type()->Tag() == TYPE_STRING ) if ( v->Type()->Tag() == TYPE_STRING )
{ {
const BroString* str = v->AsString(); const BroString* str = v->AsString();
sha1_update(&h, str->Bytes(), str->Len()); hash_update(h, str->Bytes(), str->Len());
} }
else else
{ {
ODesc d(DESC_BINARY); ODesc d(DESC_BINARY);
v->Describe(&d); v->Describe(&d);
sha1_update(&h, (const u_char *) d.Bytes(), d.Len()); hash_update(h, (const u_char *) d.Bytes(), d.Len());
} }
} }
sha1_final(&h, result); hash_final(h, result);
} }
bool SHA1Val::DoInit() bool SHA1Val::DoInit()
{ {
assert(! IsValid()); assert(! IsValid());
sha1_init(&ctx); ctx = hash_init(Hash_SHA1);
return true; return true;
} }
@ -240,7 +247,7 @@ bool SHA1Val::DoFeed(const void* data, size_t size)
if ( ! IsValid() ) if ( ! IsValid() )
return false; return false;
sha1_update(&ctx, data, size); hash_update(ctx, data, size);
return true; return true;
} }
@ -250,7 +257,7 @@ StringVal* SHA1Val::DoGet()
return val_mgr->GetEmptyString(); return val_mgr->GetEmptyString();
u_char digest[SHA_DIGEST_LENGTH]; u_char digest[SHA_DIGEST_LENGTH];
sha1_final(&ctx, digest); hash_final(ctx, digest);
return new StringVal(sha1_digest_print(digest)); return new StringVal(sha1_digest_print(digest));
} }
@ -263,22 +270,24 @@ bool SHA1Val::DoSerialize(SerialInfo* info) const
if ( ! IsValid() ) if ( ! IsValid() )
return true; return true;
if ( ! (SERIALIZE(ctx.h0) && SHA_CTX *md = (SHA_CTX *) EVP_MD_CTX_md_data(ctx);
SERIALIZE(ctx.h1) &&
SERIALIZE(ctx.h2) && if ( ! (SERIALIZE(md->h0) &&
SERIALIZE(ctx.h3) && SERIALIZE(md->h1) &&
SERIALIZE(ctx.h4) && SERIALIZE(md->h2) &&
SERIALIZE(ctx.Nl) && SERIALIZE(md->h3) &&
SERIALIZE(ctx.Nh)) ) SERIALIZE(md->h4) &&
SERIALIZE(md->Nl) &&
SERIALIZE(md->Nh)) )
return false; return false;
for ( int i = 0; i < SHA_LBLOCK; ++i ) for ( int i = 0; i < SHA_LBLOCK; ++i )
{ {
if ( ! SERIALIZE(ctx.data[i]) ) if ( ! SERIALIZE(md->data[i]) )
return false; return false;
} }
if ( ! SERIALIZE(ctx.num) ) if ( ! SERIALIZE(md->num) )
return false; return false;
return true; return true;
@ -291,22 +300,25 @@ bool SHA1Val::DoUnserialize(UnserialInfo* info)
if ( ! IsValid() ) if ( ! IsValid() )
return true; return true;
if ( ! (UNSERIALIZE(&ctx.h0) && ctx = hash_init(Hash_SHA1);
UNSERIALIZE(&ctx.h1) && SHA_CTX *md = (SHA_CTX *) EVP_MD_CTX_md_data(ctx);
UNSERIALIZE(&ctx.h2) &&
UNSERIALIZE(&ctx.h3) && if ( ! (UNSERIALIZE(&md->h0) &&
UNSERIALIZE(&ctx.h4) && UNSERIALIZE(&md->h1) &&
UNSERIALIZE(&ctx.Nl) && UNSERIALIZE(&md->h2) &&
UNSERIALIZE(&ctx.Nh)) ) UNSERIALIZE(&md->h3) &&
UNSERIALIZE(&md->h4) &&
UNSERIALIZE(&md->Nl) &&
UNSERIALIZE(&md->Nh)) )
return false; return false;
for ( int i = 0; i < SHA_LBLOCK; ++i ) for ( int i = 0; i < SHA_LBLOCK; ++i )
{ {
if ( ! UNSERIALIZE(&ctx.data[i]) ) if ( ! UNSERIALIZE(&md->data[i]) )
return false; return false;
} }
if ( ! UNSERIALIZE(&ctx.num) ) if ( ! UNSERIALIZE(&md->num) )
return false; return false;
return true; return true;
@ -314,12 +326,14 @@ bool SHA1Val::DoUnserialize(UnserialInfo* info)
SHA256Val::SHA256Val() : HashVal(sha256_type) SHA256Val::SHA256Val() : HashVal(sha256_type)
{ {
if ( IsValid() )
// prevent leaks...
EVP_MD_CTX_free(ctx);
} }
void SHA256Val::digest(val_list& vlist, u_char result[SHA256_DIGEST_LENGTH]) void SHA256Val::digest(val_list& vlist, u_char result[SHA256_DIGEST_LENGTH])
{ {
SHA256_CTX h; EVP_MD_CTX* h = hash_init(Hash_SHA256);
sha256_init(&h);
loop_over_list(vlist, i) loop_over_list(vlist, i)
{ {
@ -327,23 +341,23 @@ void SHA256Val::digest(val_list& vlist, u_char result[SHA256_DIGEST_LENGTH])
if ( v->Type()->Tag() == TYPE_STRING ) if ( v->Type()->Tag() == TYPE_STRING )
{ {
const BroString* str = v->AsString(); const BroString* str = v->AsString();
sha256_update(&h, str->Bytes(), str->Len()); hash_update(h, str->Bytes(), str->Len());
} }
else else
{ {
ODesc d(DESC_BINARY); ODesc d(DESC_BINARY);
v->Describe(&d); v->Describe(&d);
sha256_update(&h, (const u_char *) d.Bytes(), d.Len()); hash_update(h, (const u_char *) d.Bytes(), d.Len());
} }
} }
sha256_final(&h, result); hash_final(h, result);
} }
bool SHA256Val::DoInit() bool SHA256Val::DoInit()
{ {
assert( ! IsValid() ); assert( ! IsValid() );
sha256_init(&ctx); ctx = hash_init(Hash_SHA256);
return true; return true;
} }
@ -352,7 +366,7 @@ bool SHA256Val::DoFeed(const void* data, size_t size)
if ( ! IsValid() ) if ( ! IsValid() )
return false; return false;
sha256_update(&ctx, data, size); hash_update(ctx, data, size);
return true; return true;
} }
@ -362,7 +376,7 @@ StringVal* SHA256Val::DoGet()
return val_mgr->GetEmptyString(); return val_mgr->GetEmptyString();
u_char digest[SHA256_DIGEST_LENGTH]; u_char digest[SHA256_DIGEST_LENGTH];
sha256_final(&ctx, digest); hash_final(ctx, digest);
return new StringVal(sha256_digest_print(digest)); return new StringVal(sha256_digest_print(digest));
} }
@ -375,24 +389,26 @@ bool SHA256Val::DoSerialize(SerialInfo* info) const
if ( ! IsValid() ) if ( ! IsValid() )
return true; return true;
SHA256_CTX *md = (SHA256_CTX *) EVP_MD_CTX_md_data(ctx);
for ( int i = 0; i < 8; ++i ) for ( int i = 0; i < 8; ++i )
{ {
if ( ! SERIALIZE(ctx.h[i]) ) if ( ! SERIALIZE(md->h[i]) )
return false; return false;
} }
if ( ! (SERIALIZE(ctx.Nl) && if ( ! (SERIALIZE(md->Nl) &&
SERIALIZE(ctx.Nh)) ) SERIALIZE(md->Nh)) )
return false; return false;
for ( int i = 0; i < SHA_LBLOCK; ++i ) for ( int i = 0; i < SHA_LBLOCK; ++i )
{ {
if ( ! SERIALIZE(ctx.data[i]) ) if ( ! SERIALIZE(md->data[i]) )
return false; return false;
} }
if ( ! (SERIALIZE(ctx.num) && if ( ! (SERIALIZE(md->num) &&
SERIALIZE(ctx.md_len)) ) SERIALIZE(md->md_len)) )
return false; return false;
return true; return true;
@ -405,25 +421,28 @@ bool SHA256Val::DoUnserialize(UnserialInfo* info)
if ( ! IsValid() ) if ( ! IsValid() )
return true; return true;
ctx = hash_init(Hash_SHA256);
SHA256_CTX *md = (SHA256_CTX *) EVP_MD_CTX_md_data(ctx);
for ( int i = 0; i < 8; ++i ) for ( int i = 0; i < 8; ++i )
{ {
if ( ! UNSERIALIZE(&ctx.h[i]) ) if ( ! UNSERIALIZE(&md->h[i]) )
return false; return false;
} }
if ( ! (UNSERIALIZE(&ctx.Nl) && if ( ! (UNSERIALIZE(&md->Nl) &&
UNSERIALIZE(&ctx.Nh)) ) UNSERIALIZE(&md->Nh)) )
return false; return false;
for ( int i = 0; i < SHA_LBLOCK; ++i ) for ( int i = 0; i < SHA_LBLOCK; ++i )
{ {
if ( ! UNSERIALIZE(&ctx.data[i]) ) if ( ! UNSERIALIZE(&md->data[i]) )
return false; return false;
} }
if ( ! (UNSERIALIZE(&ctx.num) && if ( ! (UNSERIALIZE(&md->num) &&
UNSERIALIZE(&ctx.md_len)) ) UNSERIALIZE(&md->md_len)) )
return false; return false;
return true; return true;

View file

@ -75,7 +75,7 @@ protected:
DECLARE_SERIAL(SHA1Val); DECLARE_SERIAL(SHA1Val);
private: private:
SHA_CTX ctx; EVP_MD_CTX* ctx;
}; };
class SHA256Val : public HashVal { class SHA256Val : public HashVal {
@ -94,7 +94,7 @@ protected:
DECLARE_SERIAL(SHA256Val); DECLARE_SERIAL(SHA256Val);
private: private:
SHA256_CTX ctx; EVP_MD_CTX* ctx;
}; };
class EntropyVal : public OpaqueVal { class EntropyVal : public OpaqueVal {

View file

@ -1335,7 +1335,7 @@ MIME_Mail::MIME_Mail(analyzer::Analyzer* mail_analyzer, bool orig, int buf_size)
if ( mime_content_hash ) if ( mime_content_hash )
{ {
compute_content_hash = 1; compute_content_hash = 1;
md5_init(&md5_hash); md5_hash = hash_init(Hash_MD5);
} }
else else
compute_content_hash = 0; compute_content_hash = 0;
@ -1355,7 +1355,7 @@ void MIME_Mail::Done()
if ( compute_content_hash && mime_content_hash ) if ( compute_content_hash && mime_content_hash )
{ {
u_char* digest = new u_char[16]; u_char* digest = new u_char[16];
md5_final(md5_hash, digest); hash_final(md5_hash, digest);
val_list* vl = new val_list; val_list* vl = new val_list;
vl->append(analyzer->BuildConnVal()); vl->append(analyzer->BuildConnVal());
@ -1456,7 +1456,7 @@ void MIME_Mail::SubmitData(int len, const char* buf)
if ( compute_content_hash ) if ( compute_content_hash )
{ {
content_hash_length += len; content_hash_length += len;
md5_update(md5_hash, (const u_char*) buf, len); hash_update(md5_hash, (const u_char*) buf, len);
} }
if ( mime_entity_data || mime_all_data ) if ( mime_entity_data || mime_all_data )

View file

@ -23,6 +23,8 @@ inline void *EVP_MD_CTX_md_data(const EVP_MD_CTX* ctx)
#include "Reporter.h" #include "Reporter.h"
enum HashAlgorithm { Hash_MD5, Hash_SHA1, Hash_SHA224, Hash_SHA256, Hash_SHA384, Hash_SHA512 };
inline const char* digest_print(const u_char* digest, size_t n) inline const char* digest_print(const u_char* digest, size_t n)
{ {
static char buf[256]; // big enough for any of md5/sha1/sha256 static char buf[256]; // big enough for any of md5/sha1/sha256
@ -46,92 +48,65 @@ inline const char* sha256_digest_print(const u_char digest[SHA256_DIGEST_LENGTH]
return digest_print(digest, SHA256_DIGEST_LENGTH); return digest_print(digest, SHA256_DIGEST_LENGTH);
} }
inline void md5_init(EVP_MD_CTX** c) inline EVP_MD_CTX* hash_init(HashAlgorithm alg)
{ {
*c = EVP_MD_CTX_new(); EVP_MD_CTX *c = EVP_MD_CTX_new();
/* Allow this to work even if FIPS disables it */ /* Allow this to work even if FIPS disables it */
const EVP_MD* md;
switch (alg)
{
case Hash_MD5:
#ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW #ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW
EVP_MD_CTX_set_flags(*c, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); EVP_MD_CTX_set_flags(c, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
#endif #endif
if ( ! EVP_DigestInit_ex(*c, EVP_md5(), NULL) ) md = EVP_md5();
reporter->InternalError("MD5_Init failed"); break;
case Hash_SHA1:
md = EVP_sha1();
break;
case Hash_SHA224:
md = EVP_sha224();
break;
case Hash_SHA256:
md = EVP_sha256();
break;
case Hash_SHA384:
md = EVP_sha384();
break;
case Hash_SHA512:
md = EVP_sha512();
break;
default:
reporter->InternalError("Unknown hash algorithm passed to hash_init");
}
if ( ! EVP_DigestInit_ex(c, md, NULL) )
reporter->InternalError("EVP_DigestInit failed");
return c;
} }
inline void md5_update(EVP_MD_CTX* c, const void* data, unsigned long len) inline void hash_update(EVP_MD_CTX* c, const void* data, unsigned long len)
{ {
if ( ! EVP_DigestUpdate(c, data, len) ) if ( ! EVP_DigestUpdate(c, data, len) )
reporter->InternalError("MD5_Update failed"); reporter->InternalError("EVP_DigestUpdate failed");
} }
inline void md5_final(EVP_MD_CTX* c, u_char md[MD5_DIGEST_LENGTH]) inline void hash_final(EVP_MD_CTX* c, u_char md[MD5_DIGEST_LENGTH])
{ {
if ( ! EVP_DigestFinal(c, md, NULL) ) if ( ! EVP_DigestFinal(c, md, NULL) )
reporter->InternalError("MD5_Final failed"); reporter->InternalError("EVP_DigestFinal failed");
EVP_MD_CTX_free(c);
} }
inline unsigned char* internal_md5(const unsigned char *d, size_t n, unsigned char *md) inline unsigned char* internal_md5(const unsigned char *data, unsigned long len, unsigned char *out)
{ {
EVP_MD_CTX *c; static unsigned char static_out[MD5_DIGEST_LENGTH];
static unsigned char m[MD5_DIGEST_LENGTH]; if ( ! out )
out = static_out; // use static array for return, see OpenSSL man page
if (md == NULL) EVP_MD_CTX *c = hash_init(Hash_MD5);
md = m; hash_update(c, data, len);
md5_init(&c); hash_final(c, out);
#ifndef CHARSET_EBCDIC return out;
md5_update(c, d, n);
#else
{
char temp[1024];
unsigned long chunk;
while (n > 0) {
chunk = (n > sizeof(temp)) ? sizeof(temp) : n;
ebcdic2ascii(temp, d, chunk);
md5_update(c, temp, chunk);
n -= chunk;
d += chunk;
}
}
#endif
md5_final(c, md);
EVP_MD_CTX_free(c);
return md;
}
inline void sha1_init(SHA_CTX* c)
{
if ( ! SHA1_Init(c) )
reporter->InternalError("SHA_Init failed");
}
inline void sha1_update(SHA_CTX* c, const void* data, unsigned long len)
{
if ( ! SHA1_Update(c, data, len) )
reporter->InternalError("SHA_Update failed");
}
inline void sha1_final(SHA_CTX* c, u_char md[SHA_DIGEST_LENGTH])
{
if ( ! SHA1_Final(md, c) )
reporter->InternalError("SHA_Final failed");
}
inline void sha256_init(SHA256_CTX* c)
{
if ( ! SHA256_Init(c) )
reporter->InternalError("SHA256_Init failed");
}
inline void sha256_update(SHA256_CTX* c, const void* data, unsigned long len)
{
if ( ! SHA256_Update(c, data, len) )
reporter->InternalError("SHA256_Update failed");
}
inline void sha256_final(SHA256_CTX* c, u_char md[SHA256_DIGEST_LENGTH])
{
if ( ! SHA256_Final(md, c) )
reporter->InternalError("SHA256_Final failed");
} }
#endif //bro_digest_h #endif //bro_digest_h

View file

@ -496,13 +496,12 @@ uint64 BitVector::Hash() const
{ {
u_char buf[SHA256_DIGEST_LENGTH]; u_char buf[SHA256_DIGEST_LENGTH];
uint64 digest; uint64 digest;
SHA256_CTX ctx; EVP_MD_CTX* ctx = hash_init(Hash_SHA256);
sha256_init(&ctx);
for ( size_type i = 0; i < Blocks(); ++i ) for ( size_type i = 0; i < Blocks(); ++i )
sha256_update(&ctx, &bits[i], sizeof(bits[i])); hash_update(ctx, &bits[i], sizeof(bits[i]));
sha256_final(&ctx, buf); hash_final(ctx, buf);
memcpy(&digest, buf, sizeof(digest)); // Use the first bytes as digest memcpy(&digest, buf, sizeof(digest)); // Use the first bytes as digest
return digest; return digest;
} }

View file

@ -15,24 +15,23 @@ Hasher::seed_t Hasher::MakeSeed(const void* data, size_t size)
{ {
u_char buf[SHA256_DIGEST_LENGTH]; u_char buf[SHA256_DIGEST_LENGTH];
seed_t tmpseed; seed_t tmpseed;
SHA256_CTX ctx; EVP_MD_CTX* ctx = hash_init(Hash_SHA256);
sha256_init(&ctx);
assert(sizeof(tmpseed) == 16); assert(sizeof(tmpseed) == 16);
if ( data ) if ( data )
sha256_update(&ctx, data, size); hash_update(ctx, data, size);
else if ( global_hash_seed && global_hash_seed->Len() > 0 ) else if ( global_hash_seed && global_hash_seed->Len() > 0 )
sha256_update(&ctx, global_hash_seed->Bytes(), global_hash_seed->Len()); hash_update(ctx, global_hash_seed->Bytes(), global_hash_seed->Len());
else else
{ {
unsigned int first_seed = initial_seed(); unsigned int first_seed = initial_seed();
sha256_update(&ctx, &first_seed, sizeof(first_seed)); hash_update(ctx, &first_seed, sizeof(first_seed));
} }
sha256_final(&ctx, buf); hash_final(ctx, buf);
memcpy(&tmpseed, buf, sizeof(tmpseed)); // Use the first bytes as seed. memcpy(&tmpseed, buf, sizeof(tmpseed)); // Use the first bytes as seed.
return tmpseed; return tmpseed;
} }

View file

@ -44,4 +44,6 @@ three
[zero, one, two] [zero, one, two]
[s=abc] [s=abc]
[c=123, r1=[s=xyz]] [c=123, r1=[s=xyz]]
opaque of md5, T
opaque of sha1, T
opaque of sha256, T opaque of sha256, T

View file

@ -57,6 +57,20 @@ event bro_init()
print (Broker::data(R1($s="abc")) as R1); print (Broker::data(R1($s="abc")) as R1);
print (Broker::data(R2($c=123, $r1=R1($s="xyz"))) as R2); print (Broker::data(R2($c=123, $r1=R1($s="xyz"))) as R2);
local md5h1 = md5_hash_init();
md5_hash_update(md5h1, "abc");
local md5h2 = (Broker::data(md5h1) as opaque of md5);
local md5s1 = md5_hash_finish(md5h1);
local md5s2 = md5_hash_finish(md5h2);
print "opaque of md5", md5s1 == md5s2;
local sha1h1 = sha1_hash_init();
sha1_hash_update(sha1h1, "abc");
local sha1h2 = (Broker::data(sha1h1) as opaque of sha1);
local sha1s1 = sha1_hash_finish(sha1h1);
local sha1s2 = sha1_hash_finish(sha1h2);
print "opaque of sha1", sha1s1 == sha1s2;
local h1 = sha256_hash_init(); local h1 = sha256_hash_init();
sha256_hash_update(h1, "abc"); sha256_hash_update(h1, "abc");
local h2 = (Broker::data(h1) as opaque of sha256); local h2 = (Broker::data(h1) as opaque of sha256);