1*9860b763SAndroid Build Coastguard Worker // Copyright 2022, The Android Open Source Project
2*9860b763SAndroid Build Coastguard Worker //
3*9860b763SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*9860b763SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*9860b763SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*9860b763SAndroid Build Coastguard Worker //
7*9860b763SAndroid Build Coastguard Worker // http://www.apache.org/licenses/LICENSE-2.0
8*9860b763SAndroid Build Coastguard Worker //
9*9860b763SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*9860b763SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*9860b763SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*9860b763SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*9860b763SAndroid Build Coastguard Worker // limitations under the License.
14*9860b763SAndroid Build Coastguard Worker
15*9860b763SAndroid Build Coastguard Worker //! KeyMint trusted application (TA) implementation.
16*9860b763SAndroid Build Coastguard Worker
17*9860b763SAndroid Build Coastguard Worker #![no_std]
18*9860b763SAndroid Build Coastguard Worker extern crate alloc;
19*9860b763SAndroid Build Coastguard Worker
20*9860b763SAndroid Build Coastguard Worker use alloc::{
21*9860b763SAndroid Build Coastguard Worker boxed::Box, collections::BTreeMap, format, rc::Rc, string::String, string::ToString, vec::Vec,
22*9860b763SAndroid Build Coastguard Worker };
23*9860b763SAndroid Build Coastguard Worker use core::cmp::Ordering;
24*9860b763SAndroid Build Coastguard Worker use core::mem::size_of;
25*9860b763SAndroid Build Coastguard Worker use core::{cell::RefCell, convert::TryFrom};
26*9860b763SAndroid Build Coastguard Worker use device::DiceInfo;
27*9860b763SAndroid Build Coastguard Worker use kmr_common::{
28*9860b763SAndroid Build Coastguard Worker crypto::{self, hmac, OpaqueOr},
29*9860b763SAndroid Build Coastguard Worker get_bool_tag_value,
30*9860b763SAndroid Build Coastguard Worker keyblob::{self, RootOfTrustInfo, SecureDeletionSlot},
31*9860b763SAndroid Build Coastguard Worker km_err, tag, try_to_vec, vec_try, vec_try_with_capacity, Error, FallibleAllocExt,
32*9860b763SAndroid Build Coastguard Worker };
33*9860b763SAndroid Build Coastguard Worker use kmr_wire::{
34*9860b763SAndroid Build Coastguard Worker coset::TaggedCborSerializable,
35*9860b763SAndroid Build Coastguard Worker keymint::{
36*9860b763SAndroid Build Coastguard Worker Digest, ErrorCode, HardwareAuthToken, KeyCharacteristics, KeyMintHardwareInfo, KeyOrigin,
37*9860b763SAndroid Build Coastguard Worker KeyParam, SecurityLevel, Tag, VerifiedBootState, NEXT_MESSAGE_SIGNAL_FALSE,
38*9860b763SAndroid Build Coastguard Worker NEXT_MESSAGE_SIGNAL_TRUE,
39*9860b763SAndroid Build Coastguard Worker },
40*9860b763SAndroid Build Coastguard Worker rpc,
41*9860b763SAndroid Build Coastguard Worker rpc::{EekCurve, IRPC_V2, IRPC_V3},
42*9860b763SAndroid Build Coastguard Worker sharedsecret::SharedSecretParameters,
43*9860b763SAndroid Build Coastguard Worker *,
44*9860b763SAndroid Build Coastguard Worker };
45*9860b763SAndroid Build Coastguard Worker use log::{error, info, trace, warn};
46*9860b763SAndroid Build Coastguard Worker
47*9860b763SAndroid Build Coastguard Worker mod cert;
48*9860b763SAndroid Build Coastguard Worker mod clock;
49*9860b763SAndroid Build Coastguard Worker pub mod device;
50*9860b763SAndroid Build Coastguard Worker pub mod keys;
51*9860b763SAndroid Build Coastguard Worker mod operation;
52*9860b763SAndroid Build Coastguard Worker pub mod rkp;
53*9860b763SAndroid Build Coastguard Worker mod secret;
54*9860b763SAndroid Build Coastguard Worker
55*9860b763SAndroid Build Coastguard Worker use keys::KeyImport;
56*9860b763SAndroid Build Coastguard Worker use operation::{OpHandle, Operation};
57*9860b763SAndroid Build Coastguard Worker
58*9860b763SAndroid Build Coastguard Worker #[cfg(test)]
59*9860b763SAndroid Build Coastguard Worker mod tests;
60*9860b763SAndroid Build Coastguard Worker
61*9860b763SAndroid Build Coastguard Worker /// Possible KeyMint HAL versions
62*9860b763SAndroid Build Coastguard Worker #[repr(i32)]
63*9860b763SAndroid Build Coastguard Worker #[derive(Debug, Clone, Copy, PartialEq, Eq)]
64*9860b763SAndroid Build Coastguard Worker pub enum KeyMintHalVersion {
65*9860b763SAndroid Build Coastguard Worker /// V4 adds support for attestation of module information.
66*9860b763SAndroid Build Coastguard Worker V4 = 400,
67*9860b763SAndroid Build Coastguard Worker /// V3 adds support for attestation of second IMEI value.
68*9860b763SAndroid Build Coastguard Worker V3 = 300,
69*9860b763SAndroid Build Coastguard Worker /// V2 adds support for curve 25519 and root-of-trust transfer.
70*9860b763SAndroid Build Coastguard Worker V2 = 200,
71*9860b763SAndroid Build Coastguard Worker /// V1 is the initial version of the KeyMint HAL.
72*9860b763SAndroid Build Coastguard Worker V1 = 100,
73*9860b763SAndroid Build Coastguard Worker }
74*9860b763SAndroid Build Coastguard Worker
75*9860b763SAndroid Build Coastguard Worker /// Version code for current KeyMint.
76*9860b763SAndroid Build Coastguard Worker pub const KEYMINT_CURRENT_VERSION: KeyMintHalVersion = KeyMintHalVersion::V4;
77*9860b763SAndroid Build Coastguard Worker
78*9860b763SAndroid Build Coastguard Worker /// Maximum number of parallel operations supported when running as TEE.
79*9860b763SAndroid Build Coastguard Worker const MAX_TEE_OPERATIONS: usize = 16;
80*9860b763SAndroid Build Coastguard Worker
81*9860b763SAndroid Build Coastguard Worker /// Maximum number of parallel operations supported when running as StrongBox.
82*9860b763SAndroid Build Coastguard Worker const MAX_STRONGBOX_OPERATIONS: usize = 4;
83*9860b763SAndroid Build Coastguard Worker
84*9860b763SAndroid Build Coastguard Worker /// Maximum number of keys whose use count can be tracked.
85*9860b763SAndroid Build Coastguard Worker const MAX_USE_COUNTED_KEYS: usize = 32;
86*9860b763SAndroid Build Coastguard Worker
87*9860b763SAndroid Build Coastguard Worker /// Tags allowed in `KeyMintTa::additional_attestation_info`.
88*9860b763SAndroid Build Coastguard Worker const ALLOWED_ADDITIONAL_ATTESTATION_TAGS: &[Tag] = &[Tag::ModuleHash];
89*9860b763SAndroid Build Coastguard Worker
90*9860b763SAndroid Build Coastguard Worker /// Per-key ID use count.
91*9860b763SAndroid Build Coastguard Worker struct UseCount {
92*9860b763SAndroid Build Coastguard Worker key_id: KeyId,
93*9860b763SAndroid Build Coastguard Worker count: u64,
94*9860b763SAndroid Build Coastguard Worker }
95*9860b763SAndroid Build Coastguard Worker
96*9860b763SAndroid Build Coastguard Worker /// Attestation chain information.
97*9860b763SAndroid Build Coastguard Worker struct AttestationChainInfo {
98*9860b763SAndroid Build Coastguard Worker /// Chain of certificates from intermediate to root.
99*9860b763SAndroid Build Coastguard Worker chain: Vec<keymint::Certificate>,
100*9860b763SAndroid Build Coastguard Worker /// Subject field from the first certificate in the chain, as an ASN.1 DER encoded `Name` (cf
101*9860b763SAndroid Build Coastguard Worker /// RFC 5280 s4.1.2.4).
102*9860b763SAndroid Build Coastguard Worker issuer: Vec<u8>,
103*9860b763SAndroid Build Coastguard Worker }
104*9860b763SAndroid Build Coastguard Worker
105*9860b763SAndroid Build Coastguard Worker /// KeyMint device implementation, running in secure environment.
106*9860b763SAndroid Build Coastguard Worker pub struct KeyMintTa {
107*9860b763SAndroid Build Coastguard Worker /**
108*9860b763SAndroid Build Coastguard Worker * State that is fixed on construction.
109*9860b763SAndroid Build Coastguard Worker */
110*9860b763SAndroid Build Coastguard Worker
111*9860b763SAndroid Build Coastguard Worker /// Trait objects that hold this device's implementations of the abstract cryptographic
112*9860b763SAndroid Build Coastguard Worker /// functionality traits.
113*9860b763SAndroid Build Coastguard Worker imp: crypto::Implementation,
114*9860b763SAndroid Build Coastguard Worker
115*9860b763SAndroid Build Coastguard Worker /// Trait objects that hold this device's implementations of per-device functionality.
116*9860b763SAndroid Build Coastguard Worker dev: device::Implementation,
117*9860b763SAndroid Build Coastguard Worker
118*9860b763SAndroid Build Coastguard Worker /// Information about this particular KeyMint implementation's hardware.
119*9860b763SAndroid Build Coastguard Worker hw_info: HardwareInfo,
120*9860b763SAndroid Build Coastguard Worker
121*9860b763SAndroid Build Coastguard Worker /// Information about the implementation of the IRemotelyProvisionedComponent (IRPC) HAL.
122*9860b763SAndroid Build Coastguard Worker rpc_info: RpcInfo,
123*9860b763SAndroid Build Coastguard Worker
124*9860b763SAndroid Build Coastguard Worker /// The version of the HAL AIDL interface specification that this TA acts as.
125*9860b763SAndroid Build Coastguard Worker aidl_version: KeyMintHalVersion,
126*9860b763SAndroid Build Coastguard Worker
127*9860b763SAndroid Build Coastguard Worker /**
128*9860b763SAndroid Build Coastguard Worker * State that is set after the TA starts, but latched thereafter.
129*9860b763SAndroid Build Coastguard Worker */
130*9860b763SAndroid Build Coastguard Worker
131*9860b763SAndroid Build Coastguard Worker /// Parameters for shared secret negotiation.
132*9860b763SAndroid Build Coastguard Worker shared_secret_params: Option<SharedSecretParameters>,
133*9860b763SAndroid Build Coastguard Worker
134*9860b763SAndroid Build Coastguard Worker /// Information provided by the bootloader once at start of day.
135*9860b763SAndroid Build Coastguard Worker boot_info: Option<keymint::BootInfo>,
136*9860b763SAndroid Build Coastguard Worker rot_data: Option<Vec<u8>>,
137*9860b763SAndroid Build Coastguard Worker
138*9860b763SAndroid Build Coastguard Worker /// Information provided by the HAL service once at start of day.
139*9860b763SAndroid Build Coastguard Worker hal_info: Option<HalInfo>,
140*9860b763SAndroid Build Coastguard Worker
141*9860b763SAndroid Build Coastguard Worker /// Additional information to attest to, provided by Android. Refer to
142*9860b763SAndroid Build Coastguard Worker /// `IKeyMintDevice::setAdditionalAttestationInfo()`.
143*9860b763SAndroid Build Coastguard Worker additional_attestation_info: Vec<KeyParam>,
144*9860b763SAndroid Build Coastguard Worker
145*9860b763SAndroid Build Coastguard Worker /// Attestation chain information, retrieved on first use.
146*9860b763SAndroid Build Coastguard Worker attestation_chain_info: RefCell<BTreeMap<device::SigningKeyType, AttestationChainInfo>>,
147*9860b763SAndroid Build Coastguard Worker
148*9860b763SAndroid Build Coastguard Worker /// Attestation ID information, fixed forever for a device, but retrieved on first use.
149*9860b763SAndroid Build Coastguard Worker attestation_id_info: RefCell<Option<Rc<AttestationIdInfo>>>,
150*9860b763SAndroid Build Coastguard Worker
151*9860b763SAndroid Build Coastguard Worker /// Public DICE artifacts (UDS certs and the DICE chain) included in the certificate signing
152*9860b763SAndroid Build Coastguard Worker /// requests (CSR) and the algorithm used to sign the CSR for IRemotelyProvisionedComponent
153*9860b763SAndroid Build Coastguard Worker /// (IRPC) HAL. Fixed for a device. Retrieved on first use.
154*9860b763SAndroid Build Coastguard Worker ///
155*9860b763SAndroid Build Coastguard Worker /// Note: This information is cached only in the implementations of IRPC HAL V3 and
156*9860b763SAndroid Build Coastguard Worker /// IRPC HAL V2 in production mode.
157*9860b763SAndroid Build Coastguard Worker dice_info: RefCell<Option<Rc<DiceInfo>>>,
158*9860b763SAndroid Build Coastguard Worker
159*9860b763SAndroid Build Coastguard Worker /// Whether the device is still in early-boot.
160*9860b763SAndroid Build Coastguard Worker in_early_boot: bool,
161*9860b763SAndroid Build Coastguard Worker
162*9860b763SAndroid Build Coastguard Worker /// Device HMAC implementation which uses the `ISharedSecret` negotiated key.
163*9860b763SAndroid Build Coastguard Worker device_hmac: Option<Box<dyn device::DeviceHmac>>,
164*9860b763SAndroid Build Coastguard Worker
165*9860b763SAndroid Build Coastguard Worker /**
166*9860b763SAndroid Build Coastguard Worker * State that changes during operation.
167*9860b763SAndroid Build Coastguard Worker */
168*9860b763SAndroid Build Coastguard Worker
169*9860b763SAndroid Build Coastguard Worker /// Challenge for root-of-trust transfer (StrongBox only).
170*9860b763SAndroid Build Coastguard Worker rot_challenge: [u8; 16],
171*9860b763SAndroid Build Coastguard Worker
172*9860b763SAndroid Build Coastguard Worker /// The operation table.
173*9860b763SAndroid Build Coastguard Worker operations: Vec<Option<Operation>>,
174*9860b763SAndroid Build Coastguard Worker
175*9860b763SAndroid Build Coastguard Worker /// Use counts for keys where this is tracked.
176*9860b763SAndroid Build Coastguard Worker use_count: [Option<UseCount>; MAX_USE_COUNTED_KEYS],
177*9860b763SAndroid Build Coastguard Worker
178*9860b763SAndroid Build Coastguard Worker /// Operation handle of the (single) in-flight operation that requires trusted user presence.
179*9860b763SAndroid Build Coastguard Worker presence_required_op: Option<OpHandle>,
180*9860b763SAndroid Build Coastguard Worker }
181*9860b763SAndroid Build Coastguard Worker
182*9860b763SAndroid Build Coastguard Worker /// A helper method that can be used by the TA for processing the responses to be sent to the
183*9860b763SAndroid Build Coastguard Worker /// HAL service. Splits large response messages into multiple parts based on the capacity of the
184*9860b763SAndroid Build Coastguard Worker /// channel from the TA to the HAL. One element in the returned response array consists of:
185*9860b763SAndroid Build Coastguard Worker /// <next_msg_signal + response data> where next_msg_signal is a byte whose value is 1 if there are
186*9860b763SAndroid Build Coastguard Worker /// more messages in the response array following this one. This signal should be used by the HAL
187*9860b763SAndroid Build Coastguard Worker /// side to decide whether or not to wait for more messages. Implementation of this method must be
188*9860b763SAndroid Build Coastguard Worker /// in sync with its counterpart in the `kmr-hal` crate.
split_rsp(mut rsp_data: &[u8], max_size: usize) -> Result<Vec<Vec<u8>>, Error>189*9860b763SAndroid Build Coastguard Worker pub fn split_rsp(mut rsp_data: &[u8], max_size: usize) -> Result<Vec<Vec<u8>>, Error> {
190*9860b763SAndroid Build Coastguard Worker if rsp_data.is_empty() || max_size < 2 {
191*9860b763SAndroid Build Coastguard Worker return Err(km_err!(
192*9860b763SAndroid Build Coastguard Worker InvalidArgument,
193*9860b763SAndroid Build Coastguard Worker "response data is empty or max size: {} is invalid",
194*9860b763SAndroid Build Coastguard Worker max_size
195*9860b763SAndroid Build Coastguard Worker ));
196*9860b763SAndroid Build Coastguard Worker }
197*9860b763SAndroid Build Coastguard Worker // Need to allocate one byte for the more_msg_signal.
198*9860b763SAndroid Build Coastguard Worker let allowed_msg_length = max_size - 1;
199*9860b763SAndroid Build Coastguard Worker let mut num_of_splits = rsp_data.len() / allowed_msg_length;
200*9860b763SAndroid Build Coastguard Worker if rsp_data.len() % allowed_msg_length > 0 {
201*9860b763SAndroid Build Coastguard Worker num_of_splits += 1;
202*9860b763SAndroid Build Coastguard Worker }
203*9860b763SAndroid Build Coastguard Worker let mut split_rsp = vec_try_with_capacity!(num_of_splits)?;
204*9860b763SAndroid Build Coastguard Worker while rsp_data.len() > allowed_msg_length {
205*9860b763SAndroid Build Coastguard Worker let mut rsp = vec_try_with_capacity!(allowed_msg_length + 1)?;
206*9860b763SAndroid Build Coastguard Worker rsp.push(NEXT_MESSAGE_SIGNAL_TRUE);
207*9860b763SAndroid Build Coastguard Worker rsp.extend_from_slice(&rsp_data[..allowed_msg_length]);
208*9860b763SAndroid Build Coastguard Worker trace!("Current response size with signalling byte: {}", rsp.len());
209*9860b763SAndroid Build Coastguard Worker split_rsp.push(rsp);
210*9860b763SAndroid Build Coastguard Worker rsp_data = &rsp_data[allowed_msg_length..];
211*9860b763SAndroid Build Coastguard Worker }
212*9860b763SAndroid Build Coastguard Worker let mut last_rsp = vec_try_with_capacity!(rsp_data.len() + 1)?;
213*9860b763SAndroid Build Coastguard Worker last_rsp.push(NEXT_MESSAGE_SIGNAL_FALSE);
214*9860b763SAndroid Build Coastguard Worker last_rsp.extend_from_slice(rsp_data);
215*9860b763SAndroid Build Coastguard Worker split_rsp.push(last_rsp);
216*9860b763SAndroid Build Coastguard Worker Ok(split_rsp)
217*9860b763SAndroid Build Coastguard Worker }
218*9860b763SAndroid Build Coastguard Worker
219*9860b763SAndroid Build Coastguard Worker /// Hardware information.
220*9860b763SAndroid Build Coastguard Worker #[derive(Clone, Debug)]
221*9860b763SAndroid Build Coastguard Worker pub struct HardwareInfo {
222*9860b763SAndroid Build Coastguard Worker // Fields that correspond to the HAL `KeyMintHardwareInfo` type.
223*9860b763SAndroid Build Coastguard Worker /// Security level that this KeyMint implementation is running at.
224*9860b763SAndroid Build Coastguard Worker pub security_level: SecurityLevel,
225*9860b763SAndroid Build Coastguard Worker /// Version number.
226*9860b763SAndroid Build Coastguard Worker pub version_number: i32,
227*9860b763SAndroid Build Coastguard Worker /// KeyMint implementation name.
228*9860b763SAndroid Build Coastguard Worker pub impl_name: &'static str,
229*9860b763SAndroid Build Coastguard Worker /// Author of KeyMint implementation.
230*9860b763SAndroid Build Coastguard Worker pub author_name: &'static str,
231*9860b763SAndroid Build Coastguard Worker /// Unique identifier for this KeyMint.
232*9860b763SAndroid Build Coastguard Worker pub unique_id: &'static str,
233*9860b763SAndroid Build Coastguard Worker // The `timestamp_token_required` field in `KeyMintHardwareInfo` is skipped here because it gets
234*9860b763SAndroid Build Coastguard Worker // set depending on whether a local clock is available.
235*9860b763SAndroid Build Coastguard Worker }
236*9860b763SAndroid Build Coastguard Worker
237*9860b763SAndroid Build Coastguard Worker /// Information required to construct the structures defined in RpcHardwareInfo.aidl
238*9860b763SAndroid Build Coastguard Worker /// and DeviceInfo.aidl, for IRemotelyProvisionedComponent (IRPC) HAL V2.
239*9860b763SAndroid Build Coastguard Worker #[derive(Debug)]
240*9860b763SAndroid Build Coastguard Worker pub struct RpcInfoV2 {
241*9860b763SAndroid Build Coastguard Worker // Fields used in `RpcHardwareInfo.aidl`:
242*9860b763SAndroid Build Coastguard Worker /// Author of KeyMint implementation.
243*9860b763SAndroid Build Coastguard Worker pub author_name: &'static str,
244*9860b763SAndroid Build Coastguard Worker /// EEK curve supported by this implementation.
245*9860b763SAndroid Build Coastguard Worker pub supported_eek_curve: EekCurve,
246*9860b763SAndroid Build Coastguard Worker /// Unique identifier for this KeyMint.
247*9860b763SAndroid Build Coastguard Worker pub unique_id: &'static str,
248*9860b763SAndroid Build Coastguard Worker /// Indication of whether secure boot is enforced for the processor running this code.
249*9860b763SAndroid Build Coastguard Worker /// Used as `DeviceInfo.fused`.
250*9860b763SAndroid Build Coastguard Worker pub fused: bool,
251*9860b763SAndroid Build Coastguard Worker }
252*9860b763SAndroid Build Coastguard Worker
253*9860b763SAndroid Build Coastguard Worker /// Information required to construct the structures defined in RpcHardwareInfo.aidl
254*9860b763SAndroid Build Coastguard Worker /// and DeviceInfo.aidl, for IRemotelyProvisionedComponent (IRPC) HAL V3.
255*9860b763SAndroid Build Coastguard Worker #[derive(Debug)]
256*9860b763SAndroid Build Coastguard Worker pub struct RpcInfoV3 {
257*9860b763SAndroid Build Coastguard Worker // Fields used in `RpcHardwareInfo.aidl`:
258*9860b763SAndroid Build Coastguard Worker /// Author of KeyMint implementation.
259*9860b763SAndroid Build Coastguard Worker pub author_name: &'static str,
260*9860b763SAndroid Build Coastguard Worker /// Unique identifier for this KeyMint.
261*9860b763SAndroid Build Coastguard Worker pub unique_id: &'static str,
262*9860b763SAndroid Build Coastguard Worker /// Indication of whether secure boot is enforced for the processor running this code.
263*9860b763SAndroid Build Coastguard Worker /// Used as `DeviceInfo.fused`.
264*9860b763SAndroid Build Coastguard Worker pub fused: bool,
265*9860b763SAndroid Build Coastguard Worker /// Supported number of keys in a CSR.
266*9860b763SAndroid Build Coastguard Worker pub supported_num_of_keys_in_csr: i32,
267*9860b763SAndroid Build Coastguard Worker }
268*9860b763SAndroid Build Coastguard Worker
269*9860b763SAndroid Build Coastguard Worker /// Enum to distinguish the set of information required for different versions of IRPC HAL
270*9860b763SAndroid Build Coastguard Worker /// implementations
271*9860b763SAndroid Build Coastguard Worker pub enum RpcInfo {
272*9860b763SAndroid Build Coastguard Worker /// Information for v2 of the IRPC HAL.
273*9860b763SAndroid Build Coastguard Worker V2(RpcInfoV2),
274*9860b763SAndroid Build Coastguard Worker /// Information for v3 of the IRPC HAL.
275*9860b763SAndroid Build Coastguard Worker V3(RpcInfoV3),
276*9860b763SAndroid Build Coastguard Worker }
277*9860b763SAndroid Build Coastguard Worker
278*9860b763SAndroid Build Coastguard Worker impl RpcInfo {
279*9860b763SAndroid Build Coastguard Worker /// Indicate the HAL version of RPC information.
get_version(&self) -> i32280*9860b763SAndroid Build Coastguard Worker pub fn get_version(&self) -> i32 {
281*9860b763SAndroid Build Coastguard Worker match self {
282*9860b763SAndroid Build Coastguard Worker RpcInfo::V2(_) => IRPC_V2,
283*9860b763SAndroid Build Coastguard Worker RpcInfo::V3(_) => IRPC_V3,
284*9860b763SAndroid Build Coastguard Worker }
285*9860b763SAndroid Build Coastguard Worker }
286*9860b763SAndroid Build Coastguard Worker }
287*9860b763SAndroid Build Coastguard Worker
288*9860b763SAndroid Build Coastguard Worker /// Information provided once at service start by the HAL service, describing
289*9860b763SAndroid Build Coastguard Worker /// the state of the userspace operating system (which may change from boot to
290*9860b763SAndroid Build Coastguard Worker /// boot, e.g. for running GSI).
291*9860b763SAndroid Build Coastguard Worker #[derive(Clone, Copy, Debug)]
292*9860b763SAndroid Build Coastguard Worker pub struct HalInfo {
293*9860b763SAndroid Build Coastguard Worker /// OS version.
294*9860b763SAndroid Build Coastguard Worker pub os_version: u32,
295*9860b763SAndroid Build Coastguard Worker /// OS patchlevel, in YYYYMM format.
296*9860b763SAndroid Build Coastguard Worker pub os_patchlevel: u32,
297*9860b763SAndroid Build Coastguard Worker /// Vendor patchlevel, in YYYYMMDD format
298*9860b763SAndroid Build Coastguard Worker pub vendor_patchlevel: u32,
299*9860b763SAndroid Build Coastguard Worker }
300*9860b763SAndroid Build Coastguard Worker
301*9860b763SAndroid Build Coastguard Worker /// Identifier for a keyblob.
302*9860b763SAndroid Build Coastguard Worker #[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
303*9860b763SAndroid Build Coastguard Worker struct KeyId([u8; 32]);
304*9860b763SAndroid Build Coastguard Worker
305*9860b763SAndroid Build Coastguard Worker impl KeyMintTa {
306*9860b763SAndroid Build Coastguard Worker /// Create a new [`KeyMintTa`] instance.
new( hw_info: HardwareInfo, rpc_info: RpcInfo, imp: crypto::Implementation, dev: device::Implementation, ) -> Self307*9860b763SAndroid Build Coastguard Worker pub fn new(
308*9860b763SAndroid Build Coastguard Worker hw_info: HardwareInfo,
309*9860b763SAndroid Build Coastguard Worker rpc_info: RpcInfo,
310*9860b763SAndroid Build Coastguard Worker imp: crypto::Implementation,
311*9860b763SAndroid Build Coastguard Worker dev: device::Implementation,
312*9860b763SAndroid Build Coastguard Worker ) -> Self {
313*9860b763SAndroid Build Coastguard Worker let max_operations = if hw_info.security_level == SecurityLevel::Strongbox {
314*9860b763SAndroid Build Coastguard Worker MAX_STRONGBOX_OPERATIONS
315*9860b763SAndroid Build Coastguard Worker } else {
316*9860b763SAndroid Build Coastguard Worker MAX_TEE_OPERATIONS
317*9860b763SAndroid Build Coastguard Worker };
318*9860b763SAndroid Build Coastguard Worker Self {
319*9860b763SAndroid Build Coastguard Worker imp,
320*9860b763SAndroid Build Coastguard Worker dev,
321*9860b763SAndroid Build Coastguard Worker in_early_boot: true,
322*9860b763SAndroid Build Coastguard Worker device_hmac: None,
323*9860b763SAndroid Build Coastguard Worker rot_challenge: [0; 16],
324*9860b763SAndroid Build Coastguard Worker // Work around Rust limitation that `vec![None; n]` doesn't work.
325*9860b763SAndroid Build Coastguard Worker operations: (0..max_operations).map(|_| None).collect(),
326*9860b763SAndroid Build Coastguard Worker use_count: Default::default(),
327*9860b763SAndroid Build Coastguard Worker presence_required_op: None,
328*9860b763SAndroid Build Coastguard Worker shared_secret_params: None,
329*9860b763SAndroid Build Coastguard Worker hw_info,
330*9860b763SAndroid Build Coastguard Worker rpc_info,
331*9860b763SAndroid Build Coastguard Worker aidl_version: KEYMINT_CURRENT_VERSION,
332*9860b763SAndroid Build Coastguard Worker boot_info: None,
333*9860b763SAndroid Build Coastguard Worker rot_data: None,
334*9860b763SAndroid Build Coastguard Worker hal_info: None,
335*9860b763SAndroid Build Coastguard Worker attestation_chain_info: RefCell::new(BTreeMap::new()),
336*9860b763SAndroid Build Coastguard Worker attestation_id_info: RefCell::new(None),
337*9860b763SAndroid Build Coastguard Worker dice_info: RefCell::new(None),
338*9860b763SAndroid Build Coastguard Worker additional_attestation_info: Vec::new(),
339*9860b763SAndroid Build Coastguard Worker }
340*9860b763SAndroid Build Coastguard Worker }
341*9860b763SAndroid Build Coastguard Worker
342*9860b763SAndroid Build Coastguard Worker /// Returns key used to sign auth tokens
get_hmac_key(&self) -> Option<hmac::Key>343*9860b763SAndroid Build Coastguard Worker pub fn get_hmac_key(&self) -> Option<hmac::Key> {
344*9860b763SAndroid Build Coastguard Worker match &self.device_hmac {
345*9860b763SAndroid Build Coastguard Worker Some(device_hmac) => device_hmac.get_hmac_key(),
346*9860b763SAndroid Build Coastguard Worker None => None,
347*9860b763SAndroid Build Coastguard Worker }
348*9860b763SAndroid Build Coastguard Worker }
349*9860b763SAndroid Build Coastguard Worker
350*9860b763SAndroid Build Coastguard Worker /// Indicate whether the current device is acting as a StrongBox instance.
is_strongbox(&self) -> bool351*9860b763SAndroid Build Coastguard Worker pub fn is_strongbox(&self) -> bool {
352*9860b763SAndroid Build Coastguard Worker self.hw_info.security_level == SecurityLevel::Strongbox
353*9860b763SAndroid Build Coastguard Worker }
354*9860b763SAndroid Build Coastguard Worker
355*9860b763SAndroid Build Coastguard Worker /// Indicate whether the current device has secure storage available.
secure_storage_available(&self) -> kmr_common::tag::SecureStorage356*9860b763SAndroid Build Coastguard Worker fn secure_storage_available(&self) -> kmr_common::tag::SecureStorage {
357*9860b763SAndroid Build Coastguard Worker if self.dev.sdd_mgr.is_some() {
358*9860b763SAndroid Build Coastguard Worker kmr_common::tag::SecureStorage::Available
359*9860b763SAndroid Build Coastguard Worker } else {
360*9860b763SAndroid Build Coastguard Worker kmr_common::tag::SecureStorage::Unavailable
361*9860b763SAndroid Build Coastguard Worker }
362*9860b763SAndroid Build Coastguard Worker }
363*9860b763SAndroid Build Coastguard Worker
364*9860b763SAndroid Build Coastguard Worker /// Return the device's boot information.
boot_info(&self) -> Result<&keymint::BootInfo, Error>365*9860b763SAndroid Build Coastguard Worker fn boot_info(&self) -> Result<&keymint::BootInfo, Error> {
366*9860b763SAndroid Build Coastguard Worker self.boot_info
367*9860b763SAndroid Build Coastguard Worker .as_ref()
368*9860b763SAndroid Build Coastguard Worker .ok_or_else(|| km_err!(HardwareNotYetAvailable, "no boot info available"))
369*9860b763SAndroid Build Coastguard Worker }
370*9860b763SAndroid Build Coastguard Worker
371*9860b763SAndroid Build Coastguard Worker /// Return a copy of the device's boot information, with the verified boot key
372*9860b763SAndroid Build Coastguard Worker /// hashed (if necessary).
boot_info_hashed_key(&self) -> Result<keymint::BootInfo, Error>373*9860b763SAndroid Build Coastguard Worker fn boot_info_hashed_key(&self) -> Result<keymint::BootInfo, Error> {
374*9860b763SAndroid Build Coastguard Worker let mut boot_info = self.boot_info()?.clone();
375*9860b763SAndroid Build Coastguard Worker if boot_info.verified_boot_key.len() > 32 {
376*9860b763SAndroid Build Coastguard Worker // It looks like we have the actual key, not a hash thereof. Change that.
377*9860b763SAndroid Build Coastguard Worker boot_info.verified_boot_key =
378*9860b763SAndroid Build Coastguard Worker try_to_vec(&self.imp.sha256.hash(&boot_info.verified_boot_key)?)?;
379*9860b763SAndroid Build Coastguard Worker }
380*9860b763SAndroid Build Coastguard Worker Ok(boot_info)
381*9860b763SAndroid Build Coastguard Worker }
382*9860b763SAndroid Build Coastguard Worker
383*9860b763SAndroid Build Coastguard Worker /// Parse and decrypt an encrypted key blob, allowing through keys that require upgrade due to
384*9860b763SAndroid Build Coastguard Worker /// patchlevel updates. Keys that appear to be in a legacy format may still emit a
385*9860b763SAndroid Build Coastguard Worker /// [`ErrorCode::KeyRequiresUpgrade`] error.
keyblob_parse_decrypt_backlevel( &self, key_blob: &[u8], params: &[KeyParam], ) -> Result<(keyblob::PlaintextKeyBlob, Option<SecureDeletionSlot>), Error>386*9860b763SAndroid Build Coastguard Worker fn keyblob_parse_decrypt_backlevel(
387*9860b763SAndroid Build Coastguard Worker &self,
388*9860b763SAndroid Build Coastguard Worker key_blob: &[u8],
389*9860b763SAndroid Build Coastguard Worker params: &[KeyParam],
390*9860b763SAndroid Build Coastguard Worker ) -> Result<(keyblob::PlaintextKeyBlob, Option<SecureDeletionSlot>), Error> {
391*9860b763SAndroid Build Coastguard Worker let encrypted_keyblob = match keyblob::EncryptedKeyBlob::new(key_blob) {
392*9860b763SAndroid Build Coastguard Worker Ok(k) => k,
393*9860b763SAndroid Build Coastguard Worker Err(e) => {
394*9860b763SAndroid Build Coastguard Worker // We might have failed to parse the keyblob because it is in some prior format.
395*9860b763SAndroid Build Coastguard Worker if let Some(old_key) = self.dev.legacy_key.as_ref() {
396*9860b763SAndroid Build Coastguard Worker if old_key.is_legacy_key(key_blob, params, self.boot_info()?) {
397*9860b763SAndroid Build Coastguard Worker return Err(km_err!(
398*9860b763SAndroid Build Coastguard Worker KeyRequiresUpgrade,
399*9860b763SAndroid Build Coastguard Worker "legacy key detected, request upgrade"
400*9860b763SAndroid Build Coastguard Worker ));
401*9860b763SAndroid Build Coastguard Worker }
402*9860b763SAndroid Build Coastguard Worker }
403*9860b763SAndroid Build Coastguard Worker return Err(e);
404*9860b763SAndroid Build Coastguard Worker }
405*9860b763SAndroid Build Coastguard Worker };
406*9860b763SAndroid Build Coastguard Worker let hidden = tag::hidden(params, self.root_of_trust()?)?;
407*9860b763SAndroid Build Coastguard Worker let sdd_slot = encrypted_keyblob.secure_deletion_slot();
408*9860b763SAndroid Build Coastguard Worker let root_kek = self.root_kek(encrypted_keyblob.kek_context())?;
409*9860b763SAndroid Build Coastguard Worker let keyblob = keyblob::decrypt(
410*9860b763SAndroid Build Coastguard Worker match &self.dev.sdd_mgr {
411*9860b763SAndroid Build Coastguard Worker None => None,
412*9860b763SAndroid Build Coastguard Worker Some(mr) => Some(&**mr),
413*9860b763SAndroid Build Coastguard Worker },
414*9860b763SAndroid Build Coastguard Worker &*self.imp.aes,
415*9860b763SAndroid Build Coastguard Worker &*self.imp.hkdf,
416*9860b763SAndroid Build Coastguard Worker &root_kek,
417*9860b763SAndroid Build Coastguard Worker encrypted_keyblob,
418*9860b763SAndroid Build Coastguard Worker hidden,
419*9860b763SAndroid Build Coastguard Worker )?;
420*9860b763SAndroid Build Coastguard Worker Ok((keyblob, sdd_slot))
421*9860b763SAndroid Build Coastguard Worker }
422*9860b763SAndroid Build Coastguard Worker
423*9860b763SAndroid Build Coastguard Worker /// Parse and decrypt an encrypted key blob, detecting keys that require upgrade.
keyblob_parse_decrypt( &self, key_blob: &[u8], params: &[KeyParam], ) -> Result<(keyblob::PlaintextKeyBlob, Option<SecureDeletionSlot>), Error>424*9860b763SAndroid Build Coastguard Worker fn keyblob_parse_decrypt(
425*9860b763SAndroid Build Coastguard Worker &self,
426*9860b763SAndroid Build Coastguard Worker key_blob: &[u8],
427*9860b763SAndroid Build Coastguard Worker params: &[KeyParam],
428*9860b763SAndroid Build Coastguard Worker ) -> Result<(keyblob::PlaintextKeyBlob, Option<SecureDeletionSlot>), Error> {
429*9860b763SAndroid Build Coastguard Worker let (keyblob, slot) = self.keyblob_parse_decrypt_backlevel(key_blob, params)?;
430*9860b763SAndroid Build Coastguard Worker
431*9860b763SAndroid Build Coastguard Worker // Check all of the patchlevels and versions to see if key upgrade is required.
432*9860b763SAndroid Build Coastguard Worker fn check(v: &u32, curr: u32, name: &str) -> Result<(), Error> {
433*9860b763SAndroid Build Coastguard Worker match (*v).cmp(&curr) {
434*9860b763SAndroid Build Coastguard Worker Ordering::Less => Err(km_err!(
435*9860b763SAndroid Build Coastguard Worker KeyRequiresUpgrade,
436*9860b763SAndroid Build Coastguard Worker "keyblob with old {} {} needs upgrade to current {}",
437*9860b763SAndroid Build Coastguard Worker name,
438*9860b763SAndroid Build Coastguard Worker v,
439*9860b763SAndroid Build Coastguard Worker curr
440*9860b763SAndroid Build Coastguard Worker )),
441*9860b763SAndroid Build Coastguard Worker Ordering::Equal => Ok(()),
442*9860b763SAndroid Build Coastguard Worker Ordering::Greater => Err(km_err!(
443*9860b763SAndroid Build Coastguard Worker InvalidKeyBlob,
444*9860b763SAndroid Build Coastguard Worker "keyblob with future {} {} (current {})",
445*9860b763SAndroid Build Coastguard Worker name,
446*9860b763SAndroid Build Coastguard Worker v,
447*9860b763SAndroid Build Coastguard Worker curr
448*9860b763SAndroid Build Coastguard Worker )),
449*9860b763SAndroid Build Coastguard Worker }
450*9860b763SAndroid Build Coastguard Worker }
451*9860b763SAndroid Build Coastguard Worker
452*9860b763SAndroid Build Coastguard Worker let key_chars = keyblob.characteristics_at(self.hw_info.security_level)?;
453*9860b763SAndroid Build Coastguard Worker for param in key_chars {
454*9860b763SAndroid Build Coastguard Worker match param {
455*9860b763SAndroid Build Coastguard Worker KeyParam::OsVersion(v) => {
456*9860b763SAndroid Build Coastguard Worker if let Some(hal_info) = &self.hal_info {
457*9860b763SAndroid Build Coastguard Worker if hal_info.os_version == 0 {
458*9860b763SAndroid Build Coastguard Worker // Special case: upgrades to OS version zero are always allowed.
459*9860b763SAndroid Build Coastguard Worker if *v != 0 {
460*9860b763SAndroid Build Coastguard Worker warn!("requesting upgrade to OS version 0");
461*9860b763SAndroid Build Coastguard Worker return Err(km_err!(
462*9860b763SAndroid Build Coastguard Worker KeyRequiresUpgrade,
463*9860b763SAndroid Build Coastguard Worker "keyblob with OS version {} needs upgrade to current version 0",
464*9860b763SAndroid Build Coastguard Worker v,
465*9860b763SAndroid Build Coastguard Worker ));
466*9860b763SAndroid Build Coastguard Worker }
467*9860b763SAndroid Build Coastguard Worker } else {
468*9860b763SAndroid Build Coastguard Worker check(v, hal_info.os_version, "OS version")?;
469*9860b763SAndroid Build Coastguard Worker }
470*9860b763SAndroid Build Coastguard Worker } else {
471*9860b763SAndroid Build Coastguard Worker error!("OS version not available, can't check for upgrade from {}", v);
472*9860b763SAndroid Build Coastguard Worker }
473*9860b763SAndroid Build Coastguard Worker }
474*9860b763SAndroid Build Coastguard Worker KeyParam::OsPatchlevel(v) => {
475*9860b763SAndroid Build Coastguard Worker if let Some(hal_info) = &self.hal_info {
476*9860b763SAndroid Build Coastguard Worker check(v, hal_info.os_patchlevel, "OS patchlevel")?;
477*9860b763SAndroid Build Coastguard Worker } else {
478*9860b763SAndroid Build Coastguard Worker error!("OS patchlevel not available, can't check for upgrade from {}", v);
479*9860b763SAndroid Build Coastguard Worker }
480*9860b763SAndroid Build Coastguard Worker }
481*9860b763SAndroid Build Coastguard Worker KeyParam::VendorPatchlevel(v) => {
482*9860b763SAndroid Build Coastguard Worker if let Some(hal_info) = &self.hal_info {
483*9860b763SAndroid Build Coastguard Worker check(v, hal_info.vendor_patchlevel, "vendor patchlevel")?;
484*9860b763SAndroid Build Coastguard Worker } else {
485*9860b763SAndroid Build Coastguard Worker error!(
486*9860b763SAndroid Build Coastguard Worker "vendor patchlevel not available, can't check for upgrade from {}",
487*9860b763SAndroid Build Coastguard Worker v
488*9860b763SAndroid Build Coastguard Worker );
489*9860b763SAndroid Build Coastguard Worker }
490*9860b763SAndroid Build Coastguard Worker }
491*9860b763SAndroid Build Coastguard Worker KeyParam::BootPatchlevel(v) => {
492*9860b763SAndroid Build Coastguard Worker if let Some(boot_info) = &self.boot_info {
493*9860b763SAndroid Build Coastguard Worker check(v, boot_info.boot_patchlevel, "boot patchlevel")?;
494*9860b763SAndroid Build Coastguard Worker } else {
495*9860b763SAndroid Build Coastguard Worker error!("boot patchlevel not available, can't check for upgrade from {}", v);
496*9860b763SAndroid Build Coastguard Worker }
497*9860b763SAndroid Build Coastguard Worker }
498*9860b763SAndroid Build Coastguard Worker _ => {}
499*9860b763SAndroid Build Coastguard Worker }
500*9860b763SAndroid Build Coastguard Worker }
501*9860b763SAndroid Build Coastguard Worker Ok((keyblob, slot))
502*9860b763SAndroid Build Coastguard Worker }
503*9860b763SAndroid Build Coastguard Worker
504*9860b763SAndroid Build Coastguard Worker /// Generate a unique identifier for a keyblob.
key_id(&self, keyblob: &[u8]) -> Result<KeyId, Error>505*9860b763SAndroid Build Coastguard Worker fn key_id(&self, keyblob: &[u8]) -> Result<KeyId, Error> {
506*9860b763SAndroid Build Coastguard Worker let mut hmac_op =
507*9860b763SAndroid Build Coastguard Worker self.imp.hmac.begin(crypto::hmac::Key(vec_try![0; 16]?).into(), Digest::Sha256)?;
508*9860b763SAndroid Build Coastguard Worker hmac_op.update(keyblob)?;
509*9860b763SAndroid Build Coastguard Worker let tag = hmac_op.finish()?;
510*9860b763SAndroid Build Coastguard Worker
511*9860b763SAndroid Build Coastguard Worker Ok(KeyId(tag.try_into().map_err(|_e| {
512*9860b763SAndroid Build Coastguard Worker km_err!(SecureHwCommunicationFailed, "wrong size output from HMAC-SHA256")
513*9860b763SAndroid Build Coastguard Worker })?))
514*9860b763SAndroid Build Coastguard Worker }
515*9860b763SAndroid Build Coastguard Worker
516*9860b763SAndroid Build Coastguard Worker /// Increment the use count for the given key ID, failing if `max_uses` is reached.
update_use_count(&mut self, key_id: KeyId, max_uses: u32) -> Result<(), Error>517*9860b763SAndroid Build Coastguard Worker fn update_use_count(&mut self, key_id: KeyId, max_uses: u32) -> Result<(), Error> {
518*9860b763SAndroid Build Coastguard Worker let mut free_idx = None;
519*9860b763SAndroid Build Coastguard Worker let mut slot_idx = None;
520*9860b763SAndroid Build Coastguard Worker for idx in 0..self.use_count.len() {
521*9860b763SAndroid Build Coastguard Worker match &self.use_count[idx] {
522*9860b763SAndroid Build Coastguard Worker None if free_idx.is_none() => free_idx = Some(idx),
523*9860b763SAndroid Build Coastguard Worker None => {}
524*9860b763SAndroid Build Coastguard Worker Some(UseCount { key_id: k, count: _count }) if *k == key_id => {
525*9860b763SAndroid Build Coastguard Worker slot_idx = Some(idx);
526*9860b763SAndroid Build Coastguard Worker break;
527*9860b763SAndroid Build Coastguard Worker }
528*9860b763SAndroid Build Coastguard Worker Some(_) => {}
529*9860b763SAndroid Build Coastguard Worker }
530*9860b763SAndroid Build Coastguard Worker }
531*9860b763SAndroid Build Coastguard Worker if slot_idx.is_none() {
532*9860b763SAndroid Build Coastguard Worker // First use of this key ID; use a free slot if available.
533*9860b763SAndroid Build Coastguard Worker if let Some(idx) = free_idx {
534*9860b763SAndroid Build Coastguard Worker self.use_count[idx] = Some(UseCount { key_id, count: 0 });
535*9860b763SAndroid Build Coastguard Worker slot_idx = Some(idx);
536*9860b763SAndroid Build Coastguard Worker }
537*9860b763SAndroid Build Coastguard Worker }
538*9860b763SAndroid Build Coastguard Worker
539*9860b763SAndroid Build Coastguard Worker if let Some(idx) = slot_idx {
540*9860b763SAndroid Build Coastguard Worker let c = self.use_count[idx].as_mut().unwrap(); // safe: code above guarantees
541*9860b763SAndroid Build Coastguard Worker if c.count >= max_uses as u64 {
542*9860b763SAndroid Build Coastguard Worker Err(km_err!(KeyMaxOpsExceeded, "use count {} >= limit {}", c.count, max_uses))
543*9860b763SAndroid Build Coastguard Worker } else {
544*9860b763SAndroid Build Coastguard Worker c.count += 1;
545*9860b763SAndroid Build Coastguard Worker Ok(())
546*9860b763SAndroid Build Coastguard Worker }
547*9860b763SAndroid Build Coastguard Worker } else {
548*9860b763SAndroid Build Coastguard Worker Err(km_err!(TooManyOperations, "too many use-counted keys already in play"))
549*9860b763SAndroid Build Coastguard Worker }
550*9860b763SAndroid Build Coastguard Worker }
551*9860b763SAndroid Build Coastguard Worker
552*9860b763SAndroid Build Coastguard Worker /// Configure the boot-specific root of trust info. KeyMint implementors should call this
553*9860b763SAndroid Build Coastguard Worker /// method when this information arrives from the bootloader (which happens in an
554*9860b763SAndroid Build Coastguard Worker /// implementation-specific manner).
set_boot_info(&mut self, boot_info: keymint::BootInfo) -> Result<(), Error>555*9860b763SAndroid Build Coastguard Worker pub fn set_boot_info(&mut self, boot_info: keymint::BootInfo) -> Result<(), Error> {
556*9860b763SAndroid Build Coastguard Worker if !self.in_early_boot {
557*9860b763SAndroid Build Coastguard Worker error!("Rejecting attempt to set boot info {:?} after early boot", boot_info);
558*9860b763SAndroid Build Coastguard Worker return Err(km_err!(
559*9860b763SAndroid Build Coastguard Worker EarlyBootEnded,
560*9860b763SAndroid Build Coastguard Worker "attempt to set boot info to {boot_info:?} after early boot"
561*9860b763SAndroid Build Coastguard Worker ));
562*9860b763SAndroid Build Coastguard Worker }
563*9860b763SAndroid Build Coastguard Worker if let Some(existing_boot_info) = &self.boot_info {
564*9860b763SAndroid Build Coastguard Worker if *existing_boot_info == boot_info {
565*9860b763SAndroid Build Coastguard Worker warn!(
566*9860b763SAndroid Build Coastguard Worker "Boot info already set, ignoring second attempt to set same values {:?}",
567*9860b763SAndroid Build Coastguard Worker boot_info
568*9860b763SAndroid Build Coastguard Worker );
569*9860b763SAndroid Build Coastguard Worker } else {
570*9860b763SAndroid Build Coastguard Worker return Err(km_err!(
571*9860b763SAndroid Build Coastguard Worker RootOfTrustAlreadySet,
572*9860b763SAndroid Build Coastguard Worker "attempt to set boot info to {:?} but already set to {:?}",
573*9860b763SAndroid Build Coastguard Worker boot_info,
574*9860b763SAndroid Build Coastguard Worker existing_boot_info
575*9860b763SAndroid Build Coastguard Worker ));
576*9860b763SAndroid Build Coastguard Worker }
577*9860b763SAndroid Build Coastguard Worker } else {
578*9860b763SAndroid Build Coastguard Worker info!("Setting boot_info to {:?}", boot_info);
579*9860b763SAndroid Build Coastguard Worker let rot_info = RootOfTrustInfo {
580*9860b763SAndroid Build Coastguard Worker verified_boot_key: boot_info.verified_boot_key.clone(),
581*9860b763SAndroid Build Coastguard Worker device_boot_locked: boot_info.device_boot_locked,
582*9860b763SAndroid Build Coastguard Worker verified_boot_state: boot_info.verified_boot_state,
583*9860b763SAndroid Build Coastguard Worker };
584*9860b763SAndroid Build Coastguard Worker self.boot_info = Some(boot_info);
585*9860b763SAndroid Build Coastguard Worker self.rot_data =
586*9860b763SAndroid Build Coastguard Worker Some(rot_info.into_vec().map_err(|e| {
587*9860b763SAndroid Build Coastguard Worker km_err!(EncodingError, "failed to encode root-of-trust: {:?}", e)
588*9860b763SAndroid Build Coastguard Worker })?);
589*9860b763SAndroid Build Coastguard Worker }
590*9860b763SAndroid Build Coastguard Worker Ok(())
591*9860b763SAndroid Build Coastguard Worker }
592*9860b763SAndroid Build Coastguard Worker
593*9860b763SAndroid Build Coastguard Worker /// Check if HAL-derived information has been set. This is used as an
594*9860b763SAndroid Build Coastguard Worker /// indication that we are past the boot stage.
is_hal_info_set(&self) -> bool595*9860b763SAndroid Build Coastguard Worker pub fn is_hal_info_set(&self) -> bool {
596*9860b763SAndroid Build Coastguard Worker self.hal_info.is_some()
597*9860b763SAndroid Build Coastguard Worker }
598*9860b763SAndroid Build Coastguard Worker
599*9860b763SAndroid Build Coastguard Worker /// Configure the HAL-derived information, learnt from the userspace
600*9860b763SAndroid Build Coastguard Worker /// operating system.
set_hal_info(&mut self, hal_info: HalInfo)601*9860b763SAndroid Build Coastguard Worker pub fn set_hal_info(&mut self, hal_info: HalInfo) {
602*9860b763SAndroid Build Coastguard Worker if self.hal_info.is_none() {
603*9860b763SAndroid Build Coastguard Worker info!("Setting hal_info to {:?}", hal_info);
604*9860b763SAndroid Build Coastguard Worker self.hal_info = Some(hal_info);
605*9860b763SAndroid Build Coastguard Worker } else {
606*9860b763SAndroid Build Coastguard Worker warn!(
607*9860b763SAndroid Build Coastguard Worker "Hal info already set to {:?}, ignoring new values {:?}",
608*9860b763SAndroid Build Coastguard Worker self.hal_info, hal_info
609*9860b763SAndroid Build Coastguard Worker );
610*9860b763SAndroid Build Coastguard Worker }
611*9860b763SAndroid Build Coastguard Worker }
612*9860b763SAndroid Build Coastguard Worker
613*9860b763SAndroid Build Coastguard Worker /// Configure the version of the HAL that this TA should act as.
set_hal_version(&mut self, aidl_version: u32) -> Result<(), Error>614*9860b763SAndroid Build Coastguard Worker pub fn set_hal_version(&mut self, aidl_version: u32) -> Result<(), Error> {
615*9860b763SAndroid Build Coastguard Worker self.aidl_version = match aidl_version {
616*9860b763SAndroid Build Coastguard Worker 100 => KeyMintHalVersion::V1,
617*9860b763SAndroid Build Coastguard Worker 200 => KeyMintHalVersion::V2,
618*9860b763SAndroid Build Coastguard Worker 300 => KeyMintHalVersion::V3,
619*9860b763SAndroid Build Coastguard Worker 400 => KeyMintHalVersion::V4,
620*9860b763SAndroid Build Coastguard Worker _ => return Err(km_err!(InvalidArgument, "unsupported HAL version {}", aidl_version)),
621*9860b763SAndroid Build Coastguard Worker };
622*9860b763SAndroid Build Coastguard Worker info!("Set aidl_version to {:?}", self.aidl_version);
623*9860b763SAndroid Build Coastguard Worker Ok(())
624*9860b763SAndroid Build Coastguard Worker }
625*9860b763SAndroid Build Coastguard Worker
626*9860b763SAndroid Build Coastguard Worker /// Configure attestation IDs externally.
set_attestation_ids(&self, ids: AttestationIdInfo)627*9860b763SAndroid Build Coastguard Worker pub fn set_attestation_ids(&self, ids: AttestationIdInfo) {
628*9860b763SAndroid Build Coastguard Worker if self.dev.attest_ids.is_some() {
629*9860b763SAndroid Build Coastguard Worker error!("Attempt to set attestation IDs externally");
630*9860b763SAndroid Build Coastguard Worker } else if self.attestation_id_info.borrow().is_some() {
631*9860b763SAndroid Build Coastguard Worker error!("Attempt to set attestation IDs when already set");
632*9860b763SAndroid Build Coastguard Worker } else {
633*9860b763SAndroid Build Coastguard Worker warn!("Setting attestation IDs directly");
634*9860b763SAndroid Build Coastguard Worker *self.attestation_id_info.borrow_mut() = Some(Rc::new(ids));
635*9860b763SAndroid Build Coastguard Worker }
636*9860b763SAndroid Build Coastguard Worker }
637*9860b763SAndroid Build Coastguard Worker
638*9860b763SAndroid Build Coastguard Worker /// Retrieve the attestation ID information for the device, if available.
get_attestation_ids(&self) -> Option<Rc<AttestationIdInfo>>639*9860b763SAndroid Build Coastguard Worker fn get_attestation_ids(&self) -> Option<Rc<AttestationIdInfo>> {
640*9860b763SAndroid Build Coastguard Worker if self.attestation_id_info.borrow().is_none() {
641*9860b763SAndroid Build Coastguard Worker if let Some(get_ids_impl) = self.dev.attest_ids.as_ref() {
642*9860b763SAndroid Build Coastguard Worker // Attestation IDs are not populated, but we have a trait implementation that
643*9860b763SAndroid Build Coastguard Worker // may provide them.
644*9860b763SAndroid Build Coastguard Worker match get_ids_impl.get() {
645*9860b763SAndroid Build Coastguard Worker Ok(ids) => *self.attestation_id_info.borrow_mut() = Some(Rc::new(ids)),
646*9860b763SAndroid Build Coastguard Worker Err(e) => error!("Failed to retrieve attestation IDs: {:?}", e),
647*9860b763SAndroid Build Coastguard Worker }
648*9860b763SAndroid Build Coastguard Worker }
649*9860b763SAndroid Build Coastguard Worker }
650*9860b763SAndroid Build Coastguard Worker self.attestation_id_info.borrow().as_ref().cloned()
651*9860b763SAndroid Build Coastguard Worker }
652*9860b763SAndroid Build Coastguard Worker
653*9860b763SAndroid Build Coastguard Worker /// Retrieve the DICE info for the device, if available.
get_dice_info(&self) -> Option<Rc<DiceInfo>>654*9860b763SAndroid Build Coastguard Worker fn get_dice_info(&self) -> Option<Rc<DiceInfo>> {
655*9860b763SAndroid Build Coastguard Worker if self.dice_info.borrow().is_none() {
656*9860b763SAndroid Build Coastguard Worker // DICE info is not populated, but we have a trait method that
657*9860b763SAndroid Build Coastguard Worker // may provide them.
658*9860b763SAndroid Build Coastguard Worker match self.dev.rpc.get_dice_info(rpc::TestMode(false)) {
659*9860b763SAndroid Build Coastguard Worker Ok(dice_info) => *self.dice_info.borrow_mut() = Some(Rc::new(dice_info)),
660*9860b763SAndroid Build Coastguard Worker Err(e) => error!("Failed to retrieve DICE info: {:?}", e),
661*9860b763SAndroid Build Coastguard Worker }
662*9860b763SAndroid Build Coastguard Worker }
663*9860b763SAndroid Build Coastguard Worker self.dice_info.borrow().as_ref().cloned()
664*9860b763SAndroid Build Coastguard Worker }
665*9860b763SAndroid Build Coastguard Worker
666*9860b763SAndroid Build Coastguard Worker /// Process a single serialized request, returning a serialized response.
process(&mut self, req_data: &[u8]) -> Vec<u8>667*9860b763SAndroid Build Coastguard Worker pub fn process(&mut self, req_data: &[u8]) -> Vec<u8> {
668*9860b763SAndroid Build Coastguard Worker let (req_code, rsp) = match PerformOpReq::from_slice(req_data) {
669*9860b763SAndroid Build Coastguard Worker Ok(req) => {
670*9860b763SAndroid Build Coastguard Worker trace!("-> TA: received request {:?}", req.code());
671*9860b763SAndroid Build Coastguard Worker (Some(req.code()), self.process_req(req))
672*9860b763SAndroid Build Coastguard Worker }
673*9860b763SAndroid Build Coastguard Worker Err(e) => {
674*9860b763SAndroid Build Coastguard Worker error!("failed to decode CBOR request: {:?}", e);
675*9860b763SAndroid Build Coastguard Worker // We need to report the error to the HAL, but we don't know whether the request was
676*9860b763SAndroid Build Coastguard Worker // for the `IRemotelyProvisionedComponent` or for one of the other HALs, so we don't
677*9860b763SAndroid Build Coastguard Worker // know what numbering space the error codes are expected to be in. Assume the
678*9860b763SAndroid Build Coastguard Worker // shared KeyMint `ErrorCode` space.
679*9860b763SAndroid Build Coastguard Worker (None, error_rsp(ErrorCode::EncodingError as i32))
680*9860b763SAndroid Build Coastguard Worker }
681*9860b763SAndroid Build Coastguard Worker };
682*9860b763SAndroid Build Coastguard Worker trace!("<- TA: send response {:?} rc {}", req_code, rsp.error_code);
683*9860b763SAndroid Build Coastguard Worker match rsp.into_vec() {
684*9860b763SAndroid Build Coastguard Worker Ok(rsp_data) => rsp_data,
685*9860b763SAndroid Build Coastguard Worker Err(e) => {
686*9860b763SAndroid Build Coastguard Worker error!("failed to encode CBOR response: {:?}", e);
687*9860b763SAndroid Build Coastguard Worker invalid_cbor_rsp_data().to_vec()
688*9860b763SAndroid Build Coastguard Worker }
689*9860b763SAndroid Build Coastguard Worker }
690*9860b763SAndroid Build Coastguard Worker }
691*9860b763SAndroid Build Coastguard Worker
692*9860b763SAndroid Build Coastguard Worker /// Process a single request, returning a [`PerformOpResponse`].
693*9860b763SAndroid Build Coastguard Worker ///
694*9860b763SAndroid Build Coastguard Worker /// Select the appropriate method based on the request type, and use the
695*9860b763SAndroid Build Coastguard Worker /// request fields as parameters to the method. In the opposite direction,
696*9860b763SAndroid Build Coastguard Worker /// build a response message from the values returned by the method.
process_req(&mut self, req: PerformOpReq) -> PerformOpResponse697*9860b763SAndroid Build Coastguard Worker fn process_req(&mut self, req: PerformOpReq) -> PerformOpResponse {
698*9860b763SAndroid Build Coastguard Worker match req {
699*9860b763SAndroid Build Coastguard Worker // Internal messages.
700*9860b763SAndroid Build Coastguard Worker PerformOpReq::SetBootInfo(req) => {
701*9860b763SAndroid Build Coastguard Worker let verified_boot_state = match VerifiedBootState::try_from(req.verified_boot_state)
702*9860b763SAndroid Build Coastguard Worker {
703*9860b763SAndroid Build Coastguard Worker Ok(state) => state,
704*9860b763SAndroid Build Coastguard Worker Err(e) => return op_error_rsp(SetBootInfoRequest::CODE, Error::Cbor(e)),
705*9860b763SAndroid Build Coastguard Worker };
706*9860b763SAndroid Build Coastguard Worker match self.set_boot_info(keymint::BootInfo {
707*9860b763SAndroid Build Coastguard Worker verified_boot_key: req.verified_boot_key,
708*9860b763SAndroid Build Coastguard Worker device_boot_locked: req.device_boot_locked,
709*9860b763SAndroid Build Coastguard Worker verified_boot_state,
710*9860b763SAndroid Build Coastguard Worker verified_boot_hash: req.verified_boot_hash,
711*9860b763SAndroid Build Coastguard Worker boot_patchlevel: req.boot_patchlevel,
712*9860b763SAndroid Build Coastguard Worker }) {
713*9860b763SAndroid Build Coastguard Worker Ok(_) => op_ok_rsp(PerformOpRsp::SetBootInfo(SetBootInfoResponse {})),
714*9860b763SAndroid Build Coastguard Worker Err(e) => op_error_rsp(SetBootInfoRequest::CODE, e),
715*9860b763SAndroid Build Coastguard Worker }
716*9860b763SAndroid Build Coastguard Worker }
717*9860b763SAndroid Build Coastguard Worker PerformOpReq::SetHalInfo(req) => {
718*9860b763SAndroid Build Coastguard Worker self.set_hal_info(HalInfo {
719*9860b763SAndroid Build Coastguard Worker os_version: req.os_version,
720*9860b763SAndroid Build Coastguard Worker os_patchlevel: req.os_patchlevel,
721*9860b763SAndroid Build Coastguard Worker vendor_patchlevel: req.vendor_patchlevel,
722*9860b763SAndroid Build Coastguard Worker });
723*9860b763SAndroid Build Coastguard Worker op_ok_rsp(PerformOpRsp::SetHalInfo(SetHalInfoResponse {}))
724*9860b763SAndroid Build Coastguard Worker }
725*9860b763SAndroid Build Coastguard Worker PerformOpReq::SetAttestationIds(req) => {
726*9860b763SAndroid Build Coastguard Worker self.set_attestation_ids(req.ids);
727*9860b763SAndroid Build Coastguard Worker op_ok_rsp(PerformOpRsp::SetAttestationIds(SetAttestationIdsResponse {}))
728*9860b763SAndroid Build Coastguard Worker }
729*9860b763SAndroid Build Coastguard Worker PerformOpReq::SetHalVersion(req) => match self.set_hal_version(req.aidl_version) {
730*9860b763SAndroid Build Coastguard Worker Ok(_) => op_ok_rsp(PerformOpRsp::SetHalVersion(SetHalVersionResponse {})),
731*9860b763SAndroid Build Coastguard Worker Err(e) => op_error_rsp(SetHalVersionRequest::CODE, e),
732*9860b763SAndroid Build Coastguard Worker },
733*9860b763SAndroid Build Coastguard Worker
734*9860b763SAndroid Build Coastguard Worker // ISharedSecret messages.
735*9860b763SAndroid Build Coastguard Worker PerformOpReq::SharedSecretGetSharedSecretParameters(_req) => {
736*9860b763SAndroid Build Coastguard Worker match self.get_shared_secret_params() {
737*9860b763SAndroid Build Coastguard Worker Ok(ret) => op_ok_rsp(PerformOpRsp::SharedSecretGetSharedSecretParameters(
738*9860b763SAndroid Build Coastguard Worker GetSharedSecretParametersResponse { ret },
739*9860b763SAndroid Build Coastguard Worker )),
740*9860b763SAndroid Build Coastguard Worker Err(e) => op_error_rsp(GetSharedSecretParametersRequest::CODE, e),
741*9860b763SAndroid Build Coastguard Worker }
742*9860b763SAndroid Build Coastguard Worker }
743*9860b763SAndroid Build Coastguard Worker PerformOpReq::SharedSecretComputeSharedSecret(req) => {
744*9860b763SAndroid Build Coastguard Worker match self.compute_shared_secret(&req.params) {
745*9860b763SAndroid Build Coastguard Worker Ok(ret) => op_ok_rsp(PerformOpRsp::SharedSecretComputeSharedSecret(
746*9860b763SAndroid Build Coastguard Worker ComputeSharedSecretResponse { ret },
747*9860b763SAndroid Build Coastguard Worker )),
748*9860b763SAndroid Build Coastguard Worker Err(e) => op_error_rsp(ComputeSharedSecretRequest::CODE, e),
749*9860b763SAndroid Build Coastguard Worker }
750*9860b763SAndroid Build Coastguard Worker }
751*9860b763SAndroid Build Coastguard Worker
752*9860b763SAndroid Build Coastguard Worker // ISecureClock messages.
753*9860b763SAndroid Build Coastguard Worker PerformOpReq::SecureClockGenerateTimeStamp(req) => {
754*9860b763SAndroid Build Coastguard Worker match self.generate_timestamp(req.challenge) {
755*9860b763SAndroid Build Coastguard Worker Ok(ret) => op_ok_rsp(PerformOpRsp::SecureClockGenerateTimeStamp(
756*9860b763SAndroid Build Coastguard Worker GenerateTimeStampResponse { ret },
757*9860b763SAndroid Build Coastguard Worker )),
758*9860b763SAndroid Build Coastguard Worker Err(e) => op_error_rsp(GenerateTimeStampRequest::CODE, e),
759*9860b763SAndroid Build Coastguard Worker }
760*9860b763SAndroid Build Coastguard Worker }
761*9860b763SAndroid Build Coastguard Worker
762*9860b763SAndroid Build Coastguard Worker // IKeyMintDevice messages.
763*9860b763SAndroid Build Coastguard Worker PerformOpReq::DeviceGetHardwareInfo(_req) => match self.get_hardware_info() {
764*9860b763SAndroid Build Coastguard Worker Ok(ret) => {
765*9860b763SAndroid Build Coastguard Worker op_ok_rsp(PerformOpRsp::DeviceGetHardwareInfo(GetHardwareInfoResponse { ret }))
766*9860b763SAndroid Build Coastguard Worker }
767*9860b763SAndroid Build Coastguard Worker Err(e) => op_error_rsp(GetHardwareInfoRequest::CODE, e),
768*9860b763SAndroid Build Coastguard Worker },
769*9860b763SAndroid Build Coastguard Worker PerformOpReq::DeviceAddRngEntropy(req) => match self.add_rng_entropy(&req.data) {
770*9860b763SAndroid Build Coastguard Worker Ok(_ret) => op_ok_rsp(PerformOpRsp::DeviceAddRngEntropy(AddRngEntropyResponse {})),
771*9860b763SAndroid Build Coastguard Worker Err(e) => op_error_rsp(AddRngEntropyRequest::CODE, e),
772*9860b763SAndroid Build Coastguard Worker },
773*9860b763SAndroid Build Coastguard Worker PerformOpReq::DeviceGenerateKey(req) => {
774*9860b763SAndroid Build Coastguard Worker match self.generate_key(&req.key_params, req.attestation_key) {
775*9860b763SAndroid Build Coastguard Worker Ok(ret) => {
776*9860b763SAndroid Build Coastguard Worker op_ok_rsp(PerformOpRsp::DeviceGenerateKey(GenerateKeyResponse { ret }))
777*9860b763SAndroid Build Coastguard Worker }
778*9860b763SAndroid Build Coastguard Worker Err(e) => op_error_rsp(GenerateKeyRequest::CODE, e),
779*9860b763SAndroid Build Coastguard Worker }
780*9860b763SAndroid Build Coastguard Worker }
781*9860b763SAndroid Build Coastguard Worker PerformOpReq::DeviceImportKey(req) => {
782*9860b763SAndroid Build Coastguard Worker match self.import_key(
783*9860b763SAndroid Build Coastguard Worker &req.key_params,
784*9860b763SAndroid Build Coastguard Worker req.key_format,
785*9860b763SAndroid Build Coastguard Worker &req.key_data,
786*9860b763SAndroid Build Coastguard Worker req.attestation_key,
787*9860b763SAndroid Build Coastguard Worker KeyImport::NonWrapped,
788*9860b763SAndroid Build Coastguard Worker ) {
789*9860b763SAndroid Build Coastguard Worker Ok(ret) => op_ok_rsp(PerformOpRsp::DeviceImportKey(ImportKeyResponse { ret })),
790*9860b763SAndroid Build Coastguard Worker Err(e) => op_error_rsp(ImportKeyRequest::CODE, e),
791*9860b763SAndroid Build Coastguard Worker }
792*9860b763SAndroid Build Coastguard Worker }
793*9860b763SAndroid Build Coastguard Worker PerformOpReq::DeviceImportWrappedKey(req) => {
794*9860b763SAndroid Build Coastguard Worker match self.import_wrapped_key(
795*9860b763SAndroid Build Coastguard Worker &req.wrapped_key_data,
796*9860b763SAndroid Build Coastguard Worker &req.wrapping_key_blob,
797*9860b763SAndroid Build Coastguard Worker &req.masking_key,
798*9860b763SAndroid Build Coastguard Worker &req.unwrapping_params,
799*9860b763SAndroid Build Coastguard Worker req.password_sid,
800*9860b763SAndroid Build Coastguard Worker req.biometric_sid,
801*9860b763SAndroid Build Coastguard Worker ) {
802*9860b763SAndroid Build Coastguard Worker Ok(ret) => {
803*9860b763SAndroid Build Coastguard Worker op_ok_rsp(PerformOpRsp::DeviceImportWrappedKey(ImportWrappedKeyResponse {
804*9860b763SAndroid Build Coastguard Worker ret,
805*9860b763SAndroid Build Coastguard Worker }))
806*9860b763SAndroid Build Coastguard Worker }
807*9860b763SAndroid Build Coastguard Worker Err(e) => op_error_rsp(ImportWrappedKeyRequest::CODE, e),
808*9860b763SAndroid Build Coastguard Worker }
809*9860b763SAndroid Build Coastguard Worker }
810*9860b763SAndroid Build Coastguard Worker PerformOpReq::DeviceUpgradeKey(req) => {
811*9860b763SAndroid Build Coastguard Worker match self.upgrade_key(&req.key_blob_to_upgrade, req.upgrade_params) {
812*9860b763SAndroid Build Coastguard Worker Ok(ret) => {
813*9860b763SAndroid Build Coastguard Worker op_ok_rsp(PerformOpRsp::DeviceUpgradeKey(UpgradeKeyResponse { ret }))
814*9860b763SAndroid Build Coastguard Worker }
815*9860b763SAndroid Build Coastguard Worker Err(e) => op_error_rsp(UpgradeKeyRequest::CODE, e),
816*9860b763SAndroid Build Coastguard Worker }
817*9860b763SAndroid Build Coastguard Worker }
818*9860b763SAndroid Build Coastguard Worker PerformOpReq::DeviceDeleteKey(req) => match self.delete_key(&req.key_blob) {
819*9860b763SAndroid Build Coastguard Worker Ok(_ret) => op_ok_rsp(PerformOpRsp::DeviceDeleteKey(DeleteKeyResponse {})),
820*9860b763SAndroid Build Coastguard Worker Err(e) => op_error_rsp(DeleteKeyRequest::CODE, e),
821*9860b763SAndroid Build Coastguard Worker },
822*9860b763SAndroid Build Coastguard Worker PerformOpReq::DeviceDeleteAllKeys(_req) => match self.delete_all_keys() {
823*9860b763SAndroid Build Coastguard Worker Ok(_ret) => op_ok_rsp(PerformOpRsp::DeviceDeleteAllKeys(DeleteAllKeysResponse {})),
824*9860b763SAndroid Build Coastguard Worker Err(e) => op_error_rsp(DeleteAllKeysRequest::CODE, e),
825*9860b763SAndroid Build Coastguard Worker },
826*9860b763SAndroid Build Coastguard Worker PerformOpReq::DeviceDestroyAttestationIds(_req) => match self.destroy_attestation_ids()
827*9860b763SAndroid Build Coastguard Worker {
828*9860b763SAndroid Build Coastguard Worker Ok(_ret) => op_ok_rsp(PerformOpRsp::DeviceDestroyAttestationIds(
829*9860b763SAndroid Build Coastguard Worker DestroyAttestationIdsResponse {},
830*9860b763SAndroid Build Coastguard Worker )),
831*9860b763SAndroid Build Coastguard Worker Err(e) => op_error_rsp(DestroyAttestationIdsRequest::CODE, e),
832*9860b763SAndroid Build Coastguard Worker },
833*9860b763SAndroid Build Coastguard Worker PerformOpReq::DeviceBegin(req) => {
834*9860b763SAndroid Build Coastguard Worker match self.begin_operation(req.purpose, &req.key_blob, req.params, req.auth_token) {
835*9860b763SAndroid Build Coastguard Worker Ok(ret) => op_ok_rsp(PerformOpRsp::DeviceBegin(BeginResponse { ret })),
836*9860b763SAndroid Build Coastguard Worker Err(e) => op_error_rsp(BeginRequest::CODE, e),
837*9860b763SAndroid Build Coastguard Worker }
838*9860b763SAndroid Build Coastguard Worker }
839*9860b763SAndroid Build Coastguard Worker PerformOpReq::DeviceEarlyBootEnded(_req) => match self.early_boot_ended() {
840*9860b763SAndroid Build Coastguard Worker Ok(_ret) => {
841*9860b763SAndroid Build Coastguard Worker op_ok_rsp(PerformOpRsp::DeviceEarlyBootEnded(EarlyBootEndedResponse {}))
842*9860b763SAndroid Build Coastguard Worker }
843*9860b763SAndroid Build Coastguard Worker Err(e) => op_error_rsp(EarlyBootEndedRequest::CODE, e),
844*9860b763SAndroid Build Coastguard Worker },
845*9860b763SAndroid Build Coastguard Worker PerformOpReq::DeviceConvertStorageKeyToEphemeral(req) => {
846*9860b763SAndroid Build Coastguard Worker match self.convert_storage_key_to_ephemeral(&req.storage_key_blob) {
847*9860b763SAndroid Build Coastguard Worker Ok(ret) => op_ok_rsp(PerformOpRsp::DeviceConvertStorageKeyToEphemeral(
848*9860b763SAndroid Build Coastguard Worker ConvertStorageKeyToEphemeralResponse { ret },
849*9860b763SAndroid Build Coastguard Worker )),
850*9860b763SAndroid Build Coastguard Worker Err(e) => op_error_rsp(ConvertStorageKeyToEphemeralRequest::CODE, e),
851*9860b763SAndroid Build Coastguard Worker }
852*9860b763SAndroid Build Coastguard Worker }
853*9860b763SAndroid Build Coastguard Worker PerformOpReq::DeviceGetKeyCharacteristics(req) => {
854*9860b763SAndroid Build Coastguard Worker match self.get_key_characteristics(&req.key_blob, req.app_id, req.app_data) {
855*9860b763SAndroid Build Coastguard Worker Ok(ret) => op_ok_rsp(PerformOpRsp::DeviceGetKeyCharacteristics(
856*9860b763SAndroid Build Coastguard Worker GetKeyCharacteristicsResponse { ret },
857*9860b763SAndroid Build Coastguard Worker )),
858*9860b763SAndroid Build Coastguard Worker Err(e) => op_error_rsp(GetKeyCharacteristicsRequest::CODE, e),
859*9860b763SAndroid Build Coastguard Worker }
860*9860b763SAndroid Build Coastguard Worker }
861*9860b763SAndroid Build Coastguard Worker PerformOpReq::GetRootOfTrustChallenge(_req) => match self.get_root_of_trust_challenge()
862*9860b763SAndroid Build Coastguard Worker {
863*9860b763SAndroid Build Coastguard Worker Ok(ret) => op_ok_rsp(PerformOpRsp::GetRootOfTrustChallenge(
864*9860b763SAndroid Build Coastguard Worker GetRootOfTrustChallengeResponse { ret },
865*9860b763SAndroid Build Coastguard Worker )),
866*9860b763SAndroid Build Coastguard Worker Err(e) => op_error_rsp(GetRootOfTrustChallengeRequest::CODE, e),
867*9860b763SAndroid Build Coastguard Worker },
868*9860b763SAndroid Build Coastguard Worker PerformOpReq::GetRootOfTrust(req) => match self.get_root_of_trust(&req.challenge) {
869*9860b763SAndroid Build Coastguard Worker Ok(ret) => op_ok_rsp(PerformOpRsp::GetRootOfTrust(GetRootOfTrustResponse { ret })),
870*9860b763SAndroid Build Coastguard Worker Err(e) => op_error_rsp(GetRootOfTrustRequest::CODE, e),
871*9860b763SAndroid Build Coastguard Worker },
872*9860b763SAndroid Build Coastguard Worker PerformOpReq::SendRootOfTrust(req) => {
873*9860b763SAndroid Build Coastguard Worker match self.send_root_of_trust(&req.root_of_trust) {
874*9860b763SAndroid Build Coastguard Worker Ok(_ret) => {
875*9860b763SAndroid Build Coastguard Worker op_ok_rsp(PerformOpRsp::SendRootOfTrust(SendRootOfTrustResponse {}))
876*9860b763SAndroid Build Coastguard Worker }
877*9860b763SAndroid Build Coastguard Worker Err(e) => op_error_rsp(SendRootOfTrustRequest::CODE, e),
878*9860b763SAndroid Build Coastguard Worker }
879*9860b763SAndroid Build Coastguard Worker }
880*9860b763SAndroid Build Coastguard Worker PerformOpReq::SetAdditionalAttestationInfo(req) => {
881*9860b763SAndroid Build Coastguard Worker match self.set_additional_attestation_info(req.info) {
882*9860b763SAndroid Build Coastguard Worker Ok(_ret) => op_ok_rsp(PerformOpRsp::SetAdditionalAttestationInfo(
883*9860b763SAndroid Build Coastguard Worker SetAdditionalAttestationInfoResponse {},
884*9860b763SAndroid Build Coastguard Worker )),
885*9860b763SAndroid Build Coastguard Worker Err(e) => op_error_rsp(SetAdditionalAttestationInfoRequest::CODE, e),
886*9860b763SAndroid Build Coastguard Worker }
887*9860b763SAndroid Build Coastguard Worker }
888*9860b763SAndroid Build Coastguard Worker
889*9860b763SAndroid Build Coastguard Worker // IKeyMintOperation messages.
890*9860b763SAndroid Build Coastguard Worker PerformOpReq::OperationUpdateAad(req) => match self.op_update_aad(
891*9860b763SAndroid Build Coastguard Worker OpHandle(req.op_handle),
892*9860b763SAndroid Build Coastguard Worker &req.input,
893*9860b763SAndroid Build Coastguard Worker req.auth_token,
894*9860b763SAndroid Build Coastguard Worker req.timestamp_token,
895*9860b763SAndroid Build Coastguard Worker ) {
896*9860b763SAndroid Build Coastguard Worker Ok(_ret) => op_ok_rsp(PerformOpRsp::OperationUpdateAad(UpdateAadResponse {})),
897*9860b763SAndroid Build Coastguard Worker Err(e) => op_error_rsp(UpdateAadRequest::CODE, e),
898*9860b763SAndroid Build Coastguard Worker },
899*9860b763SAndroid Build Coastguard Worker PerformOpReq::OperationUpdate(req) => {
900*9860b763SAndroid Build Coastguard Worker match self.op_update(
901*9860b763SAndroid Build Coastguard Worker OpHandle(req.op_handle),
902*9860b763SAndroid Build Coastguard Worker &req.input,
903*9860b763SAndroid Build Coastguard Worker req.auth_token,
904*9860b763SAndroid Build Coastguard Worker req.timestamp_token,
905*9860b763SAndroid Build Coastguard Worker ) {
906*9860b763SAndroid Build Coastguard Worker Ok(ret) => op_ok_rsp(PerformOpRsp::OperationUpdate(UpdateResponse { ret })),
907*9860b763SAndroid Build Coastguard Worker Err(e) => op_error_rsp(UpdateRequest::CODE, e),
908*9860b763SAndroid Build Coastguard Worker }
909*9860b763SAndroid Build Coastguard Worker }
910*9860b763SAndroid Build Coastguard Worker PerformOpReq::OperationFinish(req) => {
911*9860b763SAndroid Build Coastguard Worker match self.op_finish(
912*9860b763SAndroid Build Coastguard Worker OpHandle(req.op_handle),
913*9860b763SAndroid Build Coastguard Worker req.input.as_deref(),
914*9860b763SAndroid Build Coastguard Worker req.signature.as_deref(),
915*9860b763SAndroid Build Coastguard Worker req.auth_token,
916*9860b763SAndroid Build Coastguard Worker req.timestamp_token,
917*9860b763SAndroid Build Coastguard Worker req.confirmation_token.as_deref(),
918*9860b763SAndroid Build Coastguard Worker ) {
919*9860b763SAndroid Build Coastguard Worker Ok(ret) => op_ok_rsp(PerformOpRsp::OperationFinish(FinishResponse { ret })),
920*9860b763SAndroid Build Coastguard Worker Err(e) => op_error_rsp(FinishRequest::CODE, e),
921*9860b763SAndroid Build Coastguard Worker }
922*9860b763SAndroid Build Coastguard Worker }
923*9860b763SAndroid Build Coastguard Worker PerformOpReq::OperationAbort(req) => match self.op_abort(OpHandle(req.op_handle)) {
924*9860b763SAndroid Build Coastguard Worker Ok(_ret) => op_ok_rsp(PerformOpRsp::OperationAbort(AbortResponse {})),
925*9860b763SAndroid Build Coastguard Worker Err(e) => op_error_rsp(AbortRequest::CODE, e),
926*9860b763SAndroid Build Coastguard Worker },
927*9860b763SAndroid Build Coastguard Worker
928*9860b763SAndroid Build Coastguard Worker // IRemotelyProvisionedComponentOperation messages.
929*9860b763SAndroid Build Coastguard Worker PerformOpReq::RpcGetHardwareInfo(_req) => match self.get_rpc_hardware_info() {
930*9860b763SAndroid Build Coastguard Worker Ok(ret) => {
931*9860b763SAndroid Build Coastguard Worker op_ok_rsp(PerformOpRsp::RpcGetHardwareInfo(GetRpcHardwareInfoResponse { ret }))
932*9860b763SAndroid Build Coastguard Worker }
933*9860b763SAndroid Build Coastguard Worker Err(e) => op_error_rsp(GetRpcHardwareInfoRequest::CODE, e),
934*9860b763SAndroid Build Coastguard Worker },
935*9860b763SAndroid Build Coastguard Worker PerformOpReq::RpcGenerateEcdsaP256KeyPair(req) => {
936*9860b763SAndroid Build Coastguard Worker match self.generate_ecdsa_p256_keypair(rpc::TestMode(req.test_mode)) {
937*9860b763SAndroid Build Coastguard Worker Ok((pubkey, ret)) => op_ok_rsp(PerformOpRsp::RpcGenerateEcdsaP256KeyPair(
938*9860b763SAndroid Build Coastguard Worker GenerateEcdsaP256KeyPairResponse { maced_public_key: pubkey, ret },
939*9860b763SAndroid Build Coastguard Worker )),
940*9860b763SAndroid Build Coastguard Worker Err(e) => op_error_rsp(GenerateEcdsaP256KeyPairRequest::CODE, e),
941*9860b763SAndroid Build Coastguard Worker }
942*9860b763SAndroid Build Coastguard Worker }
943*9860b763SAndroid Build Coastguard Worker PerformOpReq::RpcGenerateCertificateRequest(req) => {
944*9860b763SAndroid Build Coastguard Worker match self.generate_cert_req(
945*9860b763SAndroid Build Coastguard Worker rpc::TestMode(req.test_mode),
946*9860b763SAndroid Build Coastguard Worker req.keys_to_sign,
947*9860b763SAndroid Build Coastguard Worker &req.endpoint_encryption_cert_chain,
948*9860b763SAndroid Build Coastguard Worker &req.challenge,
949*9860b763SAndroid Build Coastguard Worker ) {
950*9860b763SAndroid Build Coastguard Worker Ok((device_info, protected_data, ret)) => {
951*9860b763SAndroid Build Coastguard Worker op_ok_rsp(PerformOpRsp::RpcGenerateCertificateRequest(
952*9860b763SAndroid Build Coastguard Worker GenerateCertificateRequestResponse { device_info, protected_data, ret },
953*9860b763SAndroid Build Coastguard Worker ))
954*9860b763SAndroid Build Coastguard Worker }
955*9860b763SAndroid Build Coastguard Worker Err(e) => op_error_rsp(GenerateCertificateRequestRequest::CODE, e),
956*9860b763SAndroid Build Coastguard Worker }
957*9860b763SAndroid Build Coastguard Worker }
958*9860b763SAndroid Build Coastguard Worker PerformOpReq::RpcGenerateCertificateV2Request(req) => {
959*9860b763SAndroid Build Coastguard Worker match self.generate_cert_req_v2(req.keys_to_sign, &req.challenge) {
960*9860b763SAndroid Build Coastguard Worker Ok(ret) => op_ok_rsp(PerformOpRsp::RpcGenerateCertificateV2Request(
961*9860b763SAndroid Build Coastguard Worker GenerateCertificateRequestV2Response { ret },
962*9860b763SAndroid Build Coastguard Worker )),
963*9860b763SAndroid Build Coastguard Worker Err(e) => op_error_rsp(GenerateCertificateRequestV2Request::CODE, e),
964*9860b763SAndroid Build Coastguard Worker }
965*9860b763SAndroid Build Coastguard Worker }
966*9860b763SAndroid Build Coastguard Worker }
967*9860b763SAndroid Build Coastguard Worker }
968*9860b763SAndroid Build Coastguard Worker
add_rng_entropy(&mut self, data: &[u8]) -> Result<(), Error>969*9860b763SAndroid Build Coastguard Worker fn add_rng_entropy(&mut self, data: &[u8]) -> Result<(), Error> {
970*9860b763SAndroid Build Coastguard Worker if data.len() > 2048 {
971*9860b763SAndroid Build Coastguard Worker return Err(km_err!(InvalidInputLength, "entropy size {} too large", data.len()));
972*9860b763SAndroid Build Coastguard Worker };
973*9860b763SAndroid Build Coastguard Worker
974*9860b763SAndroid Build Coastguard Worker info!("add {} bytes of entropy", data.len());
975*9860b763SAndroid Build Coastguard Worker self.imp.rng.add_entropy(data);
976*9860b763SAndroid Build Coastguard Worker Ok(())
977*9860b763SAndroid Build Coastguard Worker }
978*9860b763SAndroid Build Coastguard Worker
early_boot_ended(&mut self) -> Result<(), Error>979*9860b763SAndroid Build Coastguard Worker fn early_boot_ended(&mut self) -> Result<(), Error> {
980*9860b763SAndroid Build Coastguard Worker info!("early boot ended");
981*9860b763SAndroid Build Coastguard Worker self.in_early_boot = false;
982*9860b763SAndroid Build Coastguard Worker Ok(())
983*9860b763SAndroid Build Coastguard Worker }
984*9860b763SAndroid Build Coastguard Worker
get_hardware_info(&self) -> Result<KeyMintHardwareInfo, Error>985*9860b763SAndroid Build Coastguard Worker fn get_hardware_info(&self) -> Result<KeyMintHardwareInfo, Error> {
986*9860b763SAndroid Build Coastguard Worker Ok(KeyMintHardwareInfo {
987*9860b763SAndroid Build Coastguard Worker version_number: self.hw_info.version_number,
988*9860b763SAndroid Build Coastguard Worker security_level: self.hw_info.security_level,
989*9860b763SAndroid Build Coastguard Worker key_mint_name: self.hw_info.impl_name.to_string(),
990*9860b763SAndroid Build Coastguard Worker key_mint_author_name: self.hw_info.author_name.to_string(),
991*9860b763SAndroid Build Coastguard Worker timestamp_token_required: self.imp.clock.is_none(),
992*9860b763SAndroid Build Coastguard Worker })
993*9860b763SAndroid Build Coastguard Worker }
994*9860b763SAndroid Build Coastguard Worker
delete_key(&mut self, keyblob: &[u8]) -> Result<(), Error>995*9860b763SAndroid Build Coastguard Worker fn delete_key(&mut self, keyblob: &[u8]) -> Result<(), Error> {
996*9860b763SAndroid Build Coastguard Worker // Parse the keyblob. It cannot be decrypted, because hidden parameters are not available
997*9860b763SAndroid Build Coastguard Worker // (there is no `params` for them to arrive in).
998*9860b763SAndroid Build Coastguard Worker if let Ok(keyblob::EncryptedKeyBlob::V1(encrypted_keyblob)) =
999*9860b763SAndroid Build Coastguard Worker keyblob::EncryptedKeyBlob::new(keyblob)
1000*9860b763SAndroid Build Coastguard Worker {
1001*9860b763SAndroid Build Coastguard Worker // We have to trust that any secure deletion slot in the keyblob is valid, because the
1002*9860b763SAndroid Build Coastguard Worker // key can't be decrypted.
1003*9860b763SAndroid Build Coastguard Worker if let (Some(sdd_mgr), Some(slot)) =
1004*9860b763SAndroid Build Coastguard Worker (&mut self.dev.sdd_mgr, encrypted_keyblob.secure_deletion_slot)
1005*9860b763SAndroid Build Coastguard Worker {
1006*9860b763SAndroid Build Coastguard Worker if let Err(e) = sdd_mgr.delete_secret(slot) {
1007*9860b763SAndroid Build Coastguard Worker error!("failed to delete secure deletion slot: {:?}", e);
1008*9860b763SAndroid Build Coastguard Worker }
1009*9860b763SAndroid Build Coastguard Worker }
1010*9860b763SAndroid Build Coastguard Worker } else {
1011*9860b763SAndroid Build Coastguard Worker // We might have failed to parse the keyblob because it is in some prior format.
1012*9860b763SAndroid Build Coastguard Worker if let Some(old_key) = self.dev.legacy_key.as_mut() {
1013*9860b763SAndroid Build Coastguard Worker if let Err(e) = old_key.delete_legacy_key(keyblob) {
1014*9860b763SAndroid Build Coastguard Worker error!("failed to parse keyblob as legacy : {:?}, ignoring", e);
1015*9860b763SAndroid Build Coastguard Worker }
1016*9860b763SAndroid Build Coastguard Worker } else {
1017*9860b763SAndroid Build Coastguard Worker error!("failed to parse keyblob, ignoring");
1018*9860b763SAndroid Build Coastguard Worker }
1019*9860b763SAndroid Build Coastguard Worker }
1020*9860b763SAndroid Build Coastguard Worker
1021*9860b763SAndroid Build Coastguard Worker Ok(())
1022*9860b763SAndroid Build Coastguard Worker }
1023*9860b763SAndroid Build Coastguard Worker
delete_all_keys(&mut self) -> Result<(), Error>1024*9860b763SAndroid Build Coastguard Worker fn delete_all_keys(&mut self) -> Result<(), Error> {
1025*9860b763SAndroid Build Coastguard Worker if let Some(sdd_mgr) = &mut self.dev.sdd_mgr {
1026*9860b763SAndroid Build Coastguard Worker error!("secure deleting all keys -- device likely to need factory reset!");
1027*9860b763SAndroid Build Coastguard Worker sdd_mgr.delete_all();
1028*9860b763SAndroid Build Coastguard Worker }
1029*9860b763SAndroid Build Coastguard Worker Ok(())
1030*9860b763SAndroid Build Coastguard Worker }
1031*9860b763SAndroid Build Coastguard Worker
destroy_attestation_ids(&mut self) -> Result<(), Error>1032*9860b763SAndroid Build Coastguard Worker fn destroy_attestation_ids(&mut self) -> Result<(), Error> {
1033*9860b763SAndroid Build Coastguard Worker match self.dev.attest_ids.as_mut() {
1034*9860b763SAndroid Build Coastguard Worker Some(attest_ids) => {
1035*9860b763SAndroid Build Coastguard Worker // Drop any cached copies too.
1036*9860b763SAndroid Build Coastguard Worker *self.attestation_id_info.borrow_mut() = None;
1037*9860b763SAndroid Build Coastguard Worker error!("destroying all device attestation IDs!");
1038*9860b763SAndroid Build Coastguard Worker attest_ids.destroy_all()
1039*9860b763SAndroid Build Coastguard Worker }
1040*9860b763SAndroid Build Coastguard Worker None => {
1041*9860b763SAndroid Build Coastguard Worker error!("destroying device attestation IDs requested but not supported");
1042*9860b763SAndroid Build Coastguard Worker Err(km_err!(Unimplemented, "no attestation ID functionality available"))
1043*9860b763SAndroid Build Coastguard Worker }
1044*9860b763SAndroid Build Coastguard Worker }
1045*9860b763SAndroid Build Coastguard Worker }
1046*9860b763SAndroid Build Coastguard Worker
get_root_of_trust_challenge(&mut self) -> Result<[u8; 16], Error>1047*9860b763SAndroid Build Coastguard Worker fn get_root_of_trust_challenge(&mut self) -> Result<[u8; 16], Error> {
1048*9860b763SAndroid Build Coastguard Worker if !self.is_strongbox() {
1049*9860b763SAndroid Build Coastguard Worker return Err(km_err!(Unimplemented, "root-of-trust challenge only for StrongBox"));
1050*9860b763SAndroid Build Coastguard Worker }
1051*9860b763SAndroid Build Coastguard Worker self.imp.rng.fill_bytes(&mut self.rot_challenge[..]);
1052*9860b763SAndroid Build Coastguard Worker Ok(self.rot_challenge)
1053*9860b763SAndroid Build Coastguard Worker }
1054*9860b763SAndroid Build Coastguard Worker
get_root_of_trust(&mut self, challenge: &[u8]) -> Result<Vec<u8>, Error>1055*9860b763SAndroid Build Coastguard Worker fn get_root_of_trust(&mut self, challenge: &[u8]) -> Result<Vec<u8>, Error> {
1056*9860b763SAndroid Build Coastguard Worker if self.is_strongbox() {
1057*9860b763SAndroid Build Coastguard Worker return Err(km_err!(Unimplemented, "root-of-trust retrieval not for StrongBox"));
1058*9860b763SAndroid Build Coastguard Worker }
1059*9860b763SAndroid Build Coastguard Worker let payload = self
1060*9860b763SAndroid Build Coastguard Worker .boot_info_hashed_key()?
1061*9860b763SAndroid Build Coastguard Worker .to_tagged_vec()
1062*9860b763SAndroid Build Coastguard Worker .map_err(|_e| km_err!(EncodingError, "Failed to CBOR-encode RootOfTrust"))?;
1063*9860b763SAndroid Build Coastguard Worker
1064*9860b763SAndroid Build Coastguard Worker let mac0 = coset::CoseMac0Builder::new()
1065*9860b763SAndroid Build Coastguard Worker .protected(
1066*9860b763SAndroid Build Coastguard Worker coset::HeaderBuilder::new().algorithm(coset::iana::Algorithm::HMAC_256_256).build(),
1067*9860b763SAndroid Build Coastguard Worker )
1068*9860b763SAndroid Build Coastguard Worker .payload(payload)
1069*9860b763SAndroid Build Coastguard Worker .try_create_tag(challenge, |data| self.device_hmac(data))?
1070*9860b763SAndroid Build Coastguard Worker .build();
1071*9860b763SAndroid Build Coastguard Worker mac0.to_tagged_vec()
1072*9860b763SAndroid Build Coastguard Worker .map_err(|_e| km_err!(EncodingError, "Failed to CBOR-encode RootOfTrust"))
1073*9860b763SAndroid Build Coastguard Worker }
1074*9860b763SAndroid Build Coastguard Worker
send_root_of_trust(&mut self, root_of_trust: &[u8]) -> Result<(), Error>1075*9860b763SAndroid Build Coastguard Worker fn send_root_of_trust(&mut self, root_of_trust: &[u8]) -> Result<(), Error> {
1076*9860b763SAndroid Build Coastguard Worker if !self.is_strongbox() {
1077*9860b763SAndroid Build Coastguard Worker return Err(km_err!(Unimplemented, "root-of-trust delivery only for StrongBox"));
1078*9860b763SAndroid Build Coastguard Worker }
1079*9860b763SAndroid Build Coastguard Worker let mac0 = coset::CoseMac0::from_tagged_slice(root_of_trust)
1080*9860b763SAndroid Build Coastguard Worker .map_err(|_e| km_err!(InvalidArgument, "Failed to CBOR-decode CoseMac0"))?;
1081*9860b763SAndroid Build Coastguard Worker mac0.verify_tag(&self.rot_challenge, |tag, data| {
1082*9860b763SAndroid Build Coastguard Worker match self.verify_device_hmac(data, tag) {
1083*9860b763SAndroid Build Coastguard Worker Ok(true) => Ok(()),
1084*9860b763SAndroid Build Coastguard Worker Ok(false) => {
1085*9860b763SAndroid Build Coastguard Worker Err(km_err!(VerificationFailed, "HMAC verification of RootOfTrust failed"))
1086*9860b763SAndroid Build Coastguard Worker }
1087*9860b763SAndroid Build Coastguard Worker Err(e) => Err(e),
1088*9860b763SAndroid Build Coastguard Worker }
1089*9860b763SAndroid Build Coastguard Worker })?;
1090*9860b763SAndroid Build Coastguard Worker let payload =
1091*9860b763SAndroid Build Coastguard Worker mac0.payload.ok_or_else(|| km_err!(InvalidArgument, "Missing payload in CoseMac0"))?;
1092*9860b763SAndroid Build Coastguard Worker let boot_info = keymint::BootInfo::from_tagged_slice(&payload)
1093*9860b763SAndroid Build Coastguard Worker .map_err(|_e| km_err!(InvalidArgument, "Failed to CBOR-decode RootOfTrust"))?;
1094*9860b763SAndroid Build Coastguard Worker if self.boot_info.is_none() {
1095*9860b763SAndroid Build Coastguard Worker info!("Setting boot_info to TEE-provided {:?}", boot_info);
1096*9860b763SAndroid Build Coastguard Worker self.boot_info = Some(boot_info);
1097*9860b763SAndroid Build Coastguard Worker } else {
1098*9860b763SAndroid Build Coastguard Worker info!("Ignoring TEE-provided RootOfTrust {:?} as already set", boot_info);
1099*9860b763SAndroid Build Coastguard Worker }
1100*9860b763SAndroid Build Coastguard Worker Ok(())
1101*9860b763SAndroid Build Coastguard Worker }
1102*9860b763SAndroid Build Coastguard Worker
set_additional_attestation_info(&mut self, info: Vec<KeyParam>) -> Result<(), Error>1103*9860b763SAndroid Build Coastguard Worker fn set_additional_attestation_info(&mut self, info: Vec<KeyParam>) -> Result<(), Error> {
1104*9860b763SAndroid Build Coastguard Worker for param in info {
1105*9860b763SAndroid Build Coastguard Worker let tag = param.tag();
1106*9860b763SAndroid Build Coastguard Worker if !ALLOWED_ADDITIONAL_ATTESTATION_TAGS.contains(&tag) {
1107*9860b763SAndroid Build Coastguard Worker warn!("ignoring non-allowlisted tag: {tag:?}");
1108*9860b763SAndroid Build Coastguard Worker continue;
1109*9860b763SAndroid Build Coastguard Worker }
1110*9860b763SAndroid Build Coastguard Worker match self.additional_attestation_info.iter().find(|&x| x.tag() == tag) {
1111*9860b763SAndroid Build Coastguard Worker Some(value) if value == ¶m => {
1112*9860b763SAndroid Build Coastguard Worker warn!(
1113*9860b763SAndroid Build Coastguard Worker concat!(
1114*9860b763SAndroid Build Coastguard Worker "additional attestation info for: {:?} already set, ignoring repeated",
1115*9860b763SAndroid Build Coastguard Worker " attempt to set same info"
1116*9860b763SAndroid Build Coastguard Worker ),
1117*9860b763SAndroid Build Coastguard Worker param
1118*9860b763SAndroid Build Coastguard Worker );
1119*9860b763SAndroid Build Coastguard Worker continue;
1120*9860b763SAndroid Build Coastguard Worker }
1121*9860b763SAndroid Build Coastguard Worker Some(value) => {
1122*9860b763SAndroid Build Coastguard Worker return Err(set_additional_attestation_info_err(
1123*9860b763SAndroid Build Coastguard Worker tag,
1124*9860b763SAndroid Build Coastguard Worker format!(
1125*9860b763SAndroid Build Coastguard Worker concat!(
1126*9860b763SAndroid Build Coastguard Worker "attempt to set additional attestation info for: {:?}, but that tag",
1127*9860b763SAndroid Build Coastguard Worker " already has a different value set: {:?}"
1128*9860b763SAndroid Build Coastguard Worker ),
1129*9860b763SAndroid Build Coastguard Worker param, value
1130*9860b763SAndroid Build Coastguard Worker ),
1131*9860b763SAndroid Build Coastguard Worker ));
1132*9860b763SAndroid Build Coastguard Worker }
1133*9860b763SAndroid Build Coastguard Worker None => {
1134*9860b763SAndroid Build Coastguard Worker self.additional_attestation_info.push(param.clone());
1135*9860b763SAndroid Build Coastguard Worker }
1136*9860b763SAndroid Build Coastguard Worker }
1137*9860b763SAndroid Build Coastguard Worker }
1138*9860b763SAndroid Build Coastguard Worker Ok(())
1139*9860b763SAndroid Build Coastguard Worker }
1140*9860b763SAndroid Build Coastguard Worker
convert_storage_key_to_ephemeral(&self, keyblob: &[u8]) -> Result<Vec<u8>, Error>1141*9860b763SAndroid Build Coastguard Worker fn convert_storage_key_to_ephemeral(&self, keyblob: &[u8]) -> Result<Vec<u8>, Error> {
1142*9860b763SAndroid Build Coastguard Worker if let Some(sk_wrapper) = &self.dev.sk_wrapper {
1143*9860b763SAndroid Build Coastguard Worker // Parse and decrypt the keyblob. Note that there is no way to provide extra hidden
1144*9860b763SAndroid Build Coastguard Worker // params on the API.
1145*9860b763SAndroid Build Coastguard Worker let (keyblob, _) = self.keyblob_parse_decrypt(keyblob, &[])?;
1146*9860b763SAndroid Build Coastguard Worker
1147*9860b763SAndroid Build Coastguard Worker // Check that the keyblob is indeed a storage key.
1148*9860b763SAndroid Build Coastguard Worker let chars = keyblob.characteristics_at(self.hw_info.security_level)?;
1149*9860b763SAndroid Build Coastguard Worker if !get_bool_tag_value!(chars, StorageKey)? {
1150*9860b763SAndroid Build Coastguard Worker return Err(km_err!(InvalidArgument, "attempting to convert non-storage key"));
1151*9860b763SAndroid Build Coastguard Worker }
1152*9860b763SAndroid Build Coastguard Worker
1153*9860b763SAndroid Build Coastguard Worker // Now that we've got the key material, use a device-specific method to re-wrap it
1154*9860b763SAndroid Build Coastguard Worker // with an ephemeral key.
1155*9860b763SAndroid Build Coastguard Worker sk_wrapper.ephemeral_wrap(&keyblob.key_material)
1156*9860b763SAndroid Build Coastguard Worker } else {
1157*9860b763SAndroid Build Coastguard Worker Err(km_err!(Unimplemented, "storage key wrapping unavailable"))
1158*9860b763SAndroid Build Coastguard Worker }
1159*9860b763SAndroid Build Coastguard Worker }
1160*9860b763SAndroid Build Coastguard Worker
get_key_characteristics( &self, key_blob: &[u8], app_id: Vec<u8>, app_data: Vec<u8>, ) -> Result<Vec<KeyCharacteristics>, Error>1161*9860b763SAndroid Build Coastguard Worker fn get_key_characteristics(
1162*9860b763SAndroid Build Coastguard Worker &self,
1163*9860b763SAndroid Build Coastguard Worker key_blob: &[u8],
1164*9860b763SAndroid Build Coastguard Worker app_id: Vec<u8>,
1165*9860b763SAndroid Build Coastguard Worker app_data: Vec<u8>,
1166*9860b763SAndroid Build Coastguard Worker ) -> Result<Vec<KeyCharacteristics>, Error> {
1167*9860b763SAndroid Build Coastguard Worker // Parse and decrypt the keyblob, which requires extra hidden params.
1168*9860b763SAndroid Build Coastguard Worker let mut params = vec_try_with_capacity!(2)?;
1169*9860b763SAndroid Build Coastguard Worker if !app_id.is_empty() {
1170*9860b763SAndroid Build Coastguard Worker params.push(KeyParam::ApplicationId(app_id)); // capacity enough
1171*9860b763SAndroid Build Coastguard Worker }
1172*9860b763SAndroid Build Coastguard Worker if !app_data.is_empty() {
1173*9860b763SAndroid Build Coastguard Worker params.push(KeyParam::ApplicationData(app_data)); // capacity enough
1174*9860b763SAndroid Build Coastguard Worker }
1175*9860b763SAndroid Build Coastguard Worker let (keyblob, _) = self.keyblob_parse_decrypt(key_blob, ¶ms)?;
1176*9860b763SAndroid Build Coastguard Worker Ok(keyblob.characteristics)
1177*9860b763SAndroid Build Coastguard Worker }
1178*9860b763SAndroid Build Coastguard Worker
1179*9860b763SAndroid Build Coastguard Worker /// Generate an HMAC-SHA256 value over the data using the device's HMAC key (if available).
device_hmac(&self, data: &[u8]) -> Result<Vec<u8>, Error>1180*9860b763SAndroid Build Coastguard Worker fn device_hmac(&self, data: &[u8]) -> Result<Vec<u8>, Error> {
1181*9860b763SAndroid Build Coastguard Worker match &self.device_hmac {
1182*9860b763SAndroid Build Coastguard Worker Some(traitobj) => traitobj.hmac(&*self.imp.hmac, data),
1183*9860b763SAndroid Build Coastguard Worker None => {
1184*9860b763SAndroid Build Coastguard Worker error!("HMAC requested but no key available!");
1185*9860b763SAndroid Build Coastguard Worker Err(km_err!(HardwareNotYetAvailable, "HMAC key not agreed"))
1186*9860b763SAndroid Build Coastguard Worker }
1187*9860b763SAndroid Build Coastguard Worker }
1188*9860b763SAndroid Build Coastguard Worker }
1189*9860b763SAndroid Build Coastguard Worker
1190*9860b763SAndroid Build Coastguard Worker /// Verify an HMAC-SHA256 value over the data using the device's HMAC key (if available).
verify_device_hmac(&self, data: &[u8], mac: &[u8]) -> Result<bool, Error>1191*9860b763SAndroid Build Coastguard Worker fn verify_device_hmac(&self, data: &[u8], mac: &[u8]) -> Result<bool, Error> {
1192*9860b763SAndroid Build Coastguard Worker let remac = self.device_hmac(data)?;
1193*9860b763SAndroid Build Coastguard Worker Ok(self.imp.compare.eq(mac, &remac))
1194*9860b763SAndroid Build Coastguard Worker }
1195*9860b763SAndroid Build Coastguard Worker
1196*9860b763SAndroid Build Coastguard Worker /// Return the root of trust that is bound into keyblobs.
root_of_trust(&self) -> Result<&[u8], Error>1197*9860b763SAndroid Build Coastguard Worker fn root_of_trust(&self) -> Result<&[u8], Error> {
1198*9860b763SAndroid Build Coastguard Worker match &self.rot_data {
1199*9860b763SAndroid Build Coastguard Worker Some(data) => Ok(data),
1200*9860b763SAndroid Build Coastguard Worker None => Err(km_err!(HardwareNotYetAvailable, "No root-of-trust info available")),
1201*9860b763SAndroid Build Coastguard Worker }
1202*9860b763SAndroid Build Coastguard Worker }
1203*9860b763SAndroid Build Coastguard Worker
1204*9860b763SAndroid Build Coastguard Worker /// Return the root key used for key encryption.
root_kek(&self, context: &[u8]) -> Result<OpaqueOr<hmac::Key>, Error>1205*9860b763SAndroid Build Coastguard Worker fn root_kek(&self, context: &[u8]) -> Result<OpaqueOr<hmac::Key>, Error> {
1206*9860b763SAndroid Build Coastguard Worker self.dev.keys.root_kek(context)
1207*9860b763SAndroid Build Coastguard Worker }
1208*9860b763SAndroid Build Coastguard Worker
1209*9860b763SAndroid Build Coastguard Worker /// Add KeyMint-generated tags to the provided [`KeyCharacteristics`].
add_keymint_tags( &self, chars: &mut Vec<KeyCharacteristics>, origin: KeyOrigin, ) -> Result<(), Error>1210*9860b763SAndroid Build Coastguard Worker fn add_keymint_tags(
1211*9860b763SAndroid Build Coastguard Worker &self,
1212*9860b763SAndroid Build Coastguard Worker chars: &mut Vec<KeyCharacteristics>,
1213*9860b763SAndroid Build Coastguard Worker origin: KeyOrigin,
1214*9860b763SAndroid Build Coastguard Worker ) -> Result<(), Error> {
1215*9860b763SAndroid Build Coastguard Worker for kc in chars {
1216*9860b763SAndroid Build Coastguard Worker if kc.security_level == self.hw_info.security_level {
1217*9860b763SAndroid Build Coastguard Worker kc.authorizations.try_push(KeyParam::Origin(origin))?;
1218*9860b763SAndroid Build Coastguard Worker if let Some(hal_info) = &self.hal_info {
1219*9860b763SAndroid Build Coastguard Worker kc.authorizations.try_extend_from_slice(&[
1220*9860b763SAndroid Build Coastguard Worker KeyParam::OsVersion(hal_info.os_version),
1221*9860b763SAndroid Build Coastguard Worker KeyParam::OsPatchlevel(hal_info.os_patchlevel),
1222*9860b763SAndroid Build Coastguard Worker KeyParam::VendorPatchlevel(hal_info.vendor_patchlevel),
1223*9860b763SAndroid Build Coastguard Worker ])?;
1224*9860b763SAndroid Build Coastguard Worker }
1225*9860b763SAndroid Build Coastguard Worker if let Some(boot_info) = &self.boot_info {
1226*9860b763SAndroid Build Coastguard Worker kc.authorizations
1227*9860b763SAndroid Build Coastguard Worker .try_push(KeyParam::BootPatchlevel(boot_info.boot_patchlevel))?;
1228*9860b763SAndroid Build Coastguard Worker }
1229*9860b763SAndroid Build Coastguard Worker return Ok(());
1230*9860b763SAndroid Build Coastguard Worker }
1231*9860b763SAndroid Build Coastguard Worker }
1232*9860b763SAndroid Build Coastguard Worker Err(km_err!(
1233*9860b763SAndroid Build Coastguard Worker InvalidArgument,
1234*9860b763SAndroid Build Coastguard Worker "no characteristics at our security level {:?}",
1235*9860b763SAndroid Build Coastguard Worker self.hw_info.security_level
1236*9860b763SAndroid Build Coastguard Worker ))
1237*9860b763SAndroid Build Coastguard Worker }
1238*9860b763SAndroid Build Coastguard Worker }
1239*9860b763SAndroid Build Coastguard Worker
1240*9860b763SAndroid Build Coastguard Worker /// Create an OK response structure with the given inner response message.
op_ok_rsp(rsp: PerformOpRsp) -> PerformOpResponse1241*9860b763SAndroid Build Coastguard Worker fn op_ok_rsp(rsp: PerformOpRsp) -> PerformOpResponse {
1242*9860b763SAndroid Build Coastguard Worker // Zero is OK in any context.
1243*9860b763SAndroid Build Coastguard Worker PerformOpResponse { error_code: 0, rsp: Some(rsp) }
1244*9860b763SAndroid Build Coastguard Worker }
1245*9860b763SAndroid Build Coastguard Worker
1246*9860b763SAndroid Build Coastguard Worker /// Create a response structure with the given error code.
error_rsp(error_code: i32) -> PerformOpResponse1247*9860b763SAndroid Build Coastguard Worker fn error_rsp(error_code: i32) -> PerformOpResponse {
1248*9860b763SAndroid Build Coastguard Worker PerformOpResponse { error_code, rsp: None }
1249*9860b763SAndroid Build Coastguard Worker }
1250*9860b763SAndroid Build Coastguard Worker
1251*9860b763SAndroid Build Coastguard Worker /// Create a response structure with the given error.
op_error_rsp(op: KeyMintOperation, err: Error) -> PerformOpResponse1252*9860b763SAndroid Build Coastguard Worker fn op_error_rsp(op: KeyMintOperation, err: Error) -> PerformOpResponse {
1253*9860b763SAndroid Build Coastguard Worker warn!("failing {:?} request with error {:?}", op, err);
1254*9860b763SAndroid Build Coastguard Worker if kmr_wire::is_rpc_operation(op) {
1255*9860b763SAndroid Build Coastguard Worker // The IRemotelyProvisionedComponent HAL uses a different error space than the
1256*9860b763SAndroid Build Coastguard Worker // other HALs.
1257*9860b763SAndroid Build Coastguard Worker let rpc_err: rpc::ErrorCode = match err {
1258*9860b763SAndroid Build Coastguard Worker Error::Cbor(_) | Error::Der(_) | Error::Alloc(_) => rpc::ErrorCode::Failed,
1259*9860b763SAndroid Build Coastguard Worker Error::Hal(_, _) => {
1260*9860b763SAndroid Build Coastguard Worker error!("encountered non-RKP error on RKP method! {:?}", err);
1261*9860b763SAndroid Build Coastguard Worker rpc::ErrorCode::Failed
1262*9860b763SAndroid Build Coastguard Worker }
1263*9860b763SAndroid Build Coastguard Worker Error::Rpc(e, _) => e,
1264*9860b763SAndroid Build Coastguard Worker };
1265*9860b763SAndroid Build Coastguard Worker error_rsp(rpc_err as i32)
1266*9860b763SAndroid Build Coastguard Worker } else {
1267*9860b763SAndroid Build Coastguard Worker let hal_err = match err {
1268*9860b763SAndroid Build Coastguard Worker Error::Cbor(_) | Error::Der(_) => ErrorCode::InvalidArgument,
1269*9860b763SAndroid Build Coastguard Worker Error::Hal(e, _) => e,
1270*9860b763SAndroid Build Coastguard Worker Error::Rpc(_, _) => {
1271*9860b763SAndroid Build Coastguard Worker error!("encountered RKP error on non-RKP method! {:?}", err);
1272*9860b763SAndroid Build Coastguard Worker ErrorCode::InvalidArgument
1273*9860b763SAndroid Build Coastguard Worker }
1274*9860b763SAndroid Build Coastguard Worker Error::Alloc(_) => ErrorCode::MemoryAllocationFailed,
1275*9860b763SAndroid Build Coastguard Worker };
1276*9860b763SAndroid Build Coastguard Worker error_rsp(hal_err as i32)
1277*9860b763SAndroid Build Coastguard Worker }
1278*9860b763SAndroid Build Coastguard Worker }
1279*9860b763SAndroid Build Coastguard Worker
1280*9860b763SAndroid Build Coastguard Worker /// Create an Error for [`KeyMintTa::set_additional_attestation_info`] failure that corresponds to
1281*9860b763SAndroid Build Coastguard Worker /// the specified tag.
set_additional_attestation_info_err(tag: Tag, err_msg: String) -> Error1282*9860b763SAndroid Build Coastguard Worker fn set_additional_attestation_info_err(tag: Tag, err_msg: String) -> Error {
1283*9860b763SAndroid Build Coastguard Worker match tag {
1284*9860b763SAndroid Build Coastguard Worker Tag::ModuleHash => km_err!(ModuleHashAlreadySet, "{}", err_msg),
1285*9860b763SAndroid Build Coastguard Worker _ => km_err!(InvalidTag, "unexpected tag: {tag:?}"),
1286*9860b763SAndroid Build Coastguard Worker }
1287*9860b763SAndroid Build Coastguard Worker }
1288*9860b763SAndroid Build Coastguard Worker
1289*9860b763SAndroid Build Coastguard Worker /// Hand-encoded [`PerformOpResponse`] data for [`ErrorCode::UNKNOWN_ERROR`].
1290*9860b763SAndroid Build Coastguard Worker /// Does not perform CBOR serialization (and so is suitable for error reporting if/when
1291*9860b763SAndroid Build Coastguard Worker /// CBOR serialization fails).
invalid_cbor_rsp_data() -> [u8; 5]1292*9860b763SAndroid Build Coastguard Worker fn invalid_cbor_rsp_data() -> [u8; 5] {
1293*9860b763SAndroid Build Coastguard Worker [
1294*9860b763SAndroid Build Coastguard Worker 0x82, // 2-arr
1295*9860b763SAndroid Build Coastguard Worker 0x39, // nint, len 2
1296*9860b763SAndroid Build Coastguard Worker 0x03, // 0x3e7(999)
1297*9860b763SAndroid Build Coastguard Worker 0xe7, // = -1000
1298*9860b763SAndroid Build Coastguard Worker 0x80, // 0-arr
1299*9860b763SAndroid Build Coastguard Worker ]
1300*9860b763SAndroid Build Coastguard Worker }
1301*9860b763SAndroid Build Coastguard Worker
1302*9860b763SAndroid Build Coastguard Worker /// Build the HMAC input for a [`HardwareAuthToken`]
hardware_auth_token_mac_input(token: &HardwareAuthToken) -> Result<Vec<u8>, Error>1303*9860b763SAndroid Build Coastguard Worker pub fn hardware_auth_token_mac_input(token: &HardwareAuthToken) -> Result<Vec<u8>, Error> {
1304*9860b763SAndroid Build Coastguard Worker let mut result = vec_try_with_capacity!(
1305*9860b763SAndroid Build Coastguard Worker size_of::<u8>() + // version=0 (BE)
1306*9860b763SAndroid Build Coastguard Worker size_of::<i64>() + // challenge (Host)
1307*9860b763SAndroid Build Coastguard Worker size_of::<i64>() + // user_id (Host)
1308*9860b763SAndroid Build Coastguard Worker size_of::<i64>() + // authenticator_id (Host)
1309*9860b763SAndroid Build Coastguard Worker size_of::<i32>() + // authenticator_type (BE)
1310*9860b763SAndroid Build Coastguard Worker size_of::<i64>() // timestamp (BE)
1311*9860b763SAndroid Build Coastguard Worker )?;
1312*9860b763SAndroid Build Coastguard Worker result.extend_from_slice(&0u8.to_be_bytes()[..]);
1313*9860b763SAndroid Build Coastguard Worker result.extend_from_slice(&token.challenge.to_ne_bytes()[..]);
1314*9860b763SAndroid Build Coastguard Worker result.extend_from_slice(&token.user_id.to_ne_bytes()[..]);
1315*9860b763SAndroid Build Coastguard Worker result.extend_from_slice(&token.authenticator_id.to_ne_bytes()[..]);
1316*9860b763SAndroid Build Coastguard Worker result.extend_from_slice(&(token.authenticator_type as i32).to_be_bytes()[..]);
1317*9860b763SAndroid Build Coastguard Worker result.extend_from_slice(&token.timestamp.milliseconds.to_be_bytes()[..]);
1318*9860b763SAndroid Build Coastguard Worker Ok(result)
1319*9860b763SAndroid Build Coastguard Worker }
1320