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