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:
Markus Triska
2020-05-14 20:07:59 +02:00
parent c07274a6fa
commit 50776748a7
5 changed files with 209 additions and 56 deletions

View File

@@ -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,

View File

@@ -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
}
}