1 //! TA functionality for shared secret negotiation.
2
3 use crate::device::DeviceHmac;
4 use alloc::{boxed::Box, vec::Vec};
5 use kmr_common::{crypto, crypto::hmac, km_err, vec_try, Error, FallibleAllocExt};
6 use kmr_wire::{keymint::Digest, sharedsecret::SharedSecretParameters};
7 use log::info;
8
9 impl<'a> crate::KeyMintTa<'a> {
get_shared_secret_params(&mut self) -> Result<SharedSecretParameters, Error>10 pub(crate) fn get_shared_secret_params(&mut self) -> Result<SharedSecretParameters, Error> {
11 if self.shared_secret_params.is_none() {
12 let mut nonce = vec_try![0u8; 32]?;
13 self.imp.rng.fill_bytes(&mut nonce);
14 self.shared_secret_params = Some(SharedSecretParameters { seed: Vec::new(), nonce });
15 }
16 Ok(self.shared_secret_params.as_ref().unwrap().clone()) // safe: filled above
17 }
18
compute_shared_secret( &mut self, params: &[SharedSecretParameters], ) -> Result<Vec<u8>, Error>19 pub(crate) fn compute_shared_secret(
20 &mut self,
21 params: &[SharedSecretParameters],
22 ) -> Result<Vec<u8>, Error> {
23 info!("Setting HMAC key from {} shared secret parameters", params.len());
24 let local_params = match &self.shared_secret_params {
25 Some(params) => params,
26 None => return Err(km_err!(HardwareNotYetAvailable, "no local shared secret params")),
27 };
28
29 let context = shared_secret_context(params, local_params)?;
30 let key = hmac::Key(self.imp.ckdf.ckdf(
31 &self.dev.keys.kak()?,
32 kmr_wire::sharedsecret::KEY_AGREEMENT_LABEL.as_bytes(),
33 &[&context],
34 kmr_common::crypto::SHA256_DIGEST_LEN,
35 )?);
36
37 // Potentially hand the negotiated HMAC key off to hardware.
38 self.device_hmac = Some(self.dev.keys.hmac_key_agreed(&key).unwrap_or_else(|| {
39 // Key not installed into hardware, so build & use a local impl.
40 Box::new(SoftDeviceHmac { key })
41 }));
42 self.device_hmac(kmr_wire::sharedsecret::KEY_CHECK_LABEL.as_bytes())
43 }
44 }
45
46 /// Build the shared secret context from the given `params`, which
47 /// is required to include `must_include` (our own parameters).
shared_secret_context( params: &[SharedSecretParameters], must_include: &SharedSecretParameters, ) -> Result<Vec<u8>, crate::Error>48 pub fn shared_secret_context(
49 params: &[SharedSecretParameters],
50 must_include: &SharedSecretParameters,
51 ) -> Result<Vec<u8>, crate::Error> {
52 let mut result = Vec::new();
53 let mut seen = false;
54 for param in params {
55 result.try_extend_from_slice(¶m.seed)?;
56 if param.nonce.len() != 32 {
57 return Err(km_err!(InvalidArgument, "nonce len {} not 32", param.nonce.len()));
58 }
59 result.try_extend_from_slice(¶m.nonce)?;
60 if param == must_include {
61 seen = true;
62 }
63 }
64 if !seen {
65 Err(km_err!(InvalidArgument, "shared secret params missing local value"))
66 } else {
67 Ok(result)
68 }
69 }
70
71 /// Device HMAC implementation that holds the HMAC key in memory.
72 struct SoftDeviceHmac {
73 key: crypto::hmac::Key,
74 }
75
76 impl DeviceHmac for SoftDeviceHmac {
hmac(&self, imp: &dyn crypto::Hmac, data: &[u8]) -> Result<Vec<u8>, Error>77 fn hmac(&self, imp: &dyn crypto::Hmac, data: &[u8]) -> Result<Vec<u8>, Error> {
78 let mut hmac_op = imp.begin(self.key.clone().into(), Digest::Sha256)?;
79 hmac_op.update(data)?;
80 hmac_op.finish()
81 }
82
get_hmac_key(&self) -> Option<crypto::hmac::Key>83 fn get_hmac_key(&self) -> Option<crypto::hmac::Key> {
84 Some(self.key.clone())
85 }
86 }
87