David Drysdale | c97eb9e | 2022-01-26 13:03:48 -0800 | [diff] [blame] | 1 | // Copyright 2020, 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 a wrapper around a KeyMint device that allows up-level features to |
| 16 | //! be emulated on back-level devices. |
| 17 | |
Shaquille Johnson | 9da2e1c | 2022-09-19 12:39:01 +0000 | [diff] [blame] | 18 | use crate::ks_err; |
David Drysdale | c97eb9e | 2022-01-26 13:03:48 -0800 | [diff] [blame] | 19 | use crate::error::{map_binder_status, map_binder_status_code, map_or_log_err, Error, ErrorCode}; |
| 20 | use android_hardware_security_keymint::binder::{BinderFeatures, StatusCode, Strong}; |
| 21 | use android_hardware_security_secureclock::aidl::android::hardware::security::secureclock::TimeStampToken::TimeStampToken; |
| 22 | use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{ |
| 23 | AttestationKey::AttestationKey, BeginResult::BeginResult, EcCurve::EcCurve, |
| 24 | HardwareAuthToken::HardwareAuthToken, IKeyMintDevice::BnKeyMintDevice, |
| 25 | IKeyMintDevice::IKeyMintDevice, KeyCharacteristics::KeyCharacteristics, |
| 26 | KeyCreationResult::KeyCreationResult, KeyFormat::KeyFormat, |
| 27 | KeyMintHardwareInfo::KeyMintHardwareInfo, KeyParameter::KeyParameter, |
| 28 | KeyParameterValue::KeyParameterValue, KeyPurpose::KeyPurpose, SecurityLevel::SecurityLevel, |
| 29 | Tag::Tag, |
| 30 | }; |
| 31 | use android_security_compat::aidl::android::security::compat::IKeystoreCompatService::IKeystoreCompatService; |
| 32 | use anyhow::Context; |
| 33 | use keystore2_crypto::{hmac_sha256, HMAC_SHA256_LEN}; |
| 34 | |
David Drysdale | 5accbaa | 2023-04-12 18:47:10 +0100 | [diff] [blame] | 35 | /// Magic prefix used by the km_compat C++ code to mark a key that is owned by an |
| 36 | /// underlying Keymaster hardware device that has been wrapped by km_compat. (The |
| 37 | /// final zero byte indicates that the blob is not software emulated.) |
| 38 | pub const KEYMASTER_BLOB_HW_PREFIX: &[u8] = b"pKMblob\x00"; |
| 39 | |
David Drysdale | c97eb9e | 2022-01-26 13:03:48 -0800 | [diff] [blame] | 40 | /// Key data associated with key generation/import. |
| 41 | #[derive(Debug, PartialEq, Eq)] |
| 42 | pub enum KeyImportData<'a> { |
| 43 | None, |
| 44 | Pkcs8(&'a [u8]), |
| 45 | Raw(&'a [u8]), |
| 46 | } |
| 47 | |
| 48 | impl<'a> KeyImportData<'a> { |
| 49 | /// Translate import parameters into a `KeyImportData` instance. |
| 50 | fn new(key_format: KeyFormat, key_data: &'a [u8]) -> binder::Result<Self> { |
| 51 | match key_format { |
| 52 | KeyFormat::PKCS8 => Ok(KeyImportData::Pkcs8(key_data)), |
| 53 | KeyFormat::RAW => Ok(KeyImportData::Raw(key_data)), |
| 54 | _ => Err(binder::Status::new_service_specific_error( |
| 55 | ErrorCode::UNSUPPORTED_KEY_FORMAT.0, |
| 56 | None, |
| 57 | )), |
| 58 | } |
| 59 | } |
| 60 | } |
| 61 | |
| 62 | /// A key blob that may be software-emulated or may be directly produced by an |
| 63 | /// underlying device. In either variant the inner data is the keyblob itself, |
| 64 | /// as seen by the relevant device. |
| 65 | #[derive(Debug, PartialEq, Eq)] |
| 66 | pub enum KeyBlob<'a> { |
| 67 | Raw(&'a [u8]), |
| 68 | Wrapped(&'a [u8]), |
| 69 | } |
| 70 | |
| 71 | /// Trait for detecting that software emulation of a current-version KeyMint |
| 72 | /// feature is required for a back-level KeyMint implementation. |
| 73 | pub trait EmulationDetector: Send + Sync { |
| 74 | /// Indicate whether software emulation is required for key |
| 75 | /// generation/import using the provided parameters. |
| 76 | fn emulation_required(&self, params: &[KeyParameter], import_data: &KeyImportData) -> bool; |
| 77 | } |
| 78 | |
| 79 | const KEYBLOB_PREFIX: &[u8] = b"SoftKeyMintForV1Blob"; |
| 80 | const KEYBLOB_HMAC_KEY: &[u8] = b"SoftKeyMintForV1HMACKey"; |
| 81 | |
| 82 | /// Wrap the provided keyblob: |
| 83 | /// - prefix it with an identifier specific to this wrapper |
| 84 | /// - suffix it with an HMAC tag, using the [`KEYBLOB_HMAC_KEY`] and `keyblob`. |
| 85 | fn wrap_keyblob(keyblob: &[u8]) -> anyhow::Result<Vec<u8>> { |
| 86 | let mut result = Vec::with_capacity(KEYBLOB_PREFIX.len() + keyblob.len() + HMAC_SHA256_LEN); |
| 87 | result.extend_from_slice(KEYBLOB_PREFIX); |
| 88 | result.extend_from_slice(keyblob); |
| 89 | let tag = hmac_sha256(KEYBLOB_HMAC_KEY, keyblob) |
Shaquille Johnson | 9da2e1c | 2022-09-19 12:39:01 +0000 | [diff] [blame] | 90 | .context(ks_err!("failed to calculate HMAC-SHA256"))?; |
David Drysdale | c97eb9e | 2022-01-26 13:03:48 -0800 | [diff] [blame] | 91 | result.extend_from_slice(&tag); |
| 92 | Ok(result) |
| 93 | } |
| 94 | |
| 95 | /// Return an unwrapped version of the provided `keyblob`, which may or may |
| 96 | /// not be associated with the software emulation. |
| 97 | fn unwrap_keyblob(keyblob: &[u8]) -> KeyBlob { |
| 98 | if !keyblob.starts_with(KEYBLOB_PREFIX) { |
| 99 | return KeyBlob::Raw(keyblob); |
| 100 | } |
| 101 | let without_prefix = &keyblob[KEYBLOB_PREFIX.len()..]; |
| 102 | if without_prefix.len() < HMAC_SHA256_LEN { |
| 103 | return KeyBlob::Raw(keyblob); |
| 104 | } |
| 105 | let (inner_keyblob, want_tag) = without_prefix.split_at(without_prefix.len() - HMAC_SHA256_LEN); |
| 106 | let got_tag = match hmac_sha256(KEYBLOB_HMAC_KEY, inner_keyblob) { |
| 107 | Ok(tag) => tag, |
| 108 | Err(e) => { |
| 109 | log::error!("Error calculating HMAC-SHA256 for keyblob unwrap: {:?}", e); |
| 110 | return KeyBlob::Raw(keyblob); |
| 111 | } |
| 112 | }; |
| 113 | // Comparison does not need to be constant-time here. |
| 114 | if want_tag == got_tag { |
| 115 | KeyBlob::Wrapped(inner_keyblob) |
| 116 | } else { |
| 117 | KeyBlob::Raw(keyblob) |
| 118 | } |
| 119 | } |
| 120 | |
| 121 | /// Wrapper around a real device that implements a back-level version of |
| 122 | /// `IKeyMintDevice` |
| 123 | pub struct BacklevelKeyMintWrapper<T: EmulationDetector> { |
| 124 | /// The `real` device implements some earlier version of `IKeyMintDevice` |
| 125 | real: Strong<dyn IKeyMintDevice>, |
| 126 | /// The `soft`ware device implements the current version of `IKeyMintDevice` |
| 127 | soft: Strong<dyn IKeyMintDevice>, |
| 128 | /// Detector for operations that are not supported by the earlier version of |
| 129 | /// `IKeyMintDevice`. Or possibly a large flightless bird, who can tell. |
| 130 | emu: T, |
| 131 | } |
| 132 | |
| 133 | impl<T> BacklevelKeyMintWrapper<T> |
| 134 | where |
| 135 | T: EmulationDetector + 'static, |
| 136 | { |
| 137 | /// Create a wrapper around the provided back-level KeyMint device, so that |
| 138 | /// software emulation can be performed for any current-version features not |
| 139 | /// provided by the real device. |
| 140 | pub fn wrap( |
| 141 | emu: T, |
| 142 | real: Strong<dyn IKeyMintDevice>, |
| 143 | ) -> anyhow::Result<Strong<dyn IKeyMintDevice>> { |
| 144 | // This is a no-op if it was called before. |
| 145 | keystore2_km_compat::add_keymint_device_service(); |
| 146 | |
Shaquille Johnson | 9da2e1c | 2022-09-19 12:39:01 +0000 | [diff] [blame] | 147 | let keystore_compat_service: Strong<dyn IKeystoreCompatService> = |
| 148 | map_binder_status_code(binder::get_interface("android.security.compat")) |
| 149 | .context(ks_err!("Trying to connect to compat service."))?; |
David Drysdale | c97eb9e | 2022-01-26 13:03:48 -0800 | [diff] [blame] | 150 | let soft = |
| 151 | map_binder_status(keystore_compat_service.getKeyMintDevice(SecurityLevel::SOFTWARE)) |
| 152 | .map_err(|e| match e { |
| 153 | Error::BinderTransaction(StatusCode::NAME_NOT_FOUND) => { |
| 154 | Error::Km(ErrorCode::HARDWARE_TYPE_UNAVAILABLE) |
| 155 | } |
| 156 | e => e, |
| 157 | }) |
Shaquille Johnson | 9da2e1c | 2022-09-19 12:39:01 +0000 | [diff] [blame] | 158 | .context(ks_err!("Trying to get software device."))?; |
David Drysdale | c97eb9e | 2022-01-26 13:03:48 -0800 | [diff] [blame] | 159 | |
| 160 | Ok(BnKeyMintDevice::new_binder( |
| 161 | Self { real, soft, emu }, |
| 162 | BinderFeatures { set_requesting_sid: true, ..BinderFeatures::default() }, |
| 163 | )) |
| 164 | } |
| 165 | } |
| 166 | |
Orlando Arbildo | 9ee036a | 2023-10-31 00:15:22 +0000 | [diff] [blame] | 167 | impl<T> binder::Interface for BacklevelKeyMintWrapper<T> where T: EmulationDetector + 'static {} |
David Drysdale | c97eb9e | 2022-01-26 13:03:48 -0800 | [diff] [blame] | 168 | |
| 169 | impl<T> IKeyMintDevice for BacklevelKeyMintWrapper<T> |
| 170 | where |
| 171 | T: EmulationDetector + 'static, |
| 172 | { |
| 173 | // For methods that don't involve keyblobs, forward to either the real |
| 174 | // device, or to both real & emulated devices. |
| 175 | fn getHardwareInfo(&self) -> binder::Result<KeyMintHardwareInfo> { |
| 176 | self.real.getHardwareInfo() |
| 177 | } |
| 178 | fn addRngEntropy(&self, data: &[u8]) -> binder::Result<()> { |
| 179 | self.real.addRngEntropy(data) |
| 180 | } |
| 181 | fn deleteAllKeys(&self) -> binder::Result<()> { |
| 182 | self.real.deleteAllKeys() |
| 183 | } |
| 184 | fn destroyAttestationIds(&self) -> binder::Result<()> { |
| 185 | self.real.destroyAttestationIds() |
| 186 | } |
| 187 | fn deviceLocked( |
| 188 | &self, |
| 189 | password_only: bool, |
| 190 | timestamp_token: Option<&TimeStampToken>, |
| 191 | ) -> binder::Result<()> { |
| 192 | // Propagate to both real and software devices, but only pay attention |
| 193 | // to the result from the real device. |
| 194 | let _ = self.soft.deviceLocked(password_only, timestamp_token); |
| 195 | self.real.deviceLocked(password_only, timestamp_token) |
| 196 | } |
| 197 | fn earlyBootEnded(&self) -> binder::Result<()> { |
| 198 | // Propagate to both real and software devices, but only pay attention |
| 199 | // to the result from the real device. |
| 200 | let _ = self.soft.earlyBootEnded(); |
| 201 | self.real.earlyBootEnded() |
| 202 | } |
David Drysdale | c0ed986 | 2023-07-05 07:11:39 +0100 | [diff] [blame] | 203 | fn getRootOfTrustChallenge(&self) -> binder::Result<[u8; 16]> { |
| 204 | self.real.getRootOfTrustChallenge() |
| 205 | } |
| 206 | fn getRootOfTrust(&self, challenge: &[u8; 16]) -> binder::Result<Vec<u8>> { |
| 207 | self.real.getRootOfTrust(challenge) |
| 208 | } |
| 209 | fn sendRootOfTrust(&self, root_of_trust: &[u8]) -> binder::Result<()> { |
| 210 | self.real.sendRootOfTrust(root_of_trust) |
| 211 | } |
David Drysdale | c97eb9e | 2022-01-26 13:03:48 -0800 | [diff] [blame] | 212 | |
| 213 | // For methods that emit keyblobs, check whether the underlying real device |
| 214 | // supports the relevant parameters, and forward to the appropriate device. |
| 215 | // If the emulated device is used, ensure that the created keyblob gets |
| 216 | // prefixed so we can recognize it in future. |
| 217 | fn generateKey( |
| 218 | &self, |
| 219 | key_params: &[KeyParameter], |
| 220 | attestation_key: Option<&AttestationKey>, |
| 221 | ) -> binder::Result<KeyCreationResult> { |
| 222 | if self.emu.emulation_required(key_params, &KeyImportData::None) { |
| 223 | let mut result = self.soft.generateKey(key_params, attestation_key)?; |
| 224 | result.keyBlob = map_or_log_err(wrap_keyblob(&result.keyBlob), Ok)?; |
| 225 | Ok(result) |
| 226 | } else { |
| 227 | self.real.generateKey(key_params, attestation_key) |
| 228 | } |
| 229 | } |
| 230 | fn importKey( |
| 231 | &self, |
| 232 | key_params: &[KeyParameter], |
| 233 | key_format: KeyFormat, |
| 234 | key_data: &[u8], |
| 235 | attestation_key: Option<&AttestationKey>, |
| 236 | ) -> binder::Result<KeyCreationResult> { |
| 237 | if self.emu.emulation_required(key_params, &KeyImportData::new(key_format, key_data)?) { |
| 238 | let mut result = |
| 239 | self.soft.importKey(key_params, key_format, key_data, attestation_key)?; |
| 240 | result.keyBlob = map_or_log_err(wrap_keyblob(&result.keyBlob), Ok)?; |
| 241 | Ok(result) |
| 242 | } else { |
| 243 | self.real.importKey(key_params, key_format, key_data, attestation_key) |
| 244 | } |
| 245 | } |
| 246 | fn importWrappedKey( |
| 247 | &self, |
| 248 | wrapped_key_data: &[u8], |
| 249 | wrapping_key_blob: &[u8], |
| 250 | masking_key: &[u8], |
| 251 | unwrapping_params: &[KeyParameter], |
| 252 | password_sid: i64, |
| 253 | biometric_sid: i64, |
| 254 | ) -> binder::Result<KeyCreationResult> { |
| 255 | // A wrapped key cannot be software-emulated, as the wrapping key is |
| 256 | // likely hardware-bound. |
| 257 | self.real.importWrappedKey( |
| 258 | wrapped_key_data, |
| 259 | wrapping_key_blob, |
| 260 | masking_key, |
| 261 | unwrapping_params, |
| 262 | password_sid, |
| 263 | biometric_sid, |
| 264 | ) |
| 265 | } |
| 266 | |
| 267 | // For methods that use keyblobs, determine which device to forward the |
| 268 | // operation to based on whether the keyblob is appropriately prefixed. |
| 269 | fn upgradeKey( |
| 270 | &self, |
| 271 | keyblob_to_upgrade: &[u8], |
| 272 | upgrade_params: &[KeyParameter], |
| 273 | ) -> binder::Result<Vec<u8>> { |
| 274 | match unwrap_keyblob(keyblob_to_upgrade) { |
| 275 | KeyBlob::Raw(keyblob) => self.real.upgradeKey(keyblob, upgrade_params), |
| 276 | KeyBlob::Wrapped(keyblob) => { |
| 277 | // Re-wrap the upgraded keyblob. |
| 278 | let upgraded_keyblob = self.soft.upgradeKey(keyblob, upgrade_params)?; |
| 279 | map_or_log_err(wrap_keyblob(&upgraded_keyblob), Ok) |
| 280 | } |
| 281 | } |
| 282 | } |
| 283 | fn deleteKey(&self, keyblob: &[u8]) -> binder::Result<()> { |
| 284 | match unwrap_keyblob(keyblob) { |
| 285 | KeyBlob::Raw(keyblob) => self.real.deleteKey(keyblob), |
| 286 | KeyBlob::Wrapped(keyblob) => { |
| 287 | // Forward to the software implementation for completeness, but |
| 288 | // this should always be a no-op. |
| 289 | self.soft.deleteKey(keyblob) |
| 290 | } |
| 291 | } |
| 292 | } |
| 293 | fn begin( |
| 294 | &self, |
| 295 | purpose: KeyPurpose, |
| 296 | keyblob: &[u8], |
| 297 | params: &[KeyParameter], |
| 298 | auth_token: Option<&HardwareAuthToken>, |
| 299 | ) -> binder::Result<BeginResult> { |
| 300 | match unwrap_keyblob(keyblob) { |
| 301 | KeyBlob::Raw(keyblob) => self.real.begin(purpose, keyblob, params, auth_token), |
| 302 | KeyBlob::Wrapped(keyblob) => self.soft.begin(purpose, keyblob, params, auth_token), |
| 303 | } |
| 304 | } |
| 305 | fn getKeyCharacteristics( |
| 306 | &self, |
| 307 | keyblob: &[u8], |
| 308 | app_id: &[u8], |
| 309 | app_data: &[u8], |
| 310 | ) -> binder::Result<Vec<KeyCharacteristics>> { |
| 311 | match unwrap_keyblob(keyblob) { |
| 312 | KeyBlob::Raw(keyblob) => self.real.getKeyCharacteristics(keyblob, app_id, app_data), |
| 313 | KeyBlob::Wrapped(keyblob) => self.soft.getKeyCharacteristics(keyblob, app_id, app_data), |
| 314 | } |
| 315 | } |
David Drysdale | c97eb9e | 2022-01-26 13:03:48 -0800 | [diff] [blame] | 316 | fn convertStorageKeyToEphemeral(&self, storage_keyblob: &[u8]) -> binder::Result<Vec<u8>> { |
| 317 | // Storage keys should never be associated with a software emulated device. |
| 318 | self.real.convertStorageKeyToEphemeral(storage_keyblob) |
| 319 | } |
| 320 | } |
| 321 | |
| 322 | /// Detector for current features that are not implemented by KeyMint V1. |
| 323 | #[derive(Debug)] |
| 324 | pub struct KeyMintV1 { |
| 325 | sec_level: SecurityLevel, |
| 326 | } |
| 327 | |
| 328 | impl KeyMintV1 { |
| 329 | pub fn new(sec_level: SecurityLevel) -> Self { |
| 330 | Self { sec_level } |
| 331 | } |
| 332 | } |
| 333 | |
| 334 | impl EmulationDetector for KeyMintV1 { |
| 335 | fn emulation_required(&self, params: &[KeyParameter], _import_data: &KeyImportData) -> bool { |
| 336 | // No current difference from KeyMint v1 for STRONGBOX (it doesn't |
| 337 | // support curve 25519). |
| 338 | if self.sec_level == SecurityLevel::STRONGBOX { |
| 339 | return false; |
| 340 | } |
| 341 | |
| 342 | // KeyMint V1 does not support the use of curve 25519, so hunt for that |
| 343 | // in the parameters. |
| 344 | if params.iter().any(|p| { |
| 345 | p.tag == Tag::EC_CURVE && p.value == KeyParameterValue::EcCurve(EcCurve::CURVE_25519) |
| 346 | }) { |
| 347 | return true; |
| 348 | } |
| 349 | // In theory, if the `import_data` is `KeyImportData::Pkcs8` we could |
| 350 | // check the imported keymaterial for the Ed25519 / X25519 OIDs in the |
| 351 | // PKCS8 keydata, and use that to decide to route to software. However, |
| 352 | // the KeyMint spec doesn't require that so don't attempt to parse the |
| 353 | // key material here. |
| 354 | false |
| 355 | } |
| 356 | } |
| 357 | |
| 358 | /// Detector for current features that are not implemented by KeyMaster, via the |
| 359 | /// km_compat wrapper. |
| 360 | #[derive(Debug)] |
| 361 | pub struct Keymaster { |
| 362 | v1: KeyMintV1, |
| 363 | } |
| 364 | |
| 365 | /// TODO(b/216434270): This could be used this to replace the emulation routing |
| 366 | /// in the km_compat C++ code, and allow support for imported ECDH keys along |
| 367 | /// the way. Would need to figure out what would happen to existing emulated |
| 368 | /// keys though. |
| 369 | #[allow(dead_code)] |
| 370 | impl Keymaster { |
| 371 | pub fn new(sec_level: SecurityLevel) -> Self { |
| 372 | Self { v1: KeyMintV1::new(sec_level) } |
| 373 | } |
| 374 | } |
| 375 | |
| 376 | impl EmulationDetector for Keymaster { |
| 377 | fn emulation_required(&self, params: &[KeyParameter], import_data: &KeyImportData) -> bool { |
| 378 | // The km_compat wrapper on top of Keymaster emulates the KeyMint V1 |
| 379 | // interface, so any feature from > v1 needs to be emulated. |
| 380 | if self.v1.emulation_required(params, import_data) { |
| 381 | return true; |
| 382 | } |
| 383 | |
| 384 | // Keymaster does not support ECDH (KeyPurpose::AGREE_KEY), so hunt for |
| 385 | // that in the parameters. |
| 386 | if params.iter().any(|p| { |
| 387 | p.tag == Tag::PURPOSE && p.value == KeyParameterValue::KeyPurpose(KeyPurpose::AGREE_KEY) |
| 388 | }) { |
| 389 | return true; |
| 390 | } |
| 391 | false |
| 392 | } |
| 393 | } |
| 394 | |
| 395 | #[cfg(test)] |
| 396 | mod tests { |
| 397 | use super::*; |
| 398 | |
| 399 | #[test] |
| 400 | fn test_key_import_data() { |
| 401 | let data = vec![1, 2, 3]; |
| 402 | assert_eq!(KeyImportData::new(KeyFormat::PKCS8, &data), Ok(KeyImportData::Pkcs8(&data))); |
| 403 | assert_eq!(KeyImportData::new(KeyFormat::RAW, &data), Ok(KeyImportData::Raw(&data))); |
| 404 | assert!(KeyImportData::new(KeyFormat::X509, &data).is_err()); |
| 405 | } |
| 406 | |
| 407 | #[test] |
| 408 | fn test_wrap_keyblob() { |
| 409 | let keyblob = vec![1, 2, 3]; |
| 410 | let wrapped = wrap_keyblob(&keyblob).unwrap(); |
| 411 | assert_eq!(&wrapped[..KEYBLOB_PREFIX.len()], KEYBLOB_PREFIX); |
| 412 | assert_eq!(&wrapped[KEYBLOB_PREFIX.len()..KEYBLOB_PREFIX.len() + keyblob.len()], &keyblob); |
| 413 | assert_eq!(unwrap_keyblob(&keyblob), KeyBlob::Raw(&keyblob)); |
| 414 | assert_eq!(unwrap_keyblob(&wrapped), KeyBlob::Wrapped(&keyblob)); |
| 415 | |
| 416 | let mut corrupt_prefix = wrapped.clone(); |
| 417 | corrupt_prefix[0] ^= 0x01; |
| 418 | assert_eq!(unwrap_keyblob(&corrupt_prefix), KeyBlob::Raw(&corrupt_prefix)); |
| 419 | |
| 420 | let mut corrupt_suffix = wrapped.clone(); |
| 421 | corrupt_suffix[wrapped.len() - 1] ^= 0x01; |
| 422 | assert_eq!(unwrap_keyblob(&corrupt_suffix), KeyBlob::Raw(&corrupt_suffix)); |
| 423 | |
| 424 | let too_short = &wrapped[..wrapped.len() - 4]; |
| 425 | assert_eq!(unwrap_keyblob(too_short), KeyBlob::Raw(too_short)); |
| 426 | } |
| 427 | |
| 428 | #[test] |
| 429 | fn test_keymintv1_emulation_required() { |
| 430 | let tests = vec![ |
| 431 | (SecurityLevel::TRUSTED_ENVIRONMENT, vec![], false), |
| 432 | ( |
| 433 | SecurityLevel::TRUSTED_ENVIRONMENT, |
| 434 | vec![ |
| 435 | KeyParameter { |
| 436 | tag: Tag::PURPOSE, |
| 437 | value: KeyParameterValue::KeyPurpose(KeyPurpose::SIGN), |
| 438 | }, |
| 439 | KeyParameter { |
| 440 | tag: Tag::PURPOSE, |
| 441 | value: KeyParameterValue::KeyPurpose(KeyPurpose::VERIFY), |
| 442 | }, |
| 443 | ], |
| 444 | false, |
| 445 | ), |
| 446 | ( |
| 447 | SecurityLevel::TRUSTED_ENVIRONMENT, |
| 448 | vec![KeyParameter { |
| 449 | tag: Tag::PURPOSE, |
| 450 | value: KeyParameterValue::KeyPurpose(KeyPurpose::AGREE_KEY), |
| 451 | }], |
| 452 | false, |
| 453 | ), |
| 454 | ( |
| 455 | SecurityLevel::TRUSTED_ENVIRONMENT, |
| 456 | vec![ |
| 457 | KeyParameter { |
| 458 | tag: Tag::PURPOSE, |
| 459 | value: KeyParameterValue::KeyPurpose(KeyPurpose::AGREE_KEY), |
| 460 | }, |
| 461 | KeyParameter { |
| 462 | tag: Tag::EC_CURVE, |
| 463 | value: KeyParameterValue::EcCurve(EcCurve::P_256), |
| 464 | }, |
| 465 | ], |
| 466 | false, |
| 467 | ), |
| 468 | ( |
| 469 | SecurityLevel::TRUSTED_ENVIRONMENT, |
| 470 | vec![ |
| 471 | KeyParameter { |
| 472 | tag: Tag::PURPOSE, |
| 473 | value: KeyParameterValue::KeyPurpose(KeyPurpose::AGREE_KEY), |
| 474 | }, |
| 475 | KeyParameter { |
| 476 | tag: Tag::EC_CURVE, |
| 477 | value: KeyParameterValue::EcCurve(EcCurve::CURVE_25519), |
| 478 | }, |
| 479 | ], |
| 480 | true, |
| 481 | ), |
| 482 | ( |
| 483 | SecurityLevel::STRONGBOX, |
| 484 | vec![ |
| 485 | KeyParameter { |
| 486 | tag: Tag::PURPOSE, |
| 487 | value: KeyParameterValue::KeyPurpose(KeyPurpose::AGREE_KEY), |
| 488 | }, |
| 489 | KeyParameter { |
| 490 | tag: Tag::EC_CURVE, |
| 491 | value: KeyParameterValue::EcCurve(EcCurve::CURVE_25519), |
| 492 | }, |
| 493 | ], |
| 494 | false, |
| 495 | ), |
| 496 | ]; |
| 497 | for (sec_level, params, want) in tests { |
| 498 | let v1 = KeyMintV1::new(sec_level); |
| 499 | let got = v1.emulation_required(¶ms, &KeyImportData::None); |
| 500 | assert_eq!(got, want, "emulation_required({:?})={}, want {}", params, got, want); |
| 501 | } |
| 502 | } |
| 503 | |
| 504 | #[test] |
| 505 | fn test_keymaster_emulation_required() { |
| 506 | let tests = vec![ |
| 507 | (SecurityLevel::TRUSTED_ENVIRONMENT, vec![], false), |
| 508 | ( |
| 509 | SecurityLevel::TRUSTED_ENVIRONMENT, |
| 510 | vec![ |
| 511 | KeyParameter { |
| 512 | tag: Tag::PURPOSE, |
| 513 | value: KeyParameterValue::KeyPurpose(KeyPurpose::SIGN), |
| 514 | }, |
| 515 | KeyParameter { |
| 516 | tag: Tag::PURPOSE, |
| 517 | value: KeyParameterValue::KeyPurpose(KeyPurpose::VERIFY), |
| 518 | }, |
| 519 | ], |
| 520 | false, |
| 521 | ), |
| 522 | ( |
| 523 | SecurityLevel::TRUSTED_ENVIRONMENT, |
| 524 | vec![KeyParameter { |
| 525 | tag: Tag::PURPOSE, |
| 526 | value: KeyParameterValue::KeyPurpose(KeyPurpose::AGREE_KEY), |
| 527 | }], |
| 528 | true, |
| 529 | ), |
| 530 | ( |
| 531 | SecurityLevel::TRUSTED_ENVIRONMENT, |
| 532 | vec![ |
| 533 | KeyParameter { |
| 534 | tag: Tag::PURPOSE, |
| 535 | value: KeyParameterValue::KeyPurpose(KeyPurpose::AGREE_KEY), |
| 536 | }, |
| 537 | KeyParameter { |
| 538 | tag: Tag::EC_CURVE, |
| 539 | value: KeyParameterValue::EcCurve(EcCurve::P_256), |
| 540 | }, |
| 541 | ], |
| 542 | true, |
| 543 | ), |
| 544 | ( |
| 545 | SecurityLevel::TRUSTED_ENVIRONMENT, |
| 546 | vec![ |
| 547 | KeyParameter { |
| 548 | tag: Tag::PURPOSE, |
| 549 | value: KeyParameterValue::KeyPurpose(KeyPurpose::AGREE_KEY), |
| 550 | }, |
| 551 | KeyParameter { |
| 552 | tag: Tag::EC_CURVE, |
| 553 | value: KeyParameterValue::EcCurve(EcCurve::CURVE_25519), |
| 554 | }, |
| 555 | ], |
| 556 | true, |
| 557 | ), |
| 558 | ( |
| 559 | SecurityLevel::STRONGBOX, |
| 560 | vec![ |
| 561 | KeyParameter { |
| 562 | tag: Tag::PURPOSE, |
| 563 | value: KeyParameterValue::KeyPurpose(KeyPurpose::AGREE_KEY), |
| 564 | }, |
| 565 | KeyParameter { |
| 566 | tag: Tag::EC_CURVE, |
| 567 | value: KeyParameterValue::EcCurve(EcCurve::CURVE_25519), |
| 568 | }, |
| 569 | ], |
| 570 | true, |
| 571 | ), |
| 572 | ( |
| 573 | SecurityLevel::STRONGBOX, |
| 574 | vec![ |
| 575 | KeyParameter { |
| 576 | tag: Tag::PURPOSE, |
| 577 | value: KeyParameterValue::KeyPurpose(KeyPurpose::SIGN), |
| 578 | }, |
| 579 | KeyParameter { |
| 580 | tag: Tag::EC_CURVE, |
| 581 | value: KeyParameterValue::EcCurve(EcCurve::CURVE_25519), |
| 582 | }, |
| 583 | ], |
| 584 | false, |
| 585 | ), |
| 586 | ]; |
| 587 | for (sec_level, params, want) in tests { |
| 588 | let v0 = Keymaster::new(sec_level); |
| 589 | let got = v0.emulation_required(¶ms, &KeyImportData::None); |
| 590 | assert_eq!(got, want, "emulation_required({:?})={}, want {}", params, got, want); |
| 591 | } |
| 592 | } |
| 593 | } |