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