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