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(¶ms, &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(¶ms, &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