1 // Copyright 2022, The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 //! TA functionality for shared secret negotiation.
16
17 use crate::device::DeviceHmac;
18 use alloc::{boxed::Box, vec::Vec};
19 use kmr_common::{crypto, crypto::hmac, km_err, vec_try, Error, FallibleAllocExt};
20 use kmr_wire::{keymint::Digest, sharedsecret::SharedSecretParameters};
21 use log::info;
22
23 impl crate::KeyMintTa {
get_shared_secret_params(&mut self) -> Result<SharedSecretParameters, Error>24 pub(crate) fn get_shared_secret_params(&mut self) -> Result<SharedSecretParameters, Error> {
25 if self.shared_secret_params.is_none() {
26 let mut nonce = vec_try![0u8; 32]?;
27 self.imp.rng.fill_bytes(&mut nonce);
28 self.shared_secret_params = Some(SharedSecretParameters { seed: Vec::new(), nonce });
29 }
30 Ok(self.shared_secret_params.as_ref().unwrap().clone()) // safe: filled above
31 }
32
compute_shared_secret( &mut self, params: &[SharedSecretParameters], ) -> Result<Vec<u8>, Error>33 pub(crate) fn compute_shared_secret(
34 &mut self,
35 params: &[SharedSecretParameters],
36 ) -> Result<Vec<u8>, Error> {
37 info!("Setting HMAC key from {} shared secret parameters", params.len());
38 let local_params = match &self.shared_secret_params {
39 Some(params) => params,
40 None => return Err(km_err!(HardwareNotYetAvailable, "no local shared secret params")),
41 };
42
43 let context = shared_secret_context(params, local_params)?;
44 let key = hmac::Key(self.imp.ckdf.ckdf(
45 &self.dev.keys.kak()?,
46 kmr_wire::sharedsecret::KEY_AGREEMENT_LABEL.as_bytes(),
47 &[&context],
48 kmr_common::crypto::SHA256_DIGEST_LEN,
49 )?);
50
51 // Potentially hand the negotiated HMAC key off to hardware.
52 self.device_hmac = Some(self.dev.keys.hmac_key_agreed(&key).unwrap_or_else(|| {
53 // Key not installed into hardware, so build & use a local impl.
54 Box::new(SoftDeviceHmac { key })
55 }));
56 self.device_hmac(kmr_wire::sharedsecret::KEY_CHECK_LABEL.as_bytes())
57 }
58 }
59
60 /// Build the shared secret context from the given `params`, which
61 /// is required to include `must_include` (our own parameters).
shared_secret_context( params: &[SharedSecretParameters], must_include: &SharedSecretParameters, ) -> Result<Vec<u8>, crate::Error>62 pub fn shared_secret_context(
63 params: &[SharedSecretParameters],
64 must_include: &SharedSecretParameters,
65 ) -> Result<Vec<u8>, crate::Error> {
66 let mut result = Vec::new();
67 let mut seen = false;
68 for param in params {
69 result.try_extend_from_slice(¶m.seed)?;
70 if param.nonce.len() != 32 {
71 return Err(km_err!(InvalidArgument, "nonce len {} not 32", param.nonce.len()));
72 }
73 result.try_extend_from_slice(¶m.nonce)?;
74 if param == must_include {
75 seen = true;
76 }
77 }
78 if !seen {
79 Err(km_err!(InvalidArgument, "shared secret params missing local value"))
80 } else {
81 Ok(result)
82 }
83 }
84
85 /// Device HMAC implementation that holds the HMAC key in memory.
86 struct SoftDeviceHmac {
87 key: crypto::hmac::Key,
88 }
89
90 impl DeviceHmac for SoftDeviceHmac {
hmac(&self, imp: &dyn crypto::Hmac, data: &[u8]) -> Result<Vec<u8>, Error>91 fn hmac(&self, imp: &dyn crypto::Hmac, data: &[u8]) -> Result<Vec<u8>, Error> {
92 let mut hmac_op = imp.begin(self.key.clone().into(), Digest::Sha256)?;
93 hmac_op.update(data)?;
94 hmac_op.finish()
95 }
96
get_hmac_key(&self) -> Option<crypto::hmac::Key>97 fn get_hmac_key(&self) -> Option<crypto::hmac::Key> {
98 Some(self.key.clone())
99 }
100 }
101