1*e1997b9aSAndroid Build Coastguard Worker // Copyright 2021, The Android Open Source Project 2*e1997b9aSAndroid Build Coastguard Worker // 3*e1997b9aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); 4*e1997b9aSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License. 5*e1997b9aSAndroid Build Coastguard Worker // You may obtain a copy of the License at 6*e1997b9aSAndroid Build Coastguard Worker // 7*e1997b9aSAndroid Build Coastguard Worker // http://www.apache.org/licenses/LICENSE-2.0 8*e1997b9aSAndroid Build Coastguard Worker // 9*e1997b9aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software 10*e1997b9aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, 11*e1997b9aSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*e1997b9aSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and 13*e1997b9aSAndroid Build Coastguard Worker // limitations under the License. 14*e1997b9aSAndroid Build Coastguard Worker 15*e1997b9aSAndroid Build Coastguard Worker //! Provide the [`KeyMintDevice`] wrapper for operating directly on a KeyMint device. 16*e1997b9aSAndroid Build Coastguard Worker 17*e1997b9aSAndroid Build Coastguard Worker use crate::{ 18*e1997b9aSAndroid Build Coastguard Worker database::{ 19*e1997b9aSAndroid Build Coastguard Worker BlobInfo, BlobMetaData, BlobMetaEntry, CertificateInfo, DateTime, KeyEntry, 20*e1997b9aSAndroid Build Coastguard Worker KeyEntryLoadBits, KeyIdGuard, KeyMetaData, KeyMetaEntry, KeyType, KeystoreDB, 21*e1997b9aSAndroid Build Coastguard Worker SubComponentType, Uuid, 22*e1997b9aSAndroid Build Coastguard Worker }, 23*e1997b9aSAndroid Build Coastguard Worker error::{map_km_error, Error, ErrorCode}, 24*e1997b9aSAndroid Build Coastguard Worker globals::get_keymint_device, 25*e1997b9aSAndroid Build Coastguard Worker ks_err, 26*e1997b9aSAndroid Build Coastguard Worker super_key::KeyBlob, 27*e1997b9aSAndroid Build Coastguard Worker utils::{key_characteristics_to_internal, watchdog as wd, AID_KEYSTORE}, 28*e1997b9aSAndroid Build Coastguard Worker }; 29*e1997b9aSAndroid Build Coastguard Worker use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{ 30*e1997b9aSAndroid Build Coastguard Worker HardwareAuthToken::HardwareAuthToken, IKeyMintDevice::IKeyMintDevice, 31*e1997b9aSAndroid Build Coastguard Worker IKeyMintOperation::IKeyMintOperation, KeyCharacteristics::KeyCharacteristics, 32*e1997b9aSAndroid Build Coastguard Worker KeyCreationResult::KeyCreationResult, KeyParameter::KeyParameter, KeyPurpose::KeyPurpose, 33*e1997b9aSAndroid Build Coastguard Worker SecurityLevel::SecurityLevel, 34*e1997b9aSAndroid Build Coastguard Worker }; 35*e1997b9aSAndroid Build Coastguard Worker use android_system_keystore2::aidl::android::system::keystore2::{ 36*e1997b9aSAndroid Build Coastguard Worker Domain::Domain, KeyDescriptor::KeyDescriptor, ResponseCode::ResponseCode, 37*e1997b9aSAndroid Build Coastguard Worker }; 38*e1997b9aSAndroid Build Coastguard Worker use anyhow::{Context, Result}; 39*e1997b9aSAndroid Build Coastguard Worker use binder::Strong; 40*e1997b9aSAndroid Build Coastguard Worker 41*e1997b9aSAndroid Build Coastguard Worker /// Wrapper for operating directly on a KeyMint device. 42*e1997b9aSAndroid Build Coastguard Worker /// These methods often mirror methods in [`crate::security_level`]. However 43*e1997b9aSAndroid Build Coastguard Worker /// the functions in [`crate::security_level`] make assumptions that hold, and has side effects 44*e1997b9aSAndroid Build Coastguard Worker /// that make sense, only if called by an external client through binder. 45*e1997b9aSAndroid Build Coastguard Worker /// In addition we are trying to maintain a separation between interface services 46*e1997b9aSAndroid Build Coastguard Worker /// so that the architecture is compatible with a future move to multiple thread pools. 47*e1997b9aSAndroid Build Coastguard Worker /// So the simplest approach today is to write new implementations of them for internal use. 48*e1997b9aSAndroid Build Coastguard Worker /// Because these methods run very early, we don't even try to cooperate with 49*e1997b9aSAndroid Build Coastguard Worker /// the operation slot database; we assume there will be plenty of slots. 50*e1997b9aSAndroid Build Coastguard Worker pub struct KeyMintDevice { 51*e1997b9aSAndroid Build Coastguard Worker km_dev: Strong<dyn IKeyMintDevice>, 52*e1997b9aSAndroid Build Coastguard Worker km_uuid: Uuid, 53*e1997b9aSAndroid Build Coastguard Worker version: i32, 54*e1997b9aSAndroid Build Coastguard Worker security_level: SecurityLevel, 55*e1997b9aSAndroid Build Coastguard Worker } 56*e1997b9aSAndroid Build Coastguard Worker 57*e1997b9aSAndroid Build Coastguard Worker impl KeyMintDevice { 58*e1997b9aSAndroid Build Coastguard Worker /// Version number of KeyMasterDevice@V4_0 59*e1997b9aSAndroid Build Coastguard Worker pub const KEY_MASTER_V4_0: i32 = 40; 60*e1997b9aSAndroid Build Coastguard Worker /// Version number of KeyMasterDevice@V4_1 61*e1997b9aSAndroid Build Coastguard Worker pub const KEY_MASTER_V4_1: i32 = 41; 62*e1997b9aSAndroid Build Coastguard Worker /// Version number of KeyMintDevice@V1 63*e1997b9aSAndroid Build Coastguard Worker pub const KEY_MINT_V1: i32 = 100; 64*e1997b9aSAndroid Build Coastguard Worker /// Version number of KeyMintDevice@V2 65*e1997b9aSAndroid Build Coastguard Worker pub const KEY_MINT_V2: i32 = 200; 66*e1997b9aSAndroid Build Coastguard Worker /// Version number of KeyMintDevice@V3 67*e1997b9aSAndroid Build Coastguard Worker pub const KEY_MINT_V3: i32 = 300; 68*e1997b9aSAndroid Build Coastguard Worker 69*e1997b9aSAndroid Build Coastguard Worker /// Get a [`KeyMintDevice`] for the given [`SecurityLevel`] get(security_level: SecurityLevel) -> Result<KeyMintDevice>70*e1997b9aSAndroid Build Coastguard Worker pub fn get(security_level: SecurityLevel) -> Result<KeyMintDevice> { 71*e1997b9aSAndroid Build Coastguard Worker let (km_dev, hw_info, km_uuid) = 72*e1997b9aSAndroid Build Coastguard Worker get_keymint_device(&security_level).context(ks_err!("get_keymint_device failed"))?; 73*e1997b9aSAndroid Build Coastguard Worker 74*e1997b9aSAndroid Build Coastguard Worker Ok(KeyMintDevice { 75*e1997b9aSAndroid Build Coastguard Worker km_dev, 76*e1997b9aSAndroid Build Coastguard Worker km_uuid, 77*e1997b9aSAndroid Build Coastguard Worker version: hw_info.versionNumber, 78*e1997b9aSAndroid Build Coastguard Worker security_level: hw_info.securityLevel, 79*e1997b9aSAndroid Build Coastguard Worker }) 80*e1997b9aSAndroid Build Coastguard Worker } 81*e1997b9aSAndroid Build Coastguard Worker 82*e1997b9aSAndroid Build Coastguard Worker /// Get a [`KeyMintDevice`] for the given [`SecurityLevel`], return 83*e1997b9aSAndroid Build Coastguard Worker /// [`None`] if the error `HARDWARE_TYPE_UNAVAILABLE` is returned get_or_none(security_level: SecurityLevel) -> Result<Option<KeyMintDevice>>84*e1997b9aSAndroid Build Coastguard Worker pub fn get_or_none(security_level: SecurityLevel) -> Result<Option<KeyMintDevice>> { 85*e1997b9aSAndroid Build Coastguard Worker KeyMintDevice::get(security_level).map(Some).or_else(|e| { 86*e1997b9aSAndroid Build Coastguard Worker match e.root_cause().downcast_ref::<Error>() { 87*e1997b9aSAndroid Build Coastguard Worker Some(Error::Km(ErrorCode::HARDWARE_TYPE_UNAVAILABLE)) => Ok(None), 88*e1997b9aSAndroid Build Coastguard Worker _ => Err(e), 89*e1997b9aSAndroid Build Coastguard Worker } 90*e1997b9aSAndroid Build Coastguard Worker }) 91*e1997b9aSAndroid Build Coastguard Worker } 92*e1997b9aSAndroid Build Coastguard Worker 93*e1997b9aSAndroid Build Coastguard Worker /// Returns the version of the underlying KeyMint/KeyMaster device. version(&self) -> i3294*e1997b9aSAndroid Build Coastguard Worker pub fn version(&self) -> i32 { 95*e1997b9aSAndroid Build Coastguard Worker self.version 96*e1997b9aSAndroid Build Coastguard Worker } 97*e1997b9aSAndroid Build Coastguard Worker 98*e1997b9aSAndroid Build Coastguard Worker /// Returns the self advertised security level of the KeyMint device. 99*e1997b9aSAndroid Build Coastguard Worker /// This may differ from the requested security level if the best security level 100*e1997b9aSAndroid Build Coastguard Worker /// on the device is Software. security_level(&self) -> SecurityLevel101*e1997b9aSAndroid Build Coastguard Worker pub fn security_level(&self) -> SecurityLevel { 102*e1997b9aSAndroid Build Coastguard Worker self.security_level 103*e1997b9aSAndroid Build Coastguard Worker } 104*e1997b9aSAndroid Build Coastguard Worker 105*e1997b9aSAndroid Build Coastguard Worker /// Create a KM key and store in the database. create_and_store_key<F>( &self, db: &mut KeystoreDB, key_desc: &KeyDescriptor, key_type: KeyType, creator: F, ) -> Result<()> where F: FnOnce(&Strong<dyn IKeyMintDevice>) -> Result<KeyCreationResult, binder::Status>,106*e1997b9aSAndroid Build Coastguard Worker pub fn create_and_store_key<F>( 107*e1997b9aSAndroid Build Coastguard Worker &self, 108*e1997b9aSAndroid Build Coastguard Worker db: &mut KeystoreDB, 109*e1997b9aSAndroid Build Coastguard Worker key_desc: &KeyDescriptor, 110*e1997b9aSAndroid Build Coastguard Worker key_type: KeyType, 111*e1997b9aSAndroid Build Coastguard Worker creator: F, 112*e1997b9aSAndroid Build Coastguard Worker ) -> Result<()> 113*e1997b9aSAndroid Build Coastguard Worker where 114*e1997b9aSAndroid Build Coastguard Worker F: FnOnce(&Strong<dyn IKeyMintDevice>) -> Result<KeyCreationResult, binder::Status>, 115*e1997b9aSAndroid Build Coastguard Worker { 116*e1997b9aSAndroid Build Coastguard Worker let creation_result = 117*e1997b9aSAndroid Build Coastguard Worker map_km_error(creator(&self.km_dev)).context(ks_err!("creator failed"))?; 118*e1997b9aSAndroid Build Coastguard Worker let key_parameters = key_characteristics_to_internal(creation_result.keyCharacteristics); 119*e1997b9aSAndroid Build Coastguard Worker 120*e1997b9aSAndroid Build Coastguard Worker let creation_date = DateTime::now().context(ks_err!("DateTime::now() failed"))?; 121*e1997b9aSAndroid Build Coastguard Worker 122*e1997b9aSAndroid Build Coastguard Worker let mut key_metadata = KeyMetaData::new(); 123*e1997b9aSAndroid Build Coastguard Worker key_metadata.add(KeyMetaEntry::CreationDate(creation_date)); 124*e1997b9aSAndroid Build Coastguard Worker let mut blob_metadata = BlobMetaData::new(); 125*e1997b9aSAndroid Build Coastguard Worker blob_metadata.add(BlobMetaEntry::KmUuid(self.km_uuid)); 126*e1997b9aSAndroid Build Coastguard Worker 127*e1997b9aSAndroid Build Coastguard Worker db.store_new_key( 128*e1997b9aSAndroid Build Coastguard Worker key_desc, 129*e1997b9aSAndroid Build Coastguard Worker key_type, 130*e1997b9aSAndroid Build Coastguard Worker &key_parameters, 131*e1997b9aSAndroid Build Coastguard Worker &BlobInfo::new(&creation_result.keyBlob, &blob_metadata), 132*e1997b9aSAndroid Build Coastguard Worker &CertificateInfo::new(None, None), 133*e1997b9aSAndroid Build Coastguard Worker &key_metadata, 134*e1997b9aSAndroid Build Coastguard Worker &self.km_uuid, 135*e1997b9aSAndroid Build Coastguard Worker ) 136*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("store_new_key failed"))?; 137*e1997b9aSAndroid Build Coastguard Worker Ok(()) 138*e1997b9aSAndroid Build Coastguard Worker } 139*e1997b9aSAndroid Build Coastguard Worker 140*e1997b9aSAndroid Build Coastguard Worker /// Generate a KeyDescriptor for internal-use keys. internal_descriptor(alias: String) -> KeyDescriptor141*e1997b9aSAndroid Build Coastguard Worker pub fn internal_descriptor(alias: String) -> KeyDescriptor { 142*e1997b9aSAndroid Build Coastguard Worker KeyDescriptor { 143*e1997b9aSAndroid Build Coastguard Worker domain: Domain::APP, 144*e1997b9aSAndroid Build Coastguard Worker nspace: AID_KEYSTORE as i64, 145*e1997b9aSAndroid Build Coastguard Worker alias: Some(alias), 146*e1997b9aSAndroid Build Coastguard Worker blob: None, 147*e1997b9aSAndroid Build Coastguard Worker } 148*e1997b9aSAndroid Build Coastguard Worker } 149*e1997b9aSAndroid Build Coastguard Worker 150*e1997b9aSAndroid Build Coastguard Worker /// Look up an internal-use key in the database given a key descriptor. lookup_from_desc( db: &mut KeystoreDB, key_desc: &KeyDescriptor, key_type: KeyType, ) -> Result<(KeyIdGuard, KeyEntry)>151*e1997b9aSAndroid Build Coastguard Worker fn lookup_from_desc( 152*e1997b9aSAndroid Build Coastguard Worker db: &mut KeystoreDB, 153*e1997b9aSAndroid Build Coastguard Worker key_desc: &KeyDescriptor, 154*e1997b9aSAndroid Build Coastguard Worker key_type: KeyType, 155*e1997b9aSAndroid Build Coastguard Worker ) -> Result<(KeyIdGuard, KeyEntry)> { 156*e1997b9aSAndroid Build Coastguard Worker db.load_key_entry(key_desc, key_type, KeyEntryLoadBits::KM, AID_KEYSTORE, |_, _| Ok(())) 157*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("load_key_entry failed.")) 158*e1997b9aSAndroid Build Coastguard Worker } 159*e1997b9aSAndroid Build Coastguard Worker 160*e1997b9aSAndroid Build Coastguard Worker /// Look up the key in the database, and return None if it is absent. not_found_is_none( lookup: Result<(KeyIdGuard, KeyEntry)>, ) -> Result<Option<(KeyIdGuard, KeyEntry)>>161*e1997b9aSAndroid Build Coastguard Worker fn not_found_is_none( 162*e1997b9aSAndroid Build Coastguard Worker lookup: Result<(KeyIdGuard, KeyEntry)>, 163*e1997b9aSAndroid Build Coastguard Worker ) -> Result<Option<(KeyIdGuard, KeyEntry)>> { 164*e1997b9aSAndroid Build Coastguard Worker match lookup { 165*e1997b9aSAndroid Build Coastguard Worker Ok(result) => Ok(Some(result)), 166*e1997b9aSAndroid Build Coastguard Worker Err(e) => match e.root_cause().downcast_ref::<Error>() { 167*e1997b9aSAndroid Build Coastguard Worker Some(&Error::Rc(ResponseCode::KEY_NOT_FOUND)) => Ok(None), 168*e1997b9aSAndroid Build Coastguard Worker _ => Err(e), 169*e1997b9aSAndroid Build Coastguard Worker }, 170*e1997b9aSAndroid Build Coastguard Worker } 171*e1997b9aSAndroid Build Coastguard Worker } 172*e1997b9aSAndroid Build Coastguard Worker 173*e1997b9aSAndroid Build Coastguard Worker /// This does the lookup and store in separate transactions; caller must 174*e1997b9aSAndroid Build Coastguard Worker /// hold a lock before calling. lookup_or_generate_key<F>( &self, db: &mut KeystoreDB, key_desc: &KeyDescriptor, key_type: KeyType, params: &[KeyParameter], validate_characteristics: F, ) -> Result<(KeyIdGuard, KeyBlob)> where F: FnOnce(&[KeyCharacteristics]) -> bool,175*e1997b9aSAndroid Build Coastguard Worker pub fn lookup_or_generate_key<F>( 176*e1997b9aSAndroid Build Coastguard Worker &self, 177*e1997b9aSAndroid Build Coastguard Worker db: &mut KeystoreDB, 178*e1997b9aSAndroid Build Coastguard Worker key_desc: &KeyDescriptor, 179*e1997b9aSAndroid Build Coastguard Worker key_type: KeyType, 180*e1997b9aSAndroid Build Coastguard Worker params: &[KeyParameter], 181*e1997b9aSAndroid Build Coastguard Worker validate_characteristics: F, 182*e1997b9aSAndroid Build Coastguard Worker ) -> Result<(KeyIdGuard, KeyBlob)> 183*e1997b9aSAndroid Build Coastguard Worker where 184*e1997b9aSAndroid Build Coastguard Worker F: FnOnce(&[KeyCharacteristics]) -> bool, 185*e1997b9aSAndroid Build Coastguard Worker { 186*e1997b9aSAndroid Build Coastguard Worker // We use a separate transaction for the lookup than for the store 187*e1997b9aSAndroid Build Coastguard Worker // - to keep the code simple 188*e1997b9aSAndroid Build Coastguard Worker // - because the caller needs to hold a lock in any case 189*e1997b9aSAndroid Build Coastguard Worker // - because it avoids holding database locks during slow 190*e1997b9aSAndroid Build Coastguard Worker // KeyMint operations 191*e1997b9aSAndroid Build Coastguard Worker let lookup = Self::not_found_is_none(Self::lookup_from_desc(db, key_desc, key_type)) 192*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("first lookup failed"))?; 193*e1997b9aSAndroid Build Coastguard Worker 194*e1997b9aSAndroid Build Coastguard Worker if let Some((key_id_guard, mut key_entry)) = lookup { 195*e1997b9aSAndroid Build Coastguard Worker // If the key is associated with a different km instance 196*e1997b9aSAndroid Build Coastguard Worker // or if there is no blob metadata for some reason the key entry 197*e1997b9aSAndroid Build Coastguard Worker // is considered corrupted and needs to be replaced with a new one. 198*e1997b9aSAndroid Build Coastguard Worker let key_blob = key_entry.take_key_blob_info().and_then(|(key_blob, blob_metadata)| { 199*e1997b9aSAndroid Build Coastguard Worker if Some(&self.km_uuid) == blob_metadata.km_uuid() { 200*e1997b9aSAndroid Build Coastguard Worker Some(key_blob) 201*e1997b9aSAndroid Build Coastguard Worker } else { 202*e1997b9aSAndroid Build Coastguard Worker None 203*e1997b9aSAndroid Build Coastguard Worker } 204*e1997b9aSAndroid Build Coastguard Worker }); 205*e1997b9aSAndroid Build Coastguard Worker 206*e1997b9aSAndroid Build Coastguard Worker if let Some(key_blob_vec) = key_blob { 207*e1997b9aSAndroid Build Coastguard Worker let (key_characteristics, key_blob) = self 208*e1997b9aSAndroid Build Coastguard Worker .upgrade_keyblob_if_required_with( 209*e1997b9aSAndroid Build Coastguard Worker db, 210*e1997b9aSAndroid Build Coastguard Worker &key_id_guard, 211*e1997b9aSAndroid Build Coastguard Worker KeyBlob::NonSensitive(key_blob_vec), 212*e1997b9aSAndroid Build Coastguard Worker |key_blob| { 213*e1997b9aSAndroid Build Coastguard Worker map_km_error({ 214*e1997b9aSAndroid Build Coastguard Worker let _wp = wd::watch(concat!( 215*e1997b9aSAndroid Build Coastguard Worker "KeyMintDevice::lookup_or_generate_key: ", 216*e1997b9aSAndroid Build Coastguard Worker "calling IKeyMintDevice::getKeyCharacteristics." 217*e1997b9aSAndroid Build Coastguard Worker )); 218*e1997b9aSAndroid Build Coastguard Worker self.km_dev.getKeyCharacteristics(key_blob, &[], &[]) 219*e1997b9aSAndroid Build Coastguard Worker }) 220*e1997b9aSAndroid Build Coastguard Worker }, 221*e1997b9aSAndroid Build Coastguard Worker ) 222*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("calling getKeyCharacteristics"))?; 223*e1997b9aSAndroid Build Coastguard Worker 224*e1997b9aSAndroid Build Coastguard Worker if validate_characteristics(&key_characteristics) { 225*e1997b9aSAndroid Build Coastguard Worker return Ok((key_id_guard, key_blob)); 226*e1997b9aSAndroid Build Coastguard Worker } 227*e1997b9aSAndroid Build Coastguard Worker 228*e1997b9aSAndroid Build Coastguard Worker // If this point is reached the existing key is considered outdated or corrupted 229*e1997b9aSAndroid Build Coastguard Worker // in some way. It will be replaced with a new key below. 230*e1997b9aSAndroid Build Coastguard Worker }; 231*e1997b9aSAndroid Build Coastguard Worker } 232*e1997b9aSAndroid Build Coastguard Worker 233*e1997b9aSAndroid Build Coastguard Worker self.create_and_store_key(db, key_desc, key_type, |km_dev| { 234*e1997b9aSAndroid Build Coastguard Worker km_dev.generateKey(params, None) 235*e1997b9aSAndroid Build Coastguard Worker }) 236*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("generate_and_store_key failed"))?; 237*e1997b9aSAndroid Build Coastguard Worker Self::lookup_from_desc(db, key_desc, key_type) 238*e1997b9aSAndroid Build Coastguard Worker .and_then(|(key_id_guard, mut key_entry)| { 239*e1997b9aSAndroid Build Coastguard Worker Ok(( 240*e1997b9aSAndroid Build Coastguard Worker key_id_guard, 241*e1997b9aSAndroid Build Coastguard Worker key_entry 242*e1997b9aSAndroid Build Coastguard Worker .take_key_blob_info() 243*e1997b9aSAndroid Build Coastguard Worker .ok_or(Error::Rc(ResponseCode::KEY_NOT_FOUND)) 244*e1997b9aSAndroid Build Coastguard Worker .map(|(key_blob, _)| KeyBlob::NonSensitive(key_blob)) 245*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("Missing key blob info."))?, 246*e1997b9aSAndroid Build Coastguard Worker )) 247*e1997b9aSAndroid Build Coastguard Worker }) 248*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("second lookup failed")) 249*e1997b9aSAndroid Build Coastguard Worker } 250*e1997b9aSAndroid Build Coastguard Worker 251*e1997b9aSAndroid Build Coastguard Worker /// Call the passed closure; if it returns `KEY_REQUIRES_UPGRADE`, call upgradeKey, and 252*e1997b9aSAndroid Build Coastguard Worker /// write the upgraded key to the database. upgrade_keyblob_if_required_with<'a, T, F>( &self, db: &mut KeystoreDB, key_id_guard: &KeyIdGuard, key_blob: KeyBlob<'a>, f: F, ) -> Result<(T, KeyBlob<'a>)> where F: Fn(&[u8]) -> Result<T, Error>,253*e1997b9aSAndroid Build Coastguard Worker fn upgrade_keyblob_if_required_with<'a, T, F>( 254*e1997b9aSAndroid Build Coastguard Worker &self, 255*e1997b9aSAndroid Build Coastguard Worker db: &mut KeystoreDB, 256*e1997b9aSAndroid Build Coastguard Worker key_id_guard: &KeyIdGuard, 257*e1997b9aSAndroid Build Coastguard Worker key_blob: KeyBlob<'a>, 258*e1997b9aSAndroid Build Coastguard Worker f: F, 259*e1997b9aSAndroid Build Coastguard Worker ) -> Result<(T, KeyBlob<'a>)> 260*e1997b9aSAndroid Build Coastguard Worker where 261*e1997b9aSAndroid Build Coastguard Worker F: Fn(&[u8]) -> Result<T, Error>, 262*e1997b9aSAndroid Build Coastguard Worker { 263*e1997b9aSAndroid Build Coastguard Worker let (f_result, upgraded_blob) = crate::utils::upgrade_keyblob_if_required_with( 264*e1997b9aSAndroid Build Coastguard Worker &*self.km_dev, 265*e1997b9aSAndroid Build Coastguard Worker self.version(), 266*e1997b9aSAndroid Build Coastguard Worker &key_blob, 267*e1997b9aSAndroid Build Coastguard Worker &[], 268*e1997b9aSAndroid Build Coastguard Worker f, 269*e1997b9aSAndroid Build Coastguard Worker |upgraded_blob| { 270*e1997b9aSAndroid Build Coastguard Worker let mut new_blob_metadata = BlobMetaData::new(); 271*e1997b9aSAndroid Build Coastguard Worker new_blob_metadata.add(BlobMetaEntry::KmUuid(self.km_uuid)); 272*e1997b9aSAndroid Build Coastguard Worker 273*e1997b9aSAndroid Build Coastguard Worker db.set_blob( 274*e1997b9aSAndroid Build Coastguard Worker key_id_guard, 275*e1997b9aSAndroid Build Coastguard Worker SubComponentType::KEY_BLOB, 276*e1997b9aSAndroid Build Coastguard Worker Some(upgraded_blob), 277*e1997b9aSAndroid Build Coastguard Worker Some(&new_blob_metadata), 278*e1997b9aSAndroid Build Coastguard Worker ) 279*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("Failed to insert upgraded blob into the database"))?; 280*e1997b9aSAndroid Build Coastguard Worker Ok(()) 281*e1997b9aSAndroid Build Coastguard Worker }, 282*e1997b9aSAndroid Build Coastguard Worker )?; 283*e1997b9aSAndroid Build Coastguard Worker let returned_blob = match upgraded_blob { 284*e1997b9aSAndroid Build Coastguard Worker None => key_blob, 285*e1997b9aSAndroid Build Coastguard Worker Some(upgraded_blob) => KeyBlob::NonSensitive(upgraded_blob), 286*e1997b9aSAndroid Build Coastguard Worker }; 287*e1997b9aSAndroid Build Coastguard Worker Ok((f_result, returned_blob)) 288*e1997b9aSAndroid Build Coastguard Worker } 289*e1997b9aSAndroid Build Coastguard Worker 290*e1997b9aSAndroid Build Coastguard Worker /// Use the created key in an operation that can be done with 291*e1997b9aSAndroid Build Coastguard Worker /// a call to begin followed by a call to finish. 292*e1997b9aSAndroid Build Coastguard Worker #[allow(clippy::too_many_arguments)] use_key_in_one_step( &self, db: &mut KeystoreDB, key_id_guard: &KeyIdGuard, key_blob: &[u8], purpose: KeyPurpose, operation_parameters: &[KeyParameter], auth_token: Option<&HardwareAuthToken>, input: &[u8], ) -> Result<Vec<u8>>293*e1997b9aSAndroid Build Coastguard Worker pub fn use_key_in_one_step( 294*e1997b9aSAndroid Build Coastguard Worker &self, 295*e1997b9aSAndroid Build Coastguard Worker db: &mut KeystoreDB, 296*e1997b9aSAndroid Build Coastguard Worker key_id_guard: &KeyIdGuard, 297*e1997b9aSAndroid Build Coastguard Worker key_blob: &[u8], 298*e1997b9aSAndroid Build Coastguard Worker purpose: KeyPurpose, 299*e1997b9aSAndroid Build Coastguard Worker operation_parameters: &[KeyParameter], 300*e1997b9aSAndroid Build Coastguard Worker auth_token: Option<&HardwareAuthToken>, 301*e1997b9aSAndroid Build Coastguard Worker input: &[u8], 302*e1997b9aSAndroid Build Coastguard Worker ) -> Result<Vec<u8>> { 303*e1997b9aSAndroid Build Coastguard Worker let key_blob = KeyBlob::Ref(key_blob); 304*e1997b9aSAndroid Build Coastguard Worker 305*e1997b9aSAndroid Build Coastguard Worker let (begin_result, _) = self 306*e1997b9aSAndroid Build Coastguard Worker .upgrade_keyblob_if_required_with(db, key_id_guard, key_blob, |blob| { 307*e1997b9aSAndroid Build Coastguard Worker map_km_error({ 308*e1997b9aSAndroid Build Coastguard Worker let _wp = wd::watch( 309*e1997b9aSAndroid Build Coastguard Worker "KeyMintDevice::use_key_in_one_step: calling IKeyMintDevice::begin", 310*e1997b9aSAndroid Build Coastguard Worker ); 311*e1997b9aSAndroid Build Coastguard Worker self.km_dev.begin(purpose, blob, operation_parameters, auth_token) 312*e1997b9aSAndroid Build Coastguard Worker }) 313*e1997b9aSAndroid Build Coastguard Worker }) 314*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("Failed to begin operation."))?; 315*e1997b9aSAndroid Build Coastguard Worker let operation: Strong<dyn IKeyMintOperation> = 316*e1997b9aSAndroid Build Coastguard Worker begin_result.operation.ok_or_else(Error::sys).context(ks_err!("Operation missing"))?; 317*e1997b9aSAndroid Build Coastguard Worker map_km_error({ 318*e1997b9aSAndroid Build Coastguard Worker let _wp = 319*e1997b9aSAndroid Build Coastguard Worker wd::watch("KeyMintDevice::use_key_in_one_step: calling IKeyMintDevice::finish"); 320*e1997b9aSAndroid Build Coastguard Worker operation.finish(Some(input), None, None, None, None) 321*e1997b9aSAndroid Build Coastguard Worker }) 322*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("Failed to finish operation.")) 323*e1997b9aSAndroid Build Coastguard Worker } 324*e1997b9aSAndroid Build Coastguard Worker } 325