1 // 2 // Copyright (C) 2022 The Android Open Source Project 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 16 //! Emulated implementation of device traits for `IRemotelyProvisionedComponent`. 17 18 use core::cell::RefCell; 19 use kmr_common::crypto::{ec, ec::CoseKeyPurpose, Ec, KeyMaterial}; 20 use kmr_common::{crypto, explicit, rpc_err, vec_try, Error}; 21 use kmr_crypto_boring::{ec::BoringEc, hmac::BoringHmac}; 22 use kmr_ta::device::{ 23 CsrSigningAlgorithm, DiceInfo, PubDiceArtifacts, RetrieveRpcArtifacts, RpcV2Req, 24 }; 25 use kmr_wire::coset::{iana, CoseSign1Builder, HeaderBuilder}; 26 use kmr_wire::keymint::Digest; 27 use kmr_wire::{cbor::value::Value, coset::AsCborValue, rpc, CborError}; 28 29 /// Trait to encapsulate deterministic derivation of secret data. 30 pub trait DeriveBytes { 31 /// Derive `output_len` bytes of data from `context`, deterministically. derive_bytes(&self, context: &[u8], output_len: usize) -> Result<Vec<u8>, Error>32 fn derive_bytes(&self, context: &[u8], output_len: usize) -> Result<Vec<u8>, Error>; 33 } 34 35 /// Common emulated implementation of RPC artifact retrieval. 36 pub struct Artifacts<T: DeriveBytes> { 37 derive: T, 38 dice_artifacts: RefCell<Option<(DiceInfo, crypto::ec::Key)>>, 39 } 40 41 impl<T: DeriveBytes> RetrieveRpcArtifacts for Artifacts<T> { derive_bytes_from_hbk( &self, _hkdf: &dyn crypto::Hkdf, context: &[u8], output_len: usize, ) -> Result<Vec<u8>, Error>42 fn derive_bytes_from_hbk( 43 &self, 44 _hkdf: &dyn crypto::Hkdf, 45 context: &[u8], 46 output_len: usize, 47 ) -> Result<Vec<u8>, Error> { 48 self.derive.derive_bytes(context, output_len) 49 } 50 get_dice_info<'a>(&self, _test_mode: rpc::TestMode) -> Result<DiceInfo, Error>51 fn get_dice_info<'a>(&self, _test_mode: rpc::TestMode) -> Result<DiceInfo, Error> { 52 if self.dice_artifacts.borrow().is_none() { 53 self.generate_dice_artifacts(rpc::TestMode(false))?; 54 } 55 56 let (dice_info, _) = self 57 .dice_artifacts 58 .borrow() 59 .as_ref() 60 .ok_or_else(|| rpc_err!(Failed, "DICE artifacts are not initialized."))? 61 .clone(); 62 Ok(dice_info) 63 } 64 sign_data( &self, ec: &dyn crypto::Ec, data: &[u8], _rpc_v2: Option<RpcV2Req>, ) -> Result<Vec<u8>, Error>65 fn sign_data( 66 &self, 67 ec: &dyn crypto::Ec, 68 data: &[u8], 69 _rpc_v2: Option<RpcV2Req>, 70 ) -> Result<Vec<u8>, Error> { 71 // DICE artifacts should have been initialized via `get_dice_info` by the time this 72 // method is called. 73 let (dice_info, private_key) = self 74 .dice_artifacts 75 .borrow() 76 .as_ref() 77 .ok_or_else(|| rpc_err!(Failed, "DICE artifacts are not initialized."))? 78 .clone(); 79 80 let mut op = match dice_info.signing_algorithm { 81 CsrSigningAlgorithm::ES256 => ec.begin_sign(private_key.into(), Digest::Sha256)?, 82 CsrSigningAlgorithm::ES384 => ec.begin_sign(private_key.into(), Digest::Sha384)?, 83 CsrSigningAlgorithm::EdDSA => ec.begin_sign(private_key.into(), Digest::None)?, 84 }; 85 op.update(data)?; 86 op.finish() 87 } 88 } 89 90 impl<T: DeriveBytes> Artifacts<T> { 91 /// Constructor. new(derive: T) -> Self92 pub fn new(derive: T) -> Self { 93 Self { derive, dice_artifacts: RefCell::new(None) } 94 } 95 generate_dice_artifacts(&self, _test_mode: rpc::TestMode) -> Result<(), Error>96 fn generate_dice_artifacts(&self, _test_mode: rpc::TestMode) -> Result<(), Error> { 97 let ec = BoringEc::default(); 98 let secret = self.derive_bytes_from_hbk(&BoringHmac, b"Device Key Seed", 32)?; 99 let (pub_cose_key, private_key) = match ec::import_raw_ed25519_key(&secret)? { 100 KeyMaterial::Ec(curve, curve_type, key) => ( 101 key.public_cose_key( 102 &ec, 103 curve, 104 curve_type, 105 CoseKeyPurpose::Sign, 106 None, /* no key ID */ 107 rpc::TestMode(false), 108 )?, 109 key, 110 ), 111 _ => { 112 return Err(rpc_err!( 113 Failed, 114 "expected the Ec variant of KeyMaterial for the cdi leaf key." 115 )) 116 } 117 }; 118 119 let cose_key_cbor = pub_cose_key.to_cbor_value().map_err(CborError::from)?; 120 let cose_key_cbor_data = kmr_ta::rkp::serialize_cbor(&cose_key_cbor)?; 121 122 // Construct `DiceChainEntryPayload` 123 let dice_chain_entry_payload = Value::Map(vec_try![ 124 // Issuer 125 (Value::Integer(1.into()), Value::Text(String::from("Issuer"))), 126 // Subject 127 (Value::Integer(2.into()), Value::Text(String::from("Subject"))), 128 // Subject public key 129 (Value::Integer((-4670552).into()), Value::Bytes(cose_key_cbor_data)), 130 // Key Usage field contains a CBOR byte string of the bits which correspond 131 // to `keyCertSign` as per RFC 5280 Section 4.2.1.3 (in little-endian byte order) 132 (Value::Integer((-4670553).into()), Value::Bytes(vec_try![0x20]?)), 133 ]?); 134 let dice_chain_entry_payload_data = kmr_ta::rkp::serialize_cbor(&dice_chain_entry_payload)?; 135 136 // Construct `DiceChainEntry` 137 let protected = HeaderBuilder::new().algorithm(iana::Algorithm::EdDSA).build(); 138 let dice_chain_entry = CoseSign1Builder::new() 139 .protected(protected) 140 .payload(dice_chain_entry_payload_data) 141 .try_create_signature(&[], |input| { 142 let mut op = ec.begin_sign(private_key.clone(), Digest::None)?; 143 op.update(input)?; 144 op.finish() 145 })? 146 .build(); 147 let dice_chain_entry_cbor = dice_chain_entry.to_cbor_value().map_err(CborError::from)?; 148 149 // Construct `DiceCertChain` 150 let dice_cert_chain = Value::Array(vec_try![cose_key_cbor, dice_chain_entry_cbor]?); 151 let dice_cert_chain_data = kmr_ta::rkp::serialize_cbor(&dice_cert_chain)?; 152 153 // Construct `UdsCerts` as an empty CBOR map 154 let uds_certs_data = kmr_ta::rkp::serialize_cbor(&Value::Map(Vec::new()))?; 155 156 let pub_dice_artifacts = 157 PubDiceArtifacts { dice_cert_chain: dice_cert_chain_data, uds_certs: uds_certs_data }; 158 159 let dice_info = DiceInfo { 160 pub_dice_artifacts, 161 signing_algorithm: CsrSigningAlgorithm::EdDSA, 162 rpc_v2_test_cdi_priv: None, 163 }; 164 165 *self.dice_artifacts.borrow_mut() = Some((dice_info, explicit!(private_key)?)); 166 167 Ok(()) 168 } 169 } 170