1 // Copyright 2022, The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 //! Traits representing access to device-specific information and functionality.
16 
17 use crate::coset::{iana, AsCborValue, CoseSign1Builder, HeaderBuilder};
18 use alloc::{boxed::Box, vec::Vec};
19 use kmr_common::{
20     crypto, crypto::aes, crypto::hmac, crypto::KeyMaterial, crypto::OpaqueOr, keyblob, log_unimpl,
21     unimpl, Error,
22 };
23 use kmr_wire::{keymint, rpc, secureclock::TimeStampToken, CborError};
24 use log::error;
25 
26 use crate::rkp::serialize_cbor;
27 
28 /// Context used to derive the hardware backed key for computing HMAC in
29 /// IRemotelyProvisionedComponent.
30 pub const RPC_HMAC_KEY_CONTEXT: &[u8] = b"Key to MAC public keys";
31 
32 /// Length (in bytes) of the HMAC key used in IRemotelyProvisionedComponent.
33 pub const RPC_HMAC_KEY_LEN: usize = 32;
34 
35 /// Combined collection of trait implementations that must be provided.
36 pub struct Implementation {
37     /// Retrieval of root key material.
38     pub keys: Box<dyn RetrieveKeyMaterial>,
39 
40     /// Retrieval of attestation certificate signing information.
41     pub sign_info: Option<Box<dyn RetrieveCertSigningInfo>>,
42 
43     /// Retrieval of attestation ID information.
44     pub attest_ids: Option<Box<dyn RetrieveAttestationIds>>,
45 
46     /// Secure deletion secret manager.  If not available, rollback-resistant
47     /// keys will not be supported.
48     pub sdd_mgr: Option<Box<dyn keyblob::SecureDeletionSecretManager>>,
49 
50     /// Retrieval of bootloader status.
51     pub bootloader: Box<dyn BootloaderStatus>,
52 
53     /// Storage key wrapping. If not available `convertStorageKeyToEphemeral()` will not be
54     /// supported
55     pub sk_wrapper: Option<Box<dyn StorageKeyWrapper>>,
56 
57     /// Trusted user presence indicator.
58     pub tup: Box<dyn TrustedUserPresence>,
59 
60     /// Legacy key conversion handling.
61     pub legacy_key: Option<Box<dyn keyblob::LegacyKeyHandler>>,
62 
63     /// Retrieval of artifacts related to the device implementation of IRemotelyProvisionedComponent
64     /// (IRPC) HAL.
65     pub rpc: Box<dyn RetrieveRpcArtifacts>,
66 }
67 
68 /// Functionality related to retrieval of device-specific key material, and its subsequent use.
69 /// The caller is generally expected to drop the key material as soon as it is done with it.
70 pub trait RetrieveKeyMaterial {
71     /// Retrieve the root key used for derivation of a per-keyblob key encryption key (KEK), passing
72     /// in any opaque context.
root_kek(&self, context: &[u8]) -> Result<OpaqueOr<hmac::Key>, Error>73     fn root_kek(&self, context: &[u8]) -> Result<OpaqueOr<hmac::Key>, Error>;
74 
75     /// Retrieve any opaque (but non-confidential) context needed for future calls to [`root_kek`].
76     /// Context should not include confidential data (it will be stored in the clear).
kek_context(&self) -> Result<Vec<u8>, Error>77     fn kek_context(&self) -> Result<Vec<u8>, Error> {
78         // Default implementation is to have an empty KEK retrieval context.
79         Ok(Vec::new())
80     }
81 
82     /// Retrieve the key agreement key used for shared secret negotiation.
kak(&self) -> Result<OpaqueOr<aes::Key>, Error>83     fn kak(&self) -> Result<OpaqueOr<aes::Key>, Error>;
84 
85     /// Install the device HMAC agreed by shared secret negotiation into hardware (optional).
hmac_key_agreed(&self, _key: &crypto::hmac::Key) -> Option<Box<dyn DeviceHmac>>86     fn hmac_key_agreed(&self, _key: &crypto::hmac::Key) -> Option<Box<dyn DeviceHmac>> {
87         // By default, use a software implementation that holds the key in memory.
88         None
89     }
90 
91     /// Retrieve the hardware backed secret used for UNIQUE_ID generation.
unique_id_hbk(&self, ckdf: &dyn crypto::Ckdf) -> Result<crypto::hmac::Key, Error>92     fn unique_id_hbk(&self, ckdf: &dyn crypto::Ckdf) -> Result<crypto::hmac::Key, Error> {
93         // By default, use CKDF on the key agreement secret to derive a key.
94         let unique_id_label = b"UniqueID HBK 32B";
95         ckdf.ckdf(&self.kak()?, unique_id_label, &[], 32).map(crypto::hmac::Key::new)
96     }
97 
98     /// Build the HMAC input for a [`TimeStampToken`].  The default implementation produces
99     /// data that matches the `ISecureClock` AIDL specification; this method should only be
100     /// overridden for back-compatibility reasons.
timestamp_token_mac_input(&self, token: &TimeStampToken) -> Result<Vec<u8>, Error>101     fn timestamp_token_mac_input(&self, token: &TimeStampToken) -> Result<Vec<u8>, Error> {
102         crate::clock::timestamp_token_mac_input(token)
103     }
104 }
105 
106 /// Device HMAC calculation.
107 pub trait DeviceHmac {
108     /// Calculate the HMAC over the data using the agreed device HMAC key.
hmac(&self, imp: &dyn crypto::Hmac, data: &[u8]) -> Result<Vec<u8>, Error>109     fn hmac(&self, imp: &dyn crypto::Hmac, data: &[u8]) -> Result<Vec<u8>, Error>;
110 
111     /// Returns the key used for HMAC'ing data if available
get_hmac_key(&self) -> Option<crypto::hmac::Key>112     fn get_hmac_key(&self) -> Option<crypto::hmac::Key> {
113         // By default we assume that the implementation cannot return a key
114         None
115     }
116 }
117 
118 /// Identification of which attestation signing key is required.
119 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
120 pub enum SigningKey {
121     /// Use a batch key that is shared across multiple devices (to prevent the keys being used as
122     /// device identifiers).
123     Batch,
124     /// Use a device-unique key for signing. Only supported for StrongBox.
125     DeviceUnique,
126 }
127 
128 /// Indication of preferred attestation signing algorithm.
129 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
130 pub enum SigningAlgorithm {
131     /// Prefer to sign with an elliptic curve key.
132     Ec,
133     /// Prefer to sign with an RSA key.
134     Rsa,
135 }
136 
137 /// Indication of required signing key.
138 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
139 pub struct SigningKeyType {
140     /// Indicates the preferred type of signing key.
141     pub which: SigningKey,
142     /// Indicates what is going to be signed, to allow implementations to (optionally) use EC / RSA
143     /// signing keys for EC / RSA keys respectively.
144     pub algo_hint: SigningAlgorithm,
145 }
146 
147 /// Retrieval of attestation certificate signing information.  The caller is expected to drop key
148 /// material after use, but may cache public key material.
149 pub trait RetrieveCertSigningInfo {
150     /// Return the signing key material for the specified `key_type`.  The `algo_hint` parameter
151     /// indicates what is going to be signed, to allow implementations to (optionally) use EC / RSA
152     /// signing keys for EC /RSA keys respectively.
signing_key(&self, key_type: SigningKeyType) -> Result<KeyMaterial, Error>153     fn signing_key(&self, key_type: SigningKeyType) -> Result<KeyMaterial, Error>;
154 
155     /// Return the certificate chain associated with the specified signing key, where:
156     /// - `chain[0]` holds the public key that corresponds to `signing_key`, and which is signed
157     ///   by...
158     /// - the keypair described by the second entry `chain[1]`, which in turn is signed by...
159     /// - ...
160     /// - the final certificate in the chain should be a self-signed cert holding a Google root.
cert_chain(&self, key_type: SigningKeyType) -> Result<Vec<keymint::Certificate>, Error>161     fn cert_chain(&self, key_type: SigningKeyType) -> Result<Vec<keymint::Certificate>, Error>;
162 }
163 
164 /// Retrieval of attestation ID information.  This information will not change (so the caller can
165 /// cache this information after first invocation).
166 pub trait RetrieveAttestationIds {
167     /// Return the attestation IDs associated with the device, if available.
get(&self) -> Result<crate::AttestationIdInfo, Error>168     fn get(&self) -> Result<crate::AttestationIdInfo, Error>;
169 
170     /// Destroy all attestation IDs associated with the device.
destroy_all(&mut self) -> Result<(), Error>171     fn destroy_all(&mut self) -> Result<(), Error>;
172 }
173 
174 /// Bootloader status.
175 pub trait BootloaderStatus {
176     /// Indication of whether bootloader processing is complete
done(&self) -> bool177     fn done(&self) -> bool {
178         // By default assume that the bootloader is done before KeyMint starts.
179         true
180     }
181 }
182 
183 /// The trait that represents the device specific integration points required for the
184 /// implementation of IRemotelyProvisionedComponent (IRPC) HAL.
185 /// Note: The devices only supporting IRPC V3+ may ignore the optional IRPC V2 specific types in
186 /// the method signatures.
187 pub trait RetrieveRpcArtifacts {
188     /// Retrieve secret bytes (of the given output length) derived from a hardware backed key.
189     /// For a given context, the output is deterministic.
derive_bytes_from_hbk( &self, hkdf: &dyn crypto::Hkdf, context: &[u8], output_len: usize, ) -> Result<Vec<u8>, Error>190     fn derive_bytes_from_hbk(
191         &self,
192         hkdf: &dyn crypto::Hkdf,
193         context: &[u8],
194         output_len: usize,
195     ) -> Result<Vec<u8>, Error>;
196 
197     /// Compute HMAC_SHA256 over the given input using a key derived from hardware.
compute_hmac_sha256( &self, hmac: &dyn crypto::Hmac, hkdf: &dyn crypto::Hkdf, input: &[u8], ) -> Result<Vec<u8>, Error>198     fn compute_hmac_sha256(
199         &self,
200         hmac: &dyn crypto::Hmac,
201         hkdf: &dyn crypto::Hkdf,
202         input: &[u8],
203     ) -> Result<Vec<u8>, Error> {
204         let secret = self.derive_bytes_from_hbk(hkdf, RPC_HMAC_KEY_CONTEXT, RPC_HMAC_KEY_LEN)?;
205         crypto::hmac_sha256(hmac, &secret, input)
206     }
207 
208     /// Retrieve the information about the DICE chain belonging to the IRPC HAL implementation.
get_dice_info(&self, test_mode: rpc::TestMode) -> Result<DiceInfo, Error>209     fn get_dice_info(&self, test_mode: rpc::TestMode) -> Result<DiceInfo, Error>;
210 
211     /// Sign the input data with the CDI leaf private key of the IRPC HAL implementation. In IRPC V2,
212     /// the `data` to be signed is the [`SignedMac_structure`] in ProtectedData.aidl, when signing
213     /// the ephemeral MAC key used to authenticate the public keys. In IRPC V3, the `data` to be
214     /// signed is the [`SignedDataSigStruct`].
215     /// If a particular implementation would like to return the signature in a COSE_Sign1 message,
216     /// they can mark this unimplemented and override the default implementation in the
217     /// `sign_data_in_cose_sign1` method below.
218     ///
219     /// The signature produced by this method should be in a format suitable for COSE structures:
220     /// - Ed25519 signatures are encoded as-is.
221     /// - NIST signatures are encoded as (r||s), with each value left-padded with zeroes to
222     ///   the coordinate length.  Note that this is a *different* format than is emitted by
223     ///   the `kmr_common::crypto::Ec` trait.
224     /// (The `kmr_common::crypto::ec::to_cose_signature()` function can help with this.)
sign_data( &self, ec: &dyn crypto::Ec, data: &[u8], rpc_v2: Option<RpcV2Req>, ) -> Result<Vec<u8>, Error>225     fn sign_data(
226         &self,
227         ec: &dyn crypto::Ec,
228         data: &[u8],
229         rpc_v2: Option<RpcV2Req>,
230     ) -> Result<Vec<u8>, Error>;
231 
232     /// Sign the payload and return a COSE_Sign1 message. In IRPC V2, the `payload` is the MAC Key.
233     /// In IRPC V3, the `payload` is the `Data` that the `SignedData` is parameterized with (i.e. a
234     /// CBOR array containing `challenge` and `CsrPayload`).
sign_data_in_cose_sign1( &self, ec: &dyn crypto::Ec, signing_algorithm: &CsrSigningAlgorithm, payload: &[u8], _aad: &[u8], _rpc_v2: Option<RpcV2Req>, ) -> Result<Vec<u8>, Error>235     fn sign_data_in_cose_sign1(
236         &self,
237         ec: &dyn crypto::Ec,
238         signing_algorithm: &CsrSigningAlgorithm,
239         payload: &[u8],
240         _aad: &[u8],
241         _rpc_v2: Option<RpcV2Req>,
242     ) -> Result<Vec<u8>, Error> {
243         let cose_sign_algorithm = match signing_algorithm {
244             CsrSigningAlgorithm::ES256 => iana::Algorithm::ES256,
245             CsrSigningAlgorithm::ES384 => iana::Algorithm::ES384,
246             CsrSigningAlgorithm::EdDSA => iana::Algorithm::EdDSA,
247         };
248         // Construct `SignedData`
249         let protected = HeaderBuilder::new().algorithm(cose_sign_algorithm).build();
250         let signed_data = CoseSign1Builder::new()
251             .protected(protected)
252             .payload(payload.to_vec())
253             .try_create_signature(&[], |input| self.sign_data(ec, input, None))?
254             .build();
255         let signed_data_cbor = signed_data.to_cbor_value().map_err(CborError::from)?;
256         serialize_cbor(&signed_data_cbor)
257     }
258 }
259 
260 /// Information about the DICE chain belonging to the implementation of the IRPC HAL.
261 #[derive(Clone)]
262 pub struct DiceInfo {
263     /// Public dice artifacts.
264     pub pub_dice_artifacts: PubDiceArtifacts,
265     /// Algorithm used for signing CSRs.
266     pub signing_algorithm: CsrSigningAlgorithm,
267     /// Test-mode CDI private key.
268     ///
269     /// This is only relevant for IRPC HAL V2 when `test_mode` is true. This is ignored in all other
270     /// cases. The optional test CDI private key may be set here, if the device implementers
271     /// do not want to cache the test CDI private key across the calls to the `get_dice_info` and
272     ///`sign_data` methods when creating the CSR.
273     pub rpc_v2_test_cdi_priv: Option<RpcV2TestCDIPriv>,
274 }
275 
276 /// Algorithm used to sign with the CDI leaf private key.
277 #[derive(Clone, Copy, Debug)]
278 pub enum CsrSigningAlgorithm {
279     /// Sign with P-256 EC key.
280     ES256,
281     /// Sign with P-384 EC key.
282     ES384,
283     /// Sign with Ed25519 key.
284     EdDSA,
285 }
286 
287 /// Public DICE artifacts.
288 #[derive(Clone, Debug)]
289 pub struct PubDiceArtifacts {
290     /// Certificates for the UDS Pub encoded in CBOR as per [`AdditionalDKSignatures`] structure in
291     /// ProtectedData.aidl for IRPC HAL version 2 and as per [`UdsCerts`] structure in IRPC HAL
292     /// version 3.
293     pub uds_certs: Vec<u8>,
294     /// UDS Pub and the DICE certificates encoded in CBOR/COSE as per the [`Bcc`] structure
295     /// defined in ProtectedData.aidl for IRPC HAL version 2 and as per [`DiceCertChain`] structure
296     /// in IRPC HAL version 3.
297     pub dice_cert_chain: Vec<u8>,
298 }
299 
300 /// Enum distinguishing the two modes of operation for IRPC HAL V2, allowing an optional context
301 /// information to be passed in for the test mode.
302 pub enum RpcV2Req<'a> {
303     /// IRPC v2 request in production mode.
304     Production,
305     /// An opaque blob may be passed in for the test mode, if it was returned by the TA in
306     /// `RkpV2TestCDIPriv.context` in order to link the two requests: `get_dice_info` and `sign_data`
307     /// related to the same CSR.
308     Test(&'a [u8]),
309 }
310 
311 /// Struct encapsulating the optional CDI private key and the optional opaque context that may be
312 /// returned with `DiceInfo` in IRPC V2 test mode.
313 #[derive(Clone)]
314 pub struct RpcV2TestCDIPriv {
315     /// Test-mode CDI private key, if available.
316     pub test_cdi_priv: Option<OpaqueOr<crypto::ec::Key>>,
317     /// An optional opaque blob set by the TA, if the TA wants a mechanism to relate the
318     /// two requests: `get_dice_info` and `sign_data` related to the same CSR.
319     pub context: Vec<u8>,
320 }
321 
322 /// Marker implementation for implementations that do not support `BOOTLOADER_ONLY` keys, which
323 /// always indicates that bootloader processing is complete.
324 pub struct BootloaderDone;
325 impl BootloaderStatus for BootloaderDone {}
326 
327 /// Trusted user presence indicator.
328 pub trait TrustedUserPresence {
329     /// Indication of whether user presence is detected, via a mechanism in the current secure
330     /// environment.
available(&self) -> bool331     fn available(&self) -> bool {
332         // By default assume that trusted user presence is not supported.
333         false
334     }
335 }
336 
337 /// Marker implementation to indicate that trusted user presence is not supported.
338 pub struct TrustedPresenceUnsupported;
339 impl TrustedUserPresence for TrustedPresenceUnsupported {}
340 
341 /// Storage key wrapping.
342 pub trait StorageKeyWrapper {
343     /// Wrap the provided key material using an ephemeral storage key.
ephemeral_wrap(&self, key_material: &KeyMaterial) -> Result<Vec<u8>, Error>344     fn ephemeral_wrap(&self, key_material: &KeyMaterial) -> Result<Vec<u8>, Error>;
345 }
346 
347 // No-op implementations for the non-optional device traits. These implementations are only
348 // intended for convenience during the process of porting the KeyMint code to a new environment.
349 
350 /// Stub implementation of [`RetrieveKeyMaterial`].
351 pub struct NoOpRetrieveKeyMaterial;
352 impl RetrieveKeyMaterial for NoOpRetrieveKeyMaterial {
root_kek(&self, _context: &[u8]) -> Result<OpaqueOr<hmac::Key>, Error>353     fn root_kek(&self, _context: &[u8]) -> Result<OpaqueOr<hmac::Key>, Error> {
354         unimpl!();
355     }
356 
kak(&self) -> Result<OpaqueOr<aes::Key>, Error>357     fn kak(&self) -> Result<OpaqueOr<aes::Key>, Error> {
358         unimpl!();
359     }
360 }
361 
362 /// Stub implementation of [`RetrieveCertSigningInfo`].
363 pub struct NoOpRetrieveCertSigningInfo;
364 impl RetrieveCertSigningInfo for NoOpRetrieveCertSigningInfo {
signing_key(&self, _key_type: SigningKeyType) -> Result<KeyMaterial, Error>365     fn signing_key(&self, _key_type: SigningKeyType) -> Result<KeyMaterial, Error> {
366         unimpl!();
367     }
368 
cert_chain(&self, _key_type: SigningKeyType) -> Result<Vec<keymint::Certificate>, Error>369     fn cert_chain(&self, _key_type: SigningKeyType) -> Result<Vec<keymint::Certificate>, Error> {
370         unimpl!();
371     }
372 }
373 
374 /// Stub implementation of [`RetrieveRpcArtifacts`].
375 pub struct NoOpRetrieveRpcArtifacts;
376 impl RetrieveRpcArtifacts for NoOpRetrieveRpcArtifacts {
derive_bytes_from_hbk( &self, _hkdf: &dyn crypto::Hkdf, _context: &[u8], _output_len: usize, ) -> Result<Vec<u8>, Error>377     fn derive_bytes_from_hbk(
378         &self,
379         _hkdf: &dyn crypto::Hkdf,
380         _context: &[u8],
381         _output_len: usize,
382     ) -> Result<Vec<u8>, Error> {
383         unimpl!();
384     }
385 
get_dice_info<'a>(&self, _test_mode: rpc::TestMode) -> Result<DiceInfo, Error>386     fn get_dice_info<'a>(&self, _test_mode: rpc::TestMode) -> Result<DiceInfo, Error> {
387         unimpl!();
388     }
389 
sign_data( &self, _ec: &dyn crypto::Ec, _data: &[u8], _rpc_v2: Option<RpcV2Req>, ) -> Result<Vec<u8>, Error>390     fn sign_data(
391         &self,
392         _ec: &dyn crypto::Ec,
393         _data: &[u8],
394         _rpc_v2: Option<RpcV2Req>,
395     ) -> Result<Vec<u8>, Error> {
396         unimpl!();
397     }
398 }
399