• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(&param.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(&param.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