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