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