fogtix/crates/fogtix-bytecode/src/value.rs
2022-09-23 04:45:34 +02:00

98 lines
2.3 KiB
Rust

use crate::consts::Type;use siphasher::sip::SipHasher24 as SipHasher;
/// A key used to sign a pointer
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(align(16))]
pub struct PointerKey(pub u64, pub u64);
impl PointerKey {
#[inline(always)]
fn build_hasher(&self) -> SipHasher {
SipHasher::new_with_keys(self.0, self.1)
}
}
/// A signed pointer, the `payload` should never by dereferenced
/// without verifying the pointer first
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(align(16))]
pub struct Pointer {
pub hmac: u64,
pub payload: u64,
}
impl From<Pointer> for PointerKey {
#[inline(always)]
/// allows to derive a pointer key from a pointer
fn from(x: Pointer) -> Self {
Self(x.hmac, x.payload)
}
}
impl Pointer {
fn calculate_hmac(payload: u64, key: &PointerKey) -> u64 {
use core::hash::Hasher;
let mut h = key.build_hasher();
h.write_u64(payload);
h.finish()
}
#[inline]
pub fn new_with_key(payload: u64, key: &PointerKey) -> Pointer {
Pointer {
hmac: Self::calculate_hmac(payload, key),
payload,
}
}
#[inline]
pub fn verify(&self, key: &PointerKey) -> Option<u64> {
if self.hmac == Self::calculate_hmac(self.payload, key) {
Some(self.payload)
} else {
None
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum Value {
Pointer(Pointer),
Int(u64),
Bytes(Vec<u8>),
}
impl Value {
#[inline]
pub fn typ(&self) -> Type {
match self {
Value::Pointer(_) => Type::Pointer,
Value::Int(_) => Type::Int_,
Value::Bytes(_) => Type::Bytes,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn pointer_repr() {
use core::mem;
assert_eq!(mem::size_of::<PointerKey>(), 16);
assert_eq!(mem::align_of::<PointerKey>(), 16);
assert_eq!(mem::size_of::<Pointer>(), 16);
assert_eq!(mem::align_of::<Pointer>(), 16);
}
#[test]
fn pointer_usage() {
let k = PointerKey(0xdead, 0xbeef);
let p = Pointer::new_with_key(0xfefe, &k);
// verify that this is the same value on all systems
assert_eq!(p.hmac, 0xf5779875fe3ef8e);
assert_eq!(p.verify(&k), Some(0xfefe));
}
}