ADDED: HMAC-based key derivation (HKDF) via crypto_data_hkdf/4
This is useful to generate keys and initialization vectors from suitable input keying material, so that future predicates for symmetric encryption can be used with appropriate parameters.
This commit is contained in:
@@ -2746,6 +2746,51 @@ impl MachineState {
|
||||
*list = result;
|
||||
}
|
||||
|
||||
|
||||
pub(super)
|
||||
fn integers_to_bytevec(
|
||||
&self,
|
||||
r: RegType,
|
||||
caller: MachineStub,
|
||||
) -> Vec<u8> {
|
||||
|
||||
let mut bytes: Vec<u8> = Vec::new();
|
||||
|
||||
match self.try_from_list(r, caller) {
|
||||
Err(_) => { unreachable!() }
|
||||
Ok(addrs) => {
|
||||
|
||||
for addr in addrs {
|
||||
let addr = self.store(self.deref(addr));
|
||||
|
||||
match Number::try_from((addr, &self.heap)) {
|
||||
Ok(Number::Fixnum(n)) => {
|
||||
match u8::try_from(n) {
|
||||
Ok(b) => {
|
||||
bytes.push(b);
|
||||
}
|
||||
Err(_) => { }
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
Ok(Number::Integer(n)) => {
|
||||
if let Some(b) = n.to_u8() {
|
||||
bytes.push(b);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
_ => {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
bytes
|
||||
}
|
||||
|
||||
|
||||
pub(super)
|
||||
fn try_from_list(
|
||||
&self,
|
||||
|
||||
@@ -39,7 +39,7 @@ use crate::crossterm::event::{read, Event, KeyCode, KeyEvent, KeyModifiers};
|
||||
use crate::crossterm::terminal::{enable_raw_mode, disable_raw_mode};
|
||||
|
||||
use ring::rand::{SecureRandom, SystemRandom};
|
||||
use ring::digest;
|
||||
use ring::{digest,hkdf};
|
||||
use ripemd160::{Ripemd160, Digest};
|
||||
|
||||
pub fn get_key() -> KeyEvent {
|
||||
@@ -5206,41 +5206,8 @@ impl MachineState {
|
||||
self.unify(arg, byte);
|
||||
}
|
||||
&SystemClauseType::CryptoDataHash => {
|
||||
let mut bytes: Vec<u8> = Vec::new();
|
||||
|
||||
let stub = MachineError::functor_stub(clause_name!("crypto_data_hash"), 3);
|
||||
|
||||
match self.try_from_list(temp_v!(1), stub) {
|
||||
Err(e) => return Err(e),
|
||||
Ok(addrs) => {
|
||||
|
||||
for addr in addrs {
|
||||
let addr = self.store(self.deref(addr));
|
||||
|
||||
match Number::try_from((addr, &self.heap)) {
|
||||
Ok(Number::Fixnum(n)) => {
|
||||
match u8::try_from(n) {
|
||||
Ok(b) => {
|
||||
bytes.push(b);
|
||||
}
|
||||
Err(_) => { }
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
Ok(Number::Integer(n)) => {
|
||||
if let Some(b) = n.to_u8() {
|
||||
bytes.push(b);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
_ => {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let bytes = self.integers_to_bytevec(temp_v!(1), stub);
|
||||
|
||||
let algorithm = self[temp_v!(3)];
|
||||
let algorithm_str = match self.store(self.deref(algorithm)) {
|
||||
@@ -5276,6 +5243,58 @@ impl MachineState {
|
||||
|
||||
self.unify(self[temp_v!(2)], ints_list);
|
||||
}
|
||||
&SystemClauseType::CryptoDataHKDF => {
|
||||
let stub1 = MachineError::functor_stub(clause_name!("crypto_data_hkdf"), 6);
|
||||
let data = self.integers_to_bytevec(temp_v!(1), stub1);
|
||||
let stub2 = MachineError::functor_stub(clause_name!("crypto_data_hkdf"), 6);
|
||||
let salt = self.integers_to_bytevec(temp_v!(2), stub2);
|
||||
let stub3 = MachineError::functor_stub(clause_name!("crypto_data_hkdf"), 6);
|
||||
let info = self.integers_to_bytevec(temp_v!(3), stub3);
|
||||
|
||||
let algorithm = match self.store(self.deref(self[temp_v!(4)])) {
|
||||
Addr::Con(h) if self.heap.atom_at(h) => {
|
||||
if let HeapCellValue::Atom(ref atom, _) = &self.heap[h] {
|
||||
atom.as_str()
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
unreachable!()
|
||||
}
|
||||
};
|
||||
|
||||
let length =
|
||||
match Number::try_from((self[temp_v!(5)], &self.heap)) {
|
||||
Ok(Number::Fixnum(n)) => {
|
||||
usize::try_from(n).unwrap()
|
||||
}
|
||||
Ok(Number::Integer(n)) => {
|
||||
n.to_usize().unwrap()
|
||||
}
|
||||
_ => {
|
||||
unreachable!()
|
||||
}
|
||||
};
|
||||
|
||||
let ints_list =
|
||||
{ let digest_alg =
|
||||
match algorithm {
|
||||
"sha256" => { hkdf::HKDF_SHA256 }
|
||||
"sha384" => { hkdf::HKDF_SHA384 }
|
||||
"sha512" => { hkdf::HKDF_SHA512 }
|
||||
_ => { unreachable!() }
|
||||
};
|
||||
let salt = hkdf::Salt::new(digest_alg, &salt);
|
||||
let mut bytes : Vec<u8> = Vec::new();
|
||||
bytes.resize(length, 0);
|
||||
salt.extract(&data).expand(&[&info[..]], MyKey(length)).unwrap().fill(&mut bytes).unwrap();
|
||||
|
||||
Addr::HeapCell(self.heap.to_list(bytes.iter().map(|b| HeapCellValue::Integer(Rc::new(Integer::from(*b))))))
|
||||
};
|
||||
|
||||
self.unify(self[temp_v!(6)], ints_list);
|
||||
}
|
||||
};
|
||||
|
||||
return_from_clause!(self.last_call, self)
|
||||
@@ -5292,3 +5311,11 @@ fn rng() -> &'static dyn SecureRandom {
|
||||
|
||||
RANDOM.deref()
|
||||
}
|
||||
|
||||
struct MyKey<T: core::fmt::Debug + PartialEq>(T);
|
||||
|
||||
impl hkdf::KeyType for MyKey<usize> {
|
||||
fn len(&self) -> usize {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user