xref: /aosp_15_r20/system/keymint/hal/src/keymint.rs (revision 9860b7637a5f185913c70aa0caabe3ecb78441e4)
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 //! KeyMint HAL device implementation.
16*9860b763SAndroid Build Coastguard Worker 
17*9860b763SAndroid Build Coastguard Worker use crate::binder;
18*9860b763SAndroid Build Coastguard Worker use crate::hal::{
19*9860b763SAndroid Build Coastguard Worker     failed_conversion, keymint, keymint::IKeyMintOperation::IKeyMintOperation,
20*9860b763SAndroid Build Coastguard Worker     secureclock::TimeStampToken::TimeStampToken, Innto, TryInnto,
21*9860b763SAndroid Build Coastguard Worker };
22*9860b763SAndroid Build Coastguard Worker use crate::{ChannelHalService, SerializedChannel};
23*9860b763SAndroid Build Coastguard Worker use kmr_wire::{keymint::KeyParam, AsCborValue, *};
24*9860b763SAndroid Build Coastguard Worker use log::warn;
25*9860b763SAndroid Build Coastguard Worker use std::ffi::CString;
26*9860b763SAndroid Build Coastguard Worker use std::{
27*9860b763SAndroid Build Coastguard Worker     ops::DerefMut,
28*9860b763SAndroid Build Coastguard Worker     sync::{Arc, Mutex, MutexGuard, RwLock},
29*9860b763SAndroid Build Coastguard Worker };
30*9860b763SAndroid Build Coastguard Worker 
31*9860b763SAndroid Build Coastguard Worker /// Maximum overhead size from CBOR serialization of operation messages.
32*9860b763SAndroid Build Coastguard Worker ///
33*9860b763SAndroid Build Coastguard Worker /// A serialized `FinishRequest` includes the following additional bytes over and
34*9860b763SAndroid Build Coastguard Worker /// above the size of the input (at most):
35*9860b763SAndroid Build Coastguard Worker /// -    1: array wrapper (0x86)
36*9860b763SAndroid Build Coastguard Worker ///   -  9: int (0x1b + u64) [op_handle]
37*9860b763SAndroid Build Coastguard Worker ///   -  1: array wrapper (0x81) [input]
38*9860b763SAndroid Build Coastguard Worker ///      -  9: input data length
39*9860b763SAndroid Build Coastguard Worker ///      - XX:  input data
40*9860b763SAndroid Build Coastguard Worker ///   -  1: array wrapper (0x81) [signature]
41*9860b763SAndroid Build Coastguard Worker ///      - 5: signature data length
42*9860b763SAndroid Build Coastguard Worker ///      - 132: signature data (P-521 point)
43*9860b763SAndroid Build Coastguard Worker ///   -  1: array wrapper (0x81) [auth_token]
44*9860b763SAndroid Build Coastguard Worker ///      -  9: int (0x1b + u64) [challenge]
45*9860b763SAndroid Build Coastguard Worker ///      -  9: int (0x1b + u64) [user_id]
46*9860b763SAndroid Build Coastguard Worker ///      -  9: int (0x1b + u64) [authenticator_id]
47*9860b763SAndroid Build Coastguard Worker ///      -  9: int (0x1b + u64) [authenticator_type]
48*9860b763SAndroid Build Coastguard Worker ///      -  1: array wrapper (0x81)[timestamp]
49*9860b763SAndroid Build Coastguard Worker ///         -  9: int (0x1b + u64) [user_id]
50*9860b763SAndroid Build Coastguard Worker ///      -  2: bstr header [mac]
51*9860b763SAndroid Build Coastguard Worker ///      - 32: bstr [mac]
52*9860b763SAndroid Build Coastguard Worker ///   -  1: array wrapper (0x81) [timestamp_token]
53*9860b763SAndroid Build Coastguard Worker ///      -  1: array wrapper [TimeStampToken]
54*9860b763SAndroid Build Coastguard Worker ///         -  9: int (0x1b + u64) [challenge]
55*9860b763SAndroid Build Coastguard Worker ///         -  1: array wrapper (0x81)[timestamp]
56*9860b763SAndroid Build Coastguard Worker ///            -  9: int (0x1b + u64) [user_id]
57*9860b763SAndroid Build Coastguard Worker ///         -  2: bstr header [mac]
58*9860b763SAndroid Build Coastguard Worker ///         - 32: bstr [mac]
59*9860b763SAndroid Build Coastguard Worker ///   -  1: array wrapper (0x81) [confirmation_token]
60*9860b763SAndroid Build Coastguard Worker ///      -  2: bstr header [confirmation token]
61*9860b763SAndroid Build Coastguard Worker ///      - 32: bstr [confirmation token (HMAC-SHA256)]
62*9860b763SAndroid Build Coastguard Worker ///
63*9860b763SAndroid Build Coastguard Worker /// Add some leeway in case encodings change.
64*9860b763SAndroid Build Coastguard Worker pub const MAX_CBOR_OVERHEAD: usize = 350;
65*9860b763SAndroid Build Coastguard Worker 
66*9860b763SAndroid Build Coastguard Worker /// IKeyMintDevice implementation which converts all method invocations to serialized
67*9860b763SAndroid Build Coastguard Worker /// requests that are sent down the associated channel.
68*9860b763SAndroid Build Coastguard Worker pub struct Device<T: SerializedChannel + 'static> {
69*9860b763SAndroid Build Coastguard Worker     channel: Arc<Mutex<T>>,
70*9860b763SAndroid Build Coastguard Worker }
71*9860b763SAndroid Build Coastguard Worker 
72*9860b763SAndroid Build Coastguard Worker impl<T: SerializedChannel + 'static> Device<T> {
73*9860b763SAndroid Build Coastguard Worker     /// Construct a new instance that uses the provided channel.
new(channel: Arc<Mutex<T>>) -> Self74*9860b763SAndroid Build Coastguard Worker     pub fn new(channel: Arc<Mutex<T>>) -> Self {
75*9860b763SAndroid Build Coastguard Worker         Self { channel }
76*9860b763SAndroid Build Coastguard Worker     }
77*9860b763SAndroid Build Coastguard Worker 
78*9860b763SAndroid Build Coastguard Worker     /// Create a new instance wrapped in a proxy object.
new_as_binder( channel: Arc<Mutex<T>>, ) -> binder::Strong<dyn keymint::IKeyMintDevice::IKeyMintDevice>79*9860b763SAndroid Build Coastguard Worker     pub fn new_as_binder(
80*9860b763SAndroid Build Coastguard Worker         channel: Arc<Mutex<T>>,
81*9860b763SAndroid Build Coastguard Worker     ) -> binder::Strong<dyn keymint::IKeyMintDevice::IKeyMintDevice> {
82*9860b763SAndroid Build Coastguard Worker         keymint::IKeyMintDevice::BnKeyMintDevice::new_binder(
83*9860b763SAndroid Build Coastguard Worker             Self::new(channel),
84*9860b763SAndroid Build Coastguard Worker             binder::BinderFeatures::default(),
85*9860b763SAndroid Build Coastguard Worker         )
86*9860b763SAndroid Build Coastguard Worker     }
87*9860b763SAndroid Build Coastguard Worker }
88*9860b763SAndroid Build Coastguard Worker 
89*9860b763SAndroid Build Coastguard Worker impl<T: SerializedChannel> ChannelHalService<T> for Device<T> {
channel(&self) -> MutexGuard<T>90*9860b763SAndroid Build Coastguard Worker     fn channel(&self) -> MutexGuard<T> {
91*9860b763SAndroid Build Coastguard Worker         self.channel.lock().unwrap()
92*9860b763SAndroid Build Coastguard Worker     }
93*9860b763SAndroid Build Coastguard Worker }
94*9860b763SAndroid Build Coastguard Worker 
95*9860b763SAndroid Build Coastguard Worker impl<T: SerializedChannel> binder::Interface for Device<T> {}
96*9860b763SAndroid Build Coastguard Worker 
97*9860b763SAndroid Build Coastguard Worker impl<T: SerializedChannel> keymint::IKeyMintDevice::IKeyMintDevice for Device<T> {
getHardwareInfo(&self) -> binder::Result<keymint::KeyMintHardwareInfo::KeyMintHardwareInfo>98*9860b763SAndroid Build Coastguard Worker     fn getHardwareInfo(&self) -> binder::Result<keymint::KeyMintHardwareInfo::KeyMintHardwareInfo> {
99*9860b763SAndroid Build Coastguard Worker         let rsp: GetHardwareInfoResponse = self.execute(GetHardwareInfoRequest {})?;
100*9860b763SAndroid Build Coastguard Worker         Ok(rsp.ret.innto())
101*9860b763SAndroid Build Coastguard Worker     }
addRngEntropy(&self, data: &[u8]) -> binder::Result<()>102*9860b763SAndroid Build Coastguard Worker     fn addRngEntropy(&self, data: &[u8]) -> binder::Result<()> {
103*9860b763SAndroid Build Coastguard Worker         let _rsp: AddRngEntropyResponse =
104*9860b763SAndroid Build Coastguard Worker             self.execute(AddRngEntropyRequest { data: data.to_vec() })?;
105*9860b763SAndroid Build Coastguard Worker         Ok(())
106*9860b763SAndroid Build Coastguard Worker     }
generateKey( &self, keyParams: &[keymint::KeyParameter::KeyParameter], attestationKey: Option<&keymint::AttestationKey::AttestationKey>, ) -> binder::Result<keymint::KeyCreationResult::KeyCreationResult>107*9860b763SAndroid Build Coastguard Worker     fn generateKey(
108*9860b763SAndroid Build Coastguard Worker         &self,
109*9860b763SAndroid Build Coastguard Worker         keyParams: &[keymint::KeyParameter::KeyParameter],
110*9860b763SAndroid Build Coastguard Worker         attestationKey: Option<&keymint::AttestationKey::AttestationKey>,
111*9860b763SAndroid Build Coastguard Worker     ) -> binder::Result<keymint::KeyCreationResult::KeyCreationResult> {
112*9860b763SAndroid Build Coastguard Worker         let rsp: GenerateKeyResponse = self.execute(GenerateKeyRequest {
113*9860b763SAndroid Build Coastguard Worker             key_params: keyParams
114*9860b763SAndroid Build Coastguard Worker                 .iter()
115*9860b763SAndroid Build Coastguard Worker                 .filter_map(|p| p.try_innto().transpose())
116*9860b763SAndroid Build Coastguard Worker                 .collect::<Result<Vec<KeyParam>, _>>()
117*9860b763SAndroid Build Coastguard Worker                 .map_err(failed_conversion)?,
118*9860b763SAndroid Build Coastguard Worker             attestation_key: match attestationKey {
119*9860b763SAndroid Build Coastguard Worker                 None => None,
120*9860b763SAndroid Build Coastguard Worker                 Some(k) => Some(k.clone().try_innto().map_err(failed_conversion)?),
121*9860b763SAndroid Build Coastguard Worker             },
122*9860b763SAndroid Build Coastguard Worker         })?;
123*9860b763SAndroid Build Coastguard Worker         Ok(rsp.ret.innto())
124*9860b763SAndroid Build Coastguard Worker     }
importKey( &self, keyParams: &[keymint::KeyParameter::KeyParameter], keyFormat: keymint::KeyFormat::KeyFormat, keyData: &[u8], attestationKey: Option<&keymint::AttestationKey::AttestationKey>, ) -> binder::Result<keymint::KeyCreationResult::KeyCreationResult>125*9860b763SAndroid Build Coastguard Worker     fn importKey(
126*9860b763SAndroid Build Coastguard Worker         &self,
127*9860b763SAndroid Build Coastguard Worker         keyParams: &[keymint::KeyParameter::KeyParameter],
128*9860b763SAndroid Build Coastguard Worker         keyFormat: keymint::KeyFormat::KeyFormat,
129*9860b763SAndroid Build Coastguard Worker         keyData: &[u8],
130*9860b763SAndroid Build Coastguard Worker         attestationKey: Option<&keymint::AttestationKey::AttestationKey>,
131*9860b763SAndroid Build Coastguard Worker     ) -> binder::Result<keymint::KeyCreationResult::KeyCreationResult> {
132*9860b763SAndroid Build Coastguard Worker         let rsp: ImportKeyResponse = self.execute(ImportKeyRequest {
133*9860b763SAndroid Build Coastguard Worker             key_params: keyParams
134*9860b763SAndroid Build Coastguard Worker                 .iter()
135*9860b763SAndroid Build Coastguard Worker                 .filter_map(|p| p.try_innto().transpose())
136*9860b763SAndroid Build Coastguard Worker                 .collect::<Result<Vec<KeyParam>, _>>()
137*9860b763SAndroid Build Coastguard Worker                 .map_err(failed_conversion)?,
138*9860b763SAndroid Build Coastguard Worker             key_format: keyFormat.try_innto().map_err(failed_conversion)?,
139*9860b763SAndroid Build Coastguard Worker             key_data: keyData.to_vec(),
140*9860b763SAndroid Build Coastguard Worker             attestation_key: match attestationKey {
141*9860b763SAndroid Build Coastguard Worker                 None => None,
142*9860b763SAndroid Build Coastguard Worker                 Some(k) => Some(k.clone().try_innto().map_err(failed_conversion)?),
143*9860b763SAndroid Build Coastguard Worker             },
144*9860b763SAndroid Build Coastguard Worker         })?;
145*9860b763SAndroid Build Coastguard Worker         Ok(rsp.ret.innto())
146*9860b763SAndroid Build Coastguard Worker     }
importWrappedKey( &self, wrappedKeyData: &[u8], wrappingKeyBlob: &[u8], maskingKey: &[u8], unwrappingParams: &[keymint::KeyParameter::KeyParameter], passwordSid: i64, biometricSid: i64, ) -> binder::Result<keymint::KeyCreationResult::KeyCreationResult>147*9860b763SAndroid Build Coastguard Worker     fn importWrappedKey(
148*9860b763SAndroid Build Coastguard Worker         &self,
149*9860b763SAndroid Build Coastguard Worker         wrappedKeyData: &[u8],
150*9860b763SAndroid Build Coastguard Worker         wrappingKeyBlob: &[u8],
151*9860b763SAndroid Build Coastguard Worker         maskingKey: &[u8],
152*9860b763SAndroid Build Coastguard Worker         unwrappingParams: &[keymint::KeyParameter::KeyParameter],
153*9860b763SAndroid Build Coastguard Worker         passwordSid: i64,
154*9860b763SAndroid Build Coastguard Worker         biometricSid: i64,
155*9860b763SAndroid Build Coastguard Worker     ) -> binder::Result<keymint::KeyCreationResult::KeyCreationResult> {
156*9860b763SAndroid Build Coastguard Worker         let rsp: ImportWrappedKeyResponse = self.execute(ImportWrappedKeyRequest {
157*9860b763SAndroid Build Coastguard Worker             wrapped_key_data: wrappedKeyData.to_vec(),
158*9860b763SAndroid Build Coastguard Worker             wrapping_key_blob: wrappingKeyBlob.to_vec(),
159*9860b763SAndroid Build Coastguard Worker             masking_key: maskingKey.to_vec(),
160*9860b763SAndroid Build Coastguard Worker             unwrapping_params: unwrappingParams
161*9860b763SAndroid Build Coastguard Worker                 .iter()
162*9860b763SAndroid Build Coastguard Worker                 .filter_map(|p| p.try_innto().transpose())
163*9860b763SAndroid Build Coastguard Worker                 .collect::<Result<Vec<KeyParam>, _>>()
164*9860b763SAndroid Build Coastguard Worker                 .map_err(failed_conversion)?,
165*9860b763SAndroid Build Coastguard Worker             password_sid: passwordSid,
166*9860b763SAndroid Build Coastguard Worker             biometric_sid: biometricSid,
167*9860b763SAndroid Build Coastguard Worker         })?;
168*9860b763SAndroid Build Coastguard Worker         Ok(rsp.ret.innto())
169*9860b763SAndroid Build Coastguard Worker     }
upgradeKey( &self, keyBlobToUpgrade: &[u8], upgradeParams: &[keymint::KeyParameter::KeyParameter], ) -> binder::Result<Vec<u8>>170*9860b763SAndroid Build Coastguard Worker     fn upgradeKey(
171*9860b763SAndroid Build Coastguard Worker         &self,
172*9860b763SAndroid Build Coastguard Worker         keyBlobToUpgrade: &[u8],
173*9860b763SAndroid Build Coastguard Worker         upgradeParams: &[keymint::KeyParameter::KeyParameter],
174*9860b763SAndroid Build Coastguard Worker     ) -> binder::Result<Vec<u8>> {
175*9860b763SAndroid Build Coastguard Worker         let rsp: UpgradeKeyResponse = self.execute(UpgradeKeyRequest {
176*9860b763SAndroid Build Coastguard Worker             key_blob_to_upgrade: keyBlobToUpgrade.to_vec(),
177*9860b763SAndroid Build Coastguard Worker             upgrade_params: upgradeParams
178*9860b763SAndroid Build Coastguard Worker                 .iter()
179*9860b763SAndroid Build Coastguard Worker                 .filter_map(|p| p.try_innto().transpose())
180*9860b763SAndroid Build Coastguard Worker                 .collect::<Result<Vec<KeyParam>, _>>()
181*9860b763SAndroid Build Coastguard Worker                 .map_err(failed_conversion)?,
182*9860b763SAndroid Build Coastguard Worker         })?;
183*9860b763SAndroid Build Coastguard Worker         Ok(rsp.ret)
184*9860b763SAndroid Build Coastguard Worker     }
deleteKey(&self, keyBlob: &[u8]) -> binder::Result<()>185*9860b763SAndroid Build Coastguard Worker     fn deleteKey(&self, keyBlob: &[u8]) -> binder::Result<()> {
186*9860b763SAndroid Build Coastguard Worker         let _rsp: DeleteKeyResponse =
187*9860b763SAndroid Build Coastguard Worker             self.execute(DeleteKeyRequest { key_blob: keyBlob.to_vec() })?;
188*9860b763SAndroid Build Coastguard Worker         Ok(())
189*9860b763SAndroid Build Coastguard Worker     }
deleteAllKeys(&self) -> binder::Result<()>190*9860b763SAndroid Build Coastguard Worker     fn deleteAllKeys(&self) -> binder::Result<()> {
191*9860b763SAndroid Build Coastguard Worker         let _rsp: DeleteAllKeysResponse = self.execute(DeleteAllKeysRequest {})?;
192*9860b763SAndroid Build Coastguard Worker         Ok(())
193*9860b763SAndroid Build Coastguard Worker     }
destroyAttestationIds(&self) -> binder::Result<()>194*9860b763SAndroid Build Coastguard Worker     fn destroyAttestationIds(&self) -> binder::Result<()> {
195*9860b763SAndroid Build Coastguard Worker         let _rsp: DestroyAttestationIdsResponse = self.execute(DestroyAttestationIdsRequest {})?;
196*9860b763SAndroid Build Coastguard Worker         Ok(())
197*9860b763SAndroid Build Coastguard Worker     }
begin( &self, purpose: keymint::KeyPurpose::KeyPurpose, keyBlob: &[u8], params: &[keymint::KeyParameter::KeyParameter], authToken: Option<&keymint::HardwareAuthToken::HardwareAuthToken>, ) -> binder::Result<keymint::BeginResult::BeginResult>198*9860b763SAndroid Build Coastguard Worker     fn begin(
199*9860b763SAndroid Build Coastguard Worker         &self,
200*9860b763SAndroid Build Coastguard Worker         purpose: keymint::KeyPurpose::KeyPurpose,
201*9860b763SAndroid Build Coastguard Worker         keyBlob: &[u8],
202*9860b763SAndroid Build Coastguard Worker         params: &[keymint::KeyParameter::KeyParameter],
203*9860b763SAndroid Build Coastguard Worker         authToken: Option<&keymint::HardwareAuthToken::HardwareAuthToken>,
204*9860b763SAndroid Build Coastguard Worker     ) -> binder::Result<keymint::BeginResult::BeginResult> {
205*9860b763SAndroid Build Coastguard Worker         let rsp: BeginResponse = self.execute(BeginRequest {
206*9860b763SAndroid Build Coastguard Worker             purpose: purpose.try_innto().map_err(failed_conversion)?,
207*9860b763SAndroid Build Coastguard Worker             key_blob: keyBlob.to_vec(),
208*9860b763SAndroid Build Coastguard Worker             params: params
209*9860b763SAndroid Build Coastguard Worker                 .iter()
210*9860b763SAndroid Build Coastguard Worker                 .filter_map(|p| p.try_innto().transpose())
211*9860b763SAndroid Build Coastguard Worker                 .collect::<Result<Vec<KeyParam>, _>>()
212*9860b763SAndroid Build Coastguard Worker                 .map_err(failed_conversion)?,
213*9860b763SAndroid Build Coastguard Worker             auth_token: match authToken {
214*9860b763SAndroid Build Coastguard Worker                 None => None,
215*9860b763SAndroid Build Coastguard Worker                 Some(t) => Some(t.clone().try_innto().map_err(failed_conversion)?),
216*9860b763SAndroid Build Coastguard Worker             },
217*9860b763SAndroid Build Coastguard Worker         })?;
218*9860b763SAndroid Build Coastguard Worker         // The `begin()` method is a special case.
219*9860b763SAndroid Build Coastguard Worker         // - Internally, the in-progress operation is identified by an opaque handle value.
220*9860b763SAndroid Build Coastguard Worker         // - Externally, the in-progress operation is represented as an `IKeyMintOperation` Binder
221*9860b763SAndroid Build Coastguard Worker         //   object.
222*9860b763SAndroid Build Coastguard Worker         // The `WireOperation` struct contains the former, and acts as the latter.
223*9860b763SAndroid Build Coastguard Worker         let op = Operation::new_as_binder(self.channel.clone(), rsp.ret.op_handle);
224*9860b763SAndroid Build Coastguard Worker         Ok(keymint::BeginResult::BeginResult {
225*9860b763SAndroid Build Coastguard Worker             challenge: rsp.ret.challenge,
226*9860b763SAndroid Build Coastguard Worker             params: rsp.ret.params.innto(),
227*9860b763SAndroid Build Coastguard Worker             operation: Some(op),
228*9860b763SAndroid Build Coastguard Worker         })
229*9860b763SAndroid Build Coastguard Worker     }
deviceLocked( &self, _passwordOnly: bool, _timestampToken: Option<&TimeStampToken>, ) -> binder::Result<()>230*9860b763SAndroid Build Coastguard Worker     fn deviceLocked(
231*9860b763SAndroid Build Coastguard Worker         &self,
232*9860b763SAndroid Build Coastguard Worker         _passwordOnly: bool,
233*9860b763SAndroid Build Coastguard Worker         _timestampToken: Option<&TimeStampToken>,
234*9860b763SAndroid Build Coastguard Worker     ) -> binder::Result<()> {
235*9860b763SAndroid Build Coastguard Worker         // This method is deprecated and unused, so just fail with error UNIMPLEMENTED.
236*9860b763SAndroid Build Coastguard Worker         warn!("Deprecated method devicedLocked() was called");
237*9860b763SAndroid Build Coastguard Worker         Err(binder::Status::new_service_specific_error(
238*9860b763SAndroid Build Coastguard Worker             keymint::ErrorCode::ErrorCode::UNIMPLEMENTED.0,
239*9860b763SAndroid Build Coastguard Worker             Some(&CString::new("Deprecated method deviceLocked() is not implemented").unwrap()),
240*9860b763SAndroid Build Coastguard Worker         ))
241*9860b763SAndroid Build Coastguard Worker     }
earlyBootEnded(&self) -> binder::Result<()>242*9860b763SAndroid Build Coastguard Worker     fn earlyBootEnded(&self) -> binder::Result<()> {
243*9860b763SAndroid Build Coastguard Worker         let _rsp: EarlyBootEndedResponse = self.execute(EarlyBootEndedRequest {})?;
244*9860b763SAndroid Build Coastguard Worker         Ok(())
245*9860b763SAndroid Build Coastguard Worker     }
convertStorageKeyToEphemeral(&self, storageKeyBlob: &[u8]) -> binder::Result<Vec<u8>>246*9860b763SAndroid Build Coastguard Worker     fn convertStorageKeyToEphemeral(&self, storageKeyBlob: &[u8]) -> binder::Result<Vec<u8>> {
247*9860b763SAndroid Build Coastguard Worker         let rsp: ConvertStorageKeyToEphemeralResponse =
248*9860b763SAndroid Build Coastguard Worker             self.execute(ConvertStorageKeyToEphemeralRequest {
249*9860b763SAndroid Build Coastguard Worker                 storage_key_blob: storageKeyBlob.to_vec(),
250*9860b763SAndroid Build Coastguard Worker             })?;
251*9860b763SAndroid Build Coastguard Worker         Ok(rsp.ret)
252*9860b763SAndroid Build Coastguard Worker     }
getKeyCharacteristics( &self, keyBlob: &[u8], appId: &[u8], appData: &[u8], ) -> binder::Result<Vec<keymint::KeyCharacteristics::KeyCharacteristics>>253*9860b763SAndroid Build Coastguard Worker     fn getKeyCharacteristics(
254*9860b763SAndroid Build Coastguard Worker         &self,
255*9860b763SAndroid Build Coastguard Worker         keyBlob: &[u8],
256*9860b763SAndroid Build Coastguard Worker         appId: &[u8],
257*9860b763SAndroid Build Coastguard Worker         appData: &[u8],
258*9860b763SAndroid Build Coastguard Worker     ) -> binder::Result<Vec<keymint::KeyCharacteristics::KeyCharacteristics>> {
259*9860b763SAndroid Build Coastguard Worker         let rsp: GetKeyCharacteristicsResponse = self.execute(GetKeyCharacteristicsRequest {
260*9860b763SAndroid Build Coastguard Worker             key_blob: keyBlob.to_vec(),
261*9860b763SAndroid Build Coastguard Worker             app_id: appId.to_vec(),
262*9860b763SAndroid Build Coastguard Worker             app_data: appData.to_vec(),
263*9860b763SAndroid Build Coastguard Worker         })?;
264*9860b763SAndroid Build Coastguard Worker         Ok(rsp.ret.innto())
265*9860b763SAndroid Build Coastguard Worker     }
266*9860b763SAndroid Build Coastguard Worker     #[cfg(feature = "hal_v2")]
getRootOfTrustChallenge(&self) -> binder::Result<[u8; 16]>267*9860b763SAndroid Build Coastguard Worker     fn getRootOfTrustChallenge(&self) -> binder::Result<[u8; 16]> {
268*9860b763SAndroid Build Coastguard Worker         let rsp: GetRootOfTrustChallengeResponse =
269*9860b763SAndroid Build Coastguard Worker             self.execute(GetRootOfTrustChallengeRequest {})?;
270*9860b763SAndroid Build Coastguard Worker         Ok(rsp.ret)
271*9860b763SAndroid Build Coastguard Worker     }
272*9860b763SAndroid Build Coastguard Worker     #[cfg(feature = "hal_v2")]
getRootOfTrust(&self, challenge: &[u8; 16]) -> binder::Result<Vec<u8>>273*9860b763SAndroid Build Coastguard Worker     fn getRootOfTrust(&self, challenge: &[u8; 16]) -> binder::Result<Vec<u8>> {
274*9860b763SAndroid Build Coastguard Worker         let rsp: GetRootOfTrustResponse =
275*9860b763SAndroid Build Coastguard Worker             self.execute(GetRootOfTrustRequest { challenge: *challenge })?;
276*9860b763SAndroid Build Coastguard Worker         Ok(rsp.ret)
277*9860b763SAndroid Build Coastguard Worker     }
278*9860b763SAndroid Build Coastguard Worker     #[cfg(feature = "hal_v2")]
sendRootOfTrust(&self, root_of_trust: &[u8]) -> binder::Result<()>279*9860b763SAndroid Build Coastguard Worker     fn sendRootOfTrust(&self, root_of_trust: &[u8]) -> binder::Result<()> {
280*9860b763SAndroid Build Coastguard Worker         let _rsp: SendRootOfTrustResponse =
281*9860b763SAndroid Build Coastguard Worker             self.execute(SendRootOfTrustRequest { root_of_trust: root_of_trust.to_vec() })?;
282*9860b763SAndroid Build Coastguard Worker         Ok(())
283*9860b763SAndroid Build Coastguard Worker     }
284*9860b763SAndroid Build Coastguard Worker     #[cfg(feature = "hal_v4")]
setAdditionalAttestationInfo( &self, info: &[keymint::KeyParameter::KeyParameter], ) -> binder::Result<()>285*9860b763SAndroid Build Coastguard Worker     fn setAdditionalAttestationInfo(
286*9860b763SAndroid Build Coastguard Worker         &self,
287*9860b763SAndroid Build Coastguard Worker         info: &[keymint::KeyParameter::KeyParameter],
288*9860b763SAndroid Build Coastguard Worker     ) -> binder::Result<()> {
289*9860b763SAndroid Build Coastguard Worker         let _rsp: SetAdditionalAttestationInfoResponse =
290*9860b763SAndroid Build Coastguard Worker             self.execute(SetAdditionalAttestationInfoRequest {
291*9860b763SAndroid Build Coastguard Worker                 info: info
292*9860b763SAndroid Build Coastguard Worker                     .iter()
293*9860b763SAndroid Build Coastguard Worker                     .filter_map(|p| p.try_innto().transpose())
294*9860b763SAndroid Build Coastguard Worker                     .collect::<Result<Vec<KeyParam>, _>>()
295*9860b763SAndroid Build Coastguard Worker                     .map_err(failed_conversion)?,
296*9860b763SAndroid Build Coastguard Worker             })?;
297*9860b763SAndroid Build Coastguard Worker         Ok(())
298*9860b763SAndroid Build Coastguard Worker     }
299*9860b763SAndroid Build Coastguard Worker }
300*9860b763SAndroid Build Coastguard Worker 
301*9860b763SAndroid Build Coastguard Worker /// Representation of an in-progress KeyMint operation on a `SerializedChannel`.
302*9860b763SAndroid Build Coastguard Worker #[derive(Debug)]
303*9860b763SAndroid Build Coastguard Worker struct Operation<T: SerializedChannel + 'static> {
304*9860b763SAndroid Build Coastguard Worker     channel: Arc<Mutex<T>>,
305*9860b763SAndroid Build Coastguard Worker     op_handle: RwLock<Option<i64>>,
306*9860b763SAndroid Build Coastguard Worker }
307*9860b763SAndroid Build Coastguard Worker 
308*9860b763SAndroid Build Coastguard Worker impl<T: SerializedChannel + 'static> Drop for Operation<T> {
drop(&mut self)309*9860b763SAndroid Build Coastguard Worker     fn drop(&mut self) {
310*9860b763SAndroid Build Coastguard Worker         // Ensure that the TA is kept up-to-date by calling `abort()`, but ignore the result.
311*9860b763SAndroid Build Coastguard Worker         let _ = self.abort();
312*9860b763SAndroid Build Coastguard Worker     }
313*9860b763SAndroid Build Coastguard Worker }
314*9860b763SAndroid Build Coastguard Worker 
315*9860b763SAndroid Build Coastguard Worker impl<T: SerializedChannel> ChannelHalService<T> for Operation<T> {
channel(&self) -> MutexGuard<T>316*9860b763SAndroid Build Coastguard Worker     fn channel(&self) -> MutexGuard<T> {
317*9860b763SAndroid Build Coastguard Worker         self.channel.lock().unwrap()
318*9860b763SAndroid Build Coastguard Worker     }
319*9860b763SAndroid Build Coastguard Worker 
320*9860b763SAndroid Build Coastguard Worker     /// Execute the given request as part of the operation.  If the request fails, the operation is
321*9860b763SAndroid Build Coastguard Worker     /// invalidated (and any future requests for the operation will fail).
execute<R, S>(&self, req: R) -> binder::Result<S> where R: AsCborValue + Code<KeyMintOperation>, S: AsCborValue + Code<KeyMintOperation>,322*9860b763SAndroid Build Coastguard Worker     fn execute<R, S>(&self, req: R) -> binder::Result<S>
323*9860b763SAndroid Build Coastguard Worker     where
324*9860b763SAndroid Build Coastguard Worker         R: AsCborValue + Code<KeyMintOperation>,
325*9860b763SAndroid Build Coastguard Worker         S: AsCborValue + Code<KeyMintOperation>,
326*9860b763SAndroid Build Coastguard Worker     {
327*9860b763SAndroid Build Coastguard Worker         let result = super::channel_execute(self.channel().deref_mut(), req);
328*9860b763SAndroid Build Coastguard Worker         if result.is_err() {
329*9860b763SAndroid Build Coastguard Worker             // Any failed method on an operation terminates the operation.
330*9860b763SAndroid Build Coastguard Worker             self.invalidate();
331*9860b763SAndroid Build Coastguard Worker         }
332*9860b763SAndroid Build Coastguard Worker         result
333*9860b763SAndroid Build Coastguard Worker     }
334*9860b763SAndroid Build Coastguard Worker }
335*9860b763SAndroid Build Coastguard Worker 
336*9860b763SAndroid Build Coastguard Worker impl<T: SerializedChannel> binder::Interface for Operation<T> {}
337*9860b763SAndroid Build Coastguard Worker 
338*9860b763SAndroid Build Coastguard Worker impl<T: SerializedChannel + 'static> Operation<T> {
339*9860b763SAndroid Build Coastguard Worker     /// Create a new `Operation` wrapped in a proxy object.
new_as_binder( channel: Arc<Mutex<T>>, op_handle: i64, ) -> binder::Strong<dyn keymint::IKeyMintOperation::IKeyMintOperation>340*9860b763SAndroid Build Coastguard Worker     fn new_as_binder(
341*9860b763SAndroid Build Coastguard Worker         channel: Arc<Mutex<T>>,
342*9860b763SAndroid Build Coastguard Worker         op_handle: i64,
343*9860b763SAndroid Build Coastguard Worker     ) -> binder::Strong<dyn keymint::IKeyMintOperation::IKeyMintOperation> {
344*9860b763SAndroid Build Coastguard Worker         let op = Self { channel, op_handle: RwLock::new(Some(op_handle)) };
345*9860b763SAndroid Build Coastguard Worker         keymint::IKeyMintOperation::BnKeyMintOperation::new_binder(
346*9860b763SAndroid Build Coastguard Worker             op,
347*9860b763SAndroid Build Coastguard Worker             binder::BinderFeatures::default(),
348*9860b763SAndroid Build Coastguard Worker         )
349*9860b763SAndroid Build Coastguard Worker     }
350*9860b763SAndroid Build Coastguard Worker }
351*9860b763SAndroid Build Coastguard Worker 
352*9860b763SAndroid Build Coastguard Worker impl<T: SerializedChannel> Operation<T> {
353*9860b763SAndroid Build Coastguard Worker     // Maximum size allowed for the operation data.
354*9860b763SAndroid Build Coastguard Worker     const MAX_DATA_SIZE: usize = T::MAX_SIZE - MAX_CBOR_OVERHEAD;
355*9860b763SAndroid Build Coastguard Worker 
356*9860b763SAndroid Build Coastguard Worker     /// Invalidate the operation.
invalidate(&self)357*9860b763SAndroid Build Coastguard Worker     fn invalidate(&self) {
358*9860b763SAndroid Build Coastguard Worker         *self.op_handle.write().unwrap() = None;
359*9860b763SAndroid Build Coastguard Worker     }
360*9860b763SAndroid Build Coastguard Worker 
361*9860b763SAndroid Build Coastguard Worker     /// Retrieve the operation handle, if not already failed.
validate_handle(&self) -> binder::Result<i64>362*9860b763SAndroid Build Coastguard Worker     fn validate_handle(&self) -> binder::Result<i64> {
363*9860b763SAndroid Build Coastguard Worker         self.op_handle.read().unwrap().ok_or_else(|| {
364*9860b763SAndroid Build Coastguard Worker             binder::Status::new_service_specific_error(
365*9860b763SAndroid Build Coastguard Worker                 keymint::ErrorCode::ErrorCode::INVALID_OPERATION_HANDLE.0,
366*9860b763SAndroid Build Coastguard Worker                 Some(&CString::new("Operation handle not valid").unwrap()),
367*9860b763SAndroid Build Coastguard Worker             )
368*9860b763SAndroid Build Coastguard Worker         })
369*9860b763SAndroid Build Coastguard Worker     }
370*9860b763SAndroid Build Coastguard Worker }
371*9860b763SAndroid Build Coastguard Worker 
372*9860b763SAndroid Build Coastguard Worker /// Implement the `IKeyMintOperation` interface for a [`Operation`].  Each method invocation is
373*9860b763SAndroid Build Coastguard Worker /// serialized into a request message that is sent over the `Operation`'s channel, and a
374*9860b763SAndroid Build Coastguard Worker /// corresponding response message is read.  This response message is deserialized back into the
375*9860b763SAndroid Build Coastguard Worker /// method's output value(s).
376*9860b763SAndroid Build Coastguard Worker impl<T: SerializedChannel + 'static> keymint::IKeyMintOperation::IKeyMintOperation
377*9860b763SAndroid Build Coastguard Worker     for Operation<T>
378*9860b763SAndroid Build Coastguard Worker {
updateAad( &self, mut input: &[u8], authToken: Option<&keymint::HardwareAuthToken::HardwareAuthToken>, timeStampToken: Option<&TimeStampToken>, ) -> binder::Result<()>379*9860b763SAndroid Build Coastguard Worker     fn updateAad(
380*9860b763SAndroid Build Coastguard Worker         &self,
381*9860b763SAndroid Build Coastguard Worker         mut input: &[u8],
382*9860b763SAndroid Build Coastguard Worker         authToken: Option<&keymint::HardwareAuthToken::HardwareAuthToken>,
383*9860b763SAndroid Build Coastguard Worker         timeStampToken: Option<&TimeStampToken>,
384*9860b763SAndroid Build Coastguard Worker     ) -> binder::Result<()> {
385*9860b763SAndroid Build Coastguard Worker         let req_template = UpdateAadRequest {
386*9860b763SAndroid Build Coastguard Worker             op_handle: self.validate_handle()?,
387*9860b763SAndroid Build Coastguard Worker             input: vec![],
388*9860b763SAndroid Build Coastguard Worker             auth_token: match authToken {
389*9860b763SAndroid Build Coastguard Worker                 None => None,
390*9860b763SAndroid Build Coastguard Worker                 Some(t) => Some(t.clone().try_innto().map_err(failed_conversion)?),
391*9860b763SAndroid Build Coastguard Worker             },
392*9860b763SAndroid Build Coastguard Worker             timestamp_token: timeStampToken.map(|t| t.clone().innto()),
393*9860b763SAndroid Build Coastguard Worker         };
394*9860b763SAndroid Build Coastguard Worker         while !input.is_empty() {
395*9860b763SAndroid Build Coastguard Worker             let mut req = req_template.clone();
396*9860b763SAndroid Build Coastguard Worker             let batch_len = core::cmp::min(Self::MAX_DATA_SIZE, input.len());
397*9860b763SAndroid Build Coastguard Worker             req.input = input[..batch_len].to_vec();
398*9860b763SAndroid Build Coastguard Worker             input = &input[batch_len..];
399*9860b763SAndroid Build Coastguard Worker             let _rsp: UpdateAadResponse = self.execute(req).inspect_err(|_| {
400*9860b763SAndroid Build Coastguard Worker                 // Any failure invalidates the operation
401*9860b763SAndroid Build Coastguard Worker                 self.invalidate();
402*9860b763SAndroid Build Coastguard Worker             })?;
403*9860b763SAndroid Build Coastguard Worker         }
404*9860b763SAndroid Build Coastguard Worker         Ok(())
405*9860b763SAndroid Build Coastguard Worker     }
update( &self, mut input: &[u8], authToken: Option<&keymint::HardwareAuthToken::HardwareAuthToken>, timeStampToken: Option<&TimeStampToken>, ) -> binder::Result<Vec<u8>>406*9860b763SAndroid Build Coastguard Worker     fn update(
407*9860b763SAndroid Build Coastguard Worker         &self,
408*9860b763SAndroid Build Coastguard Worker         mut input: &[u8],
409*9860b763SAndroid Build Coastguard Worker         authToken: Option<&keymint::HardwareAuthToken::HardwareAuthToken>,
410*9860b763SAndroid Build Coastguard Worker         timeStampToken: Option<&TimeStampToken>,
411*9860b763SAndroid Build Coastguard Worker     ) -> binder::Result<Vec<u8>> {
412*9860b763SAndroid Build Coastguard Worker         let req_template = UpdateRequest {
413*9860b763SAndroid Build Coastguard Worker             op_handle: self.validate_handle()?,
414*9860b763SAndroid Build Coastguard Worker             input: input.to_vec(),
415*9860b763SAndroid Build Coastguard Worker             auth_token: match authToken {
416*9860b763SAndroid Build Coastguard Worker                 None => None,
417*9860b763SAndroid Build Coastguard Worker                 Some(t) => Some(t.clone().try_innto().map_err(failed_conversion)?),
418*9860b763SAndroid Build Coastguard Worker             },
419*9860b763SAndroid Build Coastguard Worker             timestamp_token: timeStampToken.map(|t| t.clone().innto()),
420*9860b763SAndroid Build Coastguard Worker         };
421*9860b763SAndroid Build Coastguard Worker         let mut output = vec![];
422*9860b763SAndroid Build Coastguard Worker         while !input.is_empty() {
423*9860b763SAndroid Build Coastguard Worker             let mut req = req_template.clone();
424*9860b763SAndroid Build Coastguard Worker             let batch_len = core::cmp::min(Self::MAX_DATA_SIZE, input.len());
425*9860b763SAndroid Build Coastguard Worker             req.input = input[..batch_len].to_vec();
426*9860b763SAndroid Build Coastguard Worker             input = &input[batch_len..];
427*9860b763SAndroid Build Coastguard Worker             let rsp: UpdateResponse = self.execute(req).inspect_err(|_| {
428*9860b763SAndroid Build Coastguard Worker                 self.invalidate();
429*9860b763SAndroid Build Coastguard Worker             })?;
430*9860b763SAndroid Build Coastguard Worker             output.extend_from_slice(&rsp.ret);
431*9860b763SAndroid Build Coastguard Worker         }
432*9860b763SAndroid Build Coastguard Worker         Ok(output)
433*9860b763SAndroid Build Coastguard Worker     }
finish( &self, input: Option<&[u8]>, signature: Option<&[u8]>, authToken: Option<&keymint::HardwareAuthToken::HardwareAuthToken>, timestampToken: Option<&TimeStampToken>, confirmationToken: Option<&[u8]>, ) -> binder::Result<Vec<u8>>434*9860b763SAndroid Build Coastguard Worker     fn finish(
435*9860b763SAndroid Build Coastguard Worker         &self,
436*9860b763SAndroid Build Coastguard Worker         input: Option<&[u8]>,
437*9860b763SAndroid Build Coastguard Worker         signature: Option<&[u8]>,
438*9860b763SAndroid Build Coastguard Worker         authToken: Option<&keymint::HardwareAuthToken::HardwareAuthToken>,
439*9860b763SAndroid Build Coastguard Worker         timestampToken: Option<&TimeStampToken>,
440*9860b763SAndroid Build Coastguard Worker         confirmationToken: Option<&[u8]>,
441*9860b763SAndroid Build Coastguard Worker     ) -> binder::Result<Vec<u8>> {
442*9860b763SAndroid Build Coastguard Worker         let op_handle = self.validate_handle()?;
443*9860b763SAndroid Build Coastguard Worker         let auth_token = match authToken {
444*9860b763SAndroid Build Coastguard Worker             None => None,
445*9860b763SAndroid Build Coastguard Worker             Some(t) => Some(t.clone().try_innto().map_err(failed_conversion)?),
446*9860b763SAndroid Build Coastguard Worker         };
447*9860b763SAndroid Build Coastguard Worker         let timestamp_token = timestampToken.map(|t| t.clone().innto());
448*9860b763SAndroid Build Coastguard Worker         let confirmation_token = confirmationToken.map(|v| v.to_vec());
449*9860b763SAndroid Build Coastguard Worker 
450*9860b763SAndroid Build Coastguard Worker         let mut output = vec![];
451*9860b763SAndroid Build Coastguard Worker         let result: binder::Result<FinishResponse> = if let Some(mut input) = input {
452*9860b763SAndroid Build Coastguard Worker             let MAX_DATA_SIZE = Self::MAX_DATA_SIZE;
453*9860b763SAndroid Build Coastguard Worker             while input.len() > MAX_DATA_SIZE {
454*9860b763SAndroid Build Coastguard Worker                 let req = UpdateRequest {
455*9860b763SAndroid Build Coastguard Worker                     op_handle,
456*9860b763SAndroid Build Coastguard Worker                     input: input[..MAX_DATA_SIZE].to_vec(),
457*9860b763SAndroid Build Coastguard Worker                     auth_token: auth_token.clone(),
458*9860b763SAndroid Build Coastguard Worker                     timestamp_token: timestamp_token.clone(),
459*9860b763SAndroid Build Coastguard Worker                 };
460*9860b763SAndroid Build Coastguard Worker                 input = &input[MAX_DATA_SIZE..];
461*9860b763SAndroid Build Coastguard Worker                 let rsp: UpdateResponse = self.execute(req).inspect_err(|_| {
462*9860b763SAndroid Build Coastguard Worker                     self.invalidate();
463*9860b763SAndroid Build Coastguard Worker                 })?;
464*9860b763SAndroid Build Coastguard Worker                 output.extend_from_slice(&rsp.ret);
465*9860b763SAndroid Build Coastguard Worker             }
466*9860b763SAndroid Build Coastguard Worker 
467*9860b763SAndroid Build Coastguard Worker             self.execute(FinishRequest {
468*9860b763SAndroid Build Coastguard Worker                 op_handle,
469*9860b763SAndroid Build Coastguard Worker                 input: Some(input.to_vec()),
470*9860b763SAndroid Build Coastguard Worker                 signature: signature.map(|v| v.to_vec()),
471*9860b763SAndroid Build Coastguard Worker                 auth_token,
472*9860b763SAndroid Build Coastguard Worker                 timestamp_token,
473*9860b763SAndroid Build Coastguard Worker                 confirmation_token,
474*9860b763SAndroid Build Coastguard Worker             })
475*9860b763SAndroid Build Coastguard Worker         } else {
476*9860b763SAndroid Build Coastguard Worker             self.execute(FinishRequest {
477*9860b763SAndroid Build Coastguard Worker                 op_handle,
478*9860b763SAndroid Build Coastguard Worker                 input: None,
479*9860b763SAndroid Build Coastguard Worker                 signature: signature.map(|v| v.to_vec()),
480*9860b763SAndroid Build Coastguard Worker                 auth_token,
481*9860b763SAndroid Build Coastguard Worker                 timestamp_token,
482*9860b763SAndroid Build Coastguard Worker                 confirmation_token,
483*9860b763SAndroid Build Coastguard Worker             })
484*9860b763SAndroid Build Coastguard Worker         };
485*9860b763SAndroid Build Coastguard Worker         // Finish always invalidates the operation.
486*9860b763SAndroid Build Coastguard Worker         self.invalidate();
487*9860b763SAndroid Build Coastguard Worker         result.map(|rsp| {
488*9860b763SAndroid Build Coastguard Worker             output.extend_from_slice(&rsp.ret);
489*9860b763SAndroid Build Coastguard Worker             output
490*9860b763SAndroid Build Coastguard Worker         })
491*9860b763SAndroid Build Coastguard Worker     }
abort(&self) -> binder::Result<()>492*9860b763SAndroid Build Coastguard Worker     fn abort(&self) -> binder::Result<()> {
493*9860b763SAndroid Build Coastguard Worker         let result: binder::Result<AbortResponse> =
494*9860b763SAndroid Build Coastguard Worker             self.execute(AbortRequest { op_handle: self.validate_handle()? });
495*9860b763SAndroid Build Coastguard Worker         // Abort always invalidates the operation.
496*9860b763SAndroid Build Coastguard Worker         self.invalidate();
497*9860b763SAndroid Build Coastguard Worker         let _ = result?;
498*9860b763SAndroid Build Coastguard Worker         Ok(())
499*9860b763SAndroid Build Coastguard Worker     }
500*9860b763SAndroid Build Coastguard Worker }
501