Add support for opaque hash values.

This commit is contained in:
Matthias Vallentin 2012-12-11 16:24:52 -08:00
parent 23ca1c90ef
commit 624003f036
6 changed files with 340 additions and 0 deletions

View file

@ -358,6 +358,7 @@ set(bro_SRCS
NetVar.cc
NetbiosSSN.cc
Obj.cc
OpaqueVal.cc
OSFinger.cc
PacketFilter.cc
PacketSort.cc

200
src/OpaqueVal.cc Normal file
View file

@ -0,0 +1,200 @@
#include "OpaqueVal.h"
#include "Reporter.h"
#include "Serializer.h"
bool HashVal::IsValid() const
{
return valid;
}
bool HashVal::Init()
{
assert(! "missing implementation of Init()");
return false;
}
StringVal* HashVal::Get()
{
if ( ! valid )
return new StringVal("");
StringVal* result = Finish();
valid = false;
return result;
}
bool HashVal::Feed(const void* data, size_t size)
{
if ( valid )
return Update(data, size);
reporter->InternalError("invalidated opaque handle");
return false;
}
bool HashVal::Update(const void*, size_t)
{
assert(! "missing implementation of Update()");
return false;
}
StringVal* HashVal::Finish()
{
assert(! "missing implementation of Finish()");
return new StringVal("");
}
HashVal::HashVal(OpaqueType* t) : OpaqueVal(t), valid(true) { }
IMPLEMENT_SERIAL(HashVal, SER_HASH_VAL);
bool HashVal::DoSerialize(SerialInfo* info) const
{
return SERIALIZE(valid);
}
bool HashVal::DoUnserialize(UnserialInfo* info)
{
return UNSERIALIZE(&valid);
}
void MD5Val::digest(val_list& vlist, u_char result[MD5_DIGEST_LENGTH])
{
MD5_CTX h;
md5_init(&h);
loop_over_list(vlist, i)
{
Val* v = vlist[i];
if ( v->Type()->Tag() == TYPE_STRING )
{
const BroString* str = v->AsString();
md5_update(&h, str->Bytes(), str->Len());
}
else
{
ODesc d(DESC_BINARY);
v->Describe(&d);
md5_update(&h, (const u_char *) d.Bytes(), d.Len());
}
}
md5_final(&h, result);
}
void MD5Val::hmac(val_list& vlist,
u_char key[MD5_DIGEST_LENGTH],
u_char result[MD5_DIGEST_LENGTH])
{
digest(vlist, result);
for ( int i = 0; i < MD5_DIGEST_LENGTH; ++i )
result[i] ^= key[i];
MD5(result, MD5_DIGEST_LENGTH, result);
}
bool MD5Val::Init()
{
md5_init(&ctx);
return true;
}
bool MD5Val::Update(const void* data, size_t size)
{
assert(IsValid());
md5_update(&ctx, data, size);
return true;
}
StringVal* MD5Val::Finish()
{
assert(IsValid());
u_char digest[MD5_DIGEST_LENGTH];
md5_final(&ctx, digest);
return new StringVal(md5_digest_print(digest));
}
IMPLEMENT_SERIAL(MD5Val, SER_MD5_VAL);
bool MD5Val::DoSerialize(SerialInfo* info) const
{
// TODO: Implement serialization of MD5 state.
return false;
}
bool MD5Val::DoUnserialize(UnserialInfo* info)
{
// TODO: Implement deserialization of MD5 state.
return false;
}
bool SHA1Val::Init()
{
sha1_init(&ctx);
return true;
}
bool SHA1Val::Update(const void* data, size_t size)
{
assert(IsValid());
sha1_update(&ctx, data, size);
return true;
}
StringVal* SHA1Val::Finish()
{
assert(IsValid());
u_char digest[SHA_DIGEST_LENGTH];
sha1_final(&ctx, digest);
return new StringVal(sha1_digest_print(digest));
}
IMPLEMENT_SERIAL(SHA1Val, SER_SHA1_VAL);
bool SHA1Val::DoSerialize(SerialInfo* info) const
{
// TODO: Implement serialization of SHA1 state.
return false;
}
bool SHA1Val::DoUnserialize(UnserialInfo* info)
{
// TODO: Implement deserialization of SHA1 state.
return false;
}
bool SHA256Val::Init()
{
sha256_init(&ctx);
return true;
}
bool SHA256Val::Update(const void* data, size_t size)
{
assert(IsValid());
sha256_update(&ctx, data, size);
return true;
}
StringVal* SHA256Val::Finish()
{
assert(IsValid());
u_char digest[SHA256_DIGEST_LENGTH];
sha256_final(&ctx, digest);
return new StringVal(sha256_digest_print(digest));
}
IMPLEMENT_SERIAL(SHA256Val, SER_SHA256_VAL);
bool SHA256Val::DoSerialize(SerialInfo* info) const
{
// TODO: Implement serialization of SHA256 state.
return false;
}
bool SHA256Val::DoUnserialize(UnserialInfo* info)
{
// TODO: Implement deserialization of SHA256 state.
return false;
}

84
src/OpaqueVal.h Normal file
View file

@ -0,0 +1,84 @@
#ifndef OPAQUEVAL_H
#define OPAQUEVAL_H
#include "Val.h"
#include "digest.h"
class HashVal : public OpaqueVal {
public:
virtual bool IsValid() const;
virtual bool Init();
virtual bool Feed(const void* data, size_t size);
virtual StringVal* Get();
protected:
HashVal() { };
HashVal(OpaqueType* t);
virtual bool Update(const void* data, size_t size);
virtual StringVal* Finish();
DECLARE_SERIAL(HashVal);
private:
// This flag exists because Get() can only be called once.
bool valid;
};
class MD5Val : public HashVal {
public:
static void digest(val_list& vlist, u_char result[MD5_DIGEST_LENGTH]);
static void hmac(val_list& vlist,
u_char key[MD5_DIGEST_LENGTH],
u_char result[MD5_DIGEST_LENGTH]);
MD5Val() : HashVal(new OpaqueType("md5")) { }
protected:
friend class Val;
virtual bool Init() /* override */;
virtual bool Update(const void* data, size_t size) /* override */;
virtual StringVal* Finish() /* override */;
DECLARE_SERIAL(MD5Val);
private:
MD5_CTX ctx;
};
class SHA1Val : public HashVal {
public:
SHA1Val() : HashVal(new OpaqueType("sha1")) { }
protected:
friend class Val;
virtual bool Init() /* override */;
virtual bool Update(const void* data, size_t size) /* override */;
virtual StringVal* Finish() /* override */;
DECLARE_SERIAL(SHA1Val);
private:
SHA_CTX ctx;
};
class SHA256Val : public HashVal {
public:
SHA256Val() : HashVal(new OpaqueType("sha256")) { }
protected:
friend class Val;
virtual bool Init() /* override */;
virtual bool Update(const void* data, size_t size) /* override */;
virtual StringVal* Finish() /* override */;
DECLARE_SERIAL(SHA256Val);
private:
SHA256_CTX ctx;
};
#endif

View file

@ -98,6 +98,11 @@ SERIAL_VAL(RECORD_VAL, 10)
SERIAL_VAL(ENUM_VAL, 11)
SERIAL_VAL(VECTOR_VAL, 12)
SERIAL_VAL(MUTABLE_VAL, 13)
SERIAL_VAL(OPAQUE_VAL, 14)
SERIAL_VAL(HASH_VAL, 15)
SERIAL_VAL(MD5_VAL, 16)
SERIAL_VAL(SHA1_VAL, 17)
SERIAL_VAL(SHA256_VAL, 18)
#define SERIAL_EXPR(name, val) SERIAL_CONST(name, val, EXPR)
SERIAL_EXPR(EXPR, 1)

View file

@ -3114,6 +3114,38 @@ void VectorVal::ValDescribe(ODesc* d) const
d->Add("]");
}
OpaqueVal::OpaqueVal(OpaqueType* t) : opaque_type(t) { }
OpaqueVal::~OpaqueVal()
{
Unref(opaque_type);
}
bool OpaqueVal::IsValid() const
{
return false;
}
IMPLEMENT_SERIAL(OpaqueVal, SER_OPAQUE_VAL);
bool OpaqueVal::DoSerialize(SerialInfo* info) const
{
DO_SERIALIZE(SER_OPAQUE_VAL, Val);
assert(opaque_type);
// TODO: how to serialize a serializable class?
//return SERIALIZE(*opaque_type);
return false;
}
bool OpaqueVal::DoUnserialize(UnserialInfo* info)
{
DO_UNSERIALIZE(Val);
// TODO: how to deserialize a serializable class?
//opaque_type = new OpaqueType();
//return UNSERIALIZE(opaque_type);
return false;
}
Val* check_and_promote(Val* v, const BroType* t, int is_init)
{

View file

@ -1013,6 +1013,24 @@ protected:
VectorType* vector_type;
};
// See OpaqueVal.h for derived classes.
class OpaqueVal : public Val {
public:
OpaqueVal(OpaqueType* t);
virtual ~OpaqueVal();
// Determines whether the opaque value is in a valid state.
virtual bool IsValid() const;
protected:
friend class Val;
OpaqueVal() { }
DECLARE_SERIAL(OpaqueVal);
OpaqueType* opaque_type;
};
// Checks the given value for consistency with the given type. If an
// exact match, returns it. If promotable, returns the promoted version,