1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
use crate::software_vault::SoftwareVault;
use crate::VaultError;
use arrayref::array_ref;
use ockam_core::compat::vec::Vec;
use ockam_vault_core::{
Hasher, Secret, SecretAttributes, SecretType, SecretVault, AES128_SECRET_LENGTH,
AES256_SECRET_LENGTH,
};
use sha2::{Digest, Sha256};
impl Hasher for SoftwareVault {
fn sha256(&mut self, data: &[u8]) -> ockam_core::Result<[u8; 32]> {
let digest = Sha256::digest(data);
Ok(*array_ref![digest, 0, 32])
}
fn hkdf_sha256(
&mut self,
salt: &Secret,
info: &[u8],
ikm: Option<&Secret>,
output_attributes: Vec<SecretAttributes>,
) -> ockam_core::Result<Vec<Secret>> {
let ikm: ockam_core::Result<&[u8]> = match ikm {
Some(ikm) => {
let ikm = self.get_entry(ikm)?;
if ikm.key_attributes().stype() == SecretType::Buffer {
Ok(ikm.key().as_ref())
} else {
Err(VaultError::InvalidKeyType.into())
}
}
None => Ok(&[0u8; 0]),
};
let ikm = ikm?;
let salt = self.get_entry(salt)?;
if salt.key_attributes().stype() != SecretType::Buffer {
return Err(VaultError::InvalidKeyType.into());
}
let okm_len = output_attributes.len() * 32;
let okm = {
let mut okm = vec![0u8; okm_len];
let prk = hkdf::Hkdf::<Sha256>::new(Some(salt.key().as_ref()), ikm);
prk.expand(info, okm.as_mut_slice())
.map_err(|_| Into::<ockam_core::Error>::into(VaultError::HkdfExpandError))?;
okm
};
let mut secrets = Vec::<Secret>::new();
let mut index = 0;
for attributes in output_attributes {
let length = attributes.length();
if attributes.stype() == SecretType::Aes {
if length != AES256_SECRET_LENGTH && length != AES128_SECRET_LENGTH {
return Err(VaultError::InvalidAesKeyLength.into());
}
} else if attributes.stype() != SecretType::Buffer {
return Err(VaultError::InvalidHkdfOutputType.into());
}
let secret = &okm[index..index + length];
let secret = self.secret_import(secret, attributes)?;
secrets.push(secret);
index += 32;
}
Ok(secrets)
}
}
#[cfg(test)]
mod tests {
use crate::SoftwareVault;
use ockam_vault_test_attribute::*;
fn new_vault() -> SoftwareVault {
SoftwareVault::default()
}
#[vault_test]
fn sha256() {}
#[vault_test]
fn hkdf() {}
}