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