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, rng::BoringRng}; 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, EcCurve}; 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 sign_algo: CsrSigningAlgorithm, 39 // Invariant once populated: `self.dice_info.signing_algorithm` == `self.sign_algo` 40 dice_info: RefCell<Option<DiceInfo>>, 41 // Invariant once populated: `self.bcc_signing_key` is a variant that matches `self.sign_algo` 42 bcc_signing_key: RefCell<Option<ec::Key>>, 43 } 44 45 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>46 fn derive_bytes_from_hbk( 47 &self, 48 _hkdf: &dyn crypto::Hkdf, 49 context: &[u8], 50 output_len: usize, 51 ) -> Result<Vec<u8>, Error> { 52 self.derive.derive_bytes(context, output_len) 53 } 54 get_dice_info(&self, _test_mode: rpc::TestMode) -> Result<DiceInfo, Error>55 fn get_dice_info(&self, _test_mode: rpc::TestMode) -> Result<DiceInfo, Error> { 56 if self.dice_info.borrow().is_none() { 57 let (dice_info, priv_key) = self.generate_dice_artifacts(rpc::TestMode(false))?; 58 *self.dice_info.borrow_mut() = Some(dice_info); 59 *self.bcc_signing_key.borrow_mut() = Some(priv_key); 60 } 61 62 Ok(self 63 .dice_info 64 .borrow() 65 .as_ref() 66 .ok_or_else(|| rpc_err!(Failed, "DICE artifacts are not initialized."))? 67 .clone()) 68 } 69 sign_data( &self, ec: &dyn crypto::Ec, data: &[u8], _rpc_v2: Option<RpcV2Req>, ) -> Result<Vec<u8>, Error>70 fn sign_data( 71 &self, 72 ec: &dyn crypto::Ec, 73 data: &[u8], 74 _rpc_v2: Option<RpcV2Req>, 75 ) -> Result<Vec<u8>, Error> { 76 // DICE artifacts should have been initialized via `get_dice_info()` by the time this 77 // method is called. 78 let private_key = self 79 .bcc_signing_key 80 .borrow() 81 .as_ref() 82 .ok_or_else(|| rpc_err!(Failed, "DICE artifacts are not initialized."))? 83 .clone(); 84 85 let mut op = ec.begin_sign(private_key.into(), self.signing_digest())?; 86 op.update(data)?; 87 let sig = op.finish()?; 88 crypto::ec::to_cose_signature(self.signing_curve(), sig) 89 } 90 } 91 92 impl<T: DeriveBytes> Artifacts<T> { 93 /// Constructor. new(derive: T, sign_algo: CsrSigningAlgorithm) -> Self94 pub fn new(derive: T, sign_algo: CsrSigningAlgorithm) -> Self { 95 Self { 96 derive, 97 sign_algo, 98 dice_info: RefCell::new(None), 99 bcc_signing_key: RefCell::new(None), 100 } 101 } 102 103 /// Indicate the curve used in signing. signing_curve(&self) -> EcCurve104 fn signing_curve(&self) -> EcCurve { 105 match self.sign_algo { 106 CsrSigningAlgorithm::ES256 => EcCurve::P256, 107 CsrSigningAlgorithm::ES384 => EcCurve::P384, 108 CsrSigningAlgorithm::EdDSA => EcCurve::Curve25519, 109 } 110 } 111 112 /// Indicate the digest used in signing. signing_digest(&self) -> Digest113 fn signing_digest(&self) -> Digest { 114 match self.sign_algo { 115 CsrSigningAlgorithm::ES256 => Digest::Sha256, 116 CsrSigningAlgorithm::ES384 => Digest::Sha384, 117 CsrSigningAlgorithm::EdDSA => Digest::None, 118 } 119 } 120 121 /// Indicate the COSE algorithm value associated with signing. signing_cose_algo(&self) -> iana::Algorithm122 fn signing_cose_algo(&self) -> iana::Algorithm { 123 match self.sign_algo { 124 CsrSigningAlgorithm::ES256 => iana::Algorithm::ES256, 125 CsrSigningAlgorithm::ES384 => iana::Algorithm::ES384, 126 CsrSigningAlgorithm::EdDSA => iana::Algorithm::EdDSA, 127 } 128 } 129 generate_dice_artifacts( &self, _test_mode: rpc::TestMode, ) -> Result<(DiceInfo, ec::Key), Error>130 fn generate_dice_artifacts( 131 &self, 132 _test_mode: rpc::TestMode, 133 ) -> Result<(DiceInfo, ec::Key), Error> { 134 let ec = BoringEc::default(); 135 136 let key_material = match self.sign_algo { 137 CsrSigningAlgorithm::EdDSA => { 138 let secret = self.derive_bytes_from_hbk(&BoringHmac, b"Device Key Seed", 32)?; 139 ec::import_raw_ed25519_key(&secret) 140 } 141 // TODO: generate the *same* key after reboot, by use of the TPM. 142 CsrSigningAlgorithm::ES256 => { 143 ec.generate_nist_key(&mut BoringRng, ec::NistCurve::P256, &[]) 144 } 145 CsrSigningAlgorithm::ES384 => { 146 ec.generate_nist_key(&mut BoringRng, ec::NistCurve::P384, &[]) 147 } 148 }?; 149 let (pub_cose_key, private_key) = match key_material { 150 KeyMaterial::Ec(curve, curve_type, key) => ( 151 key.public_cose_key( 152 &ec, 153 curve, 154 curve_type, 155 CoseKeyPurpose::Sign, 156 None, /* no key ID */ 157 rpc::TestMode(false), 158 )?, 159 key, 160 ), 161 _ => { 162 return Err(rpc_err!( 163 Failed, 164 "expected the Ec variant of KeyMaterial for the cdi leaf key." 165 )) 166 } 167 }; 168 169 let cose_key_cbor = pub_cose_key.to_cbor_value().map_err(CborError::from)?; 170 let cose_key_cbor_data = kmr_ta::rkp::serialize_cbor(&cose_key_cbor)?; 171 172 // Construct `DiceChainEntryPayload` 173 let dice_chain_entry_payload = Value::Map(vec_try![ 174 // Issuer 175 ( 176 Value::Integer(1.into()), 177 Value::Text(String::from("Issuer")) 178 ), 179 // Subject 180 ( 181 Value::Integer(2.into()), 182 Value::Text(String::from("Subject")) 183 ), 184 // Subject public key 185 ( 186 Value::Integer((-4670552).into()), 187 Value::Bytes(cose_key_cbor_data) 188 ), 189 // Key Usage field contains a CBOR byte string of the bits which correspond 190 // to `keyCertSign` as per RFC 5280 Section 4.2.1.3 (in little-endian byte order) 191 ( 192 Value::Integer((-4670553).into()), 193 Value::Bytes(vec_try![0x20]?) 194 ), 195 ]?); 196 let dice_chain_entry_payload_data = kmr_ta::rkp::serialize_cbor(&dice_chain_entry_payload)?; 197 198 // Construct `DiceChainEntry` 199 let protected = HeaderBuilder::new() 200 .algorithm(self.signing_cose_algo()) 201 .build(); 202 let dice_chain_entry = CoseSign1Builder::new() 203 .protected(protected) 204 .payload(dice_chain_entry_payload_data) 205 .try_create_signature(&[], |input| { 206 let mut op = ec.begin_sign(private_key.clone(), self.signing_digest())?; 207 op.update(input)?; 208 let sig = op.finish()?; 209 crypto::ec::to_cose_signature(self.signing_curve(), sig) 210 })? 211 .build(); 212 let dice_chain_entry_cbor = dice_chain_entry.to_cbor_value().map_err(CborError::from)?; 213 214 // Construct `DiceCertChain` 215 let dice_cert_chain = Value::Array(vec_try![cose_key_cbor, dice_chain_entry_cbor]?); 216 let dice_cert_chain_data = kmr_ta::rkp::serialize_cbor(&dice_cert_chain)?; 217 218 // Construct `UdsCerts` as an empty CBOR map 219 let uds_certs_data = kmr_ta::rkp::serialize_cbor(&Value::Map(Vec::new()))?; 220 221 let pub_dice_artifacts = PubDiceArtifacts { 222 dice_cert_chain: dice_cert_chain_data, 223 uds_certs: uds_certs_data, 224 }; 225 226 let dice_info = DiceInfo { 227 pub_dice_artifacts, 228 signing_algorithm: self.sign_algo, 229 rpc_v2_test_cdi_priv: None, 230 }; 231 232 Ok((dice_info, explicit!(private_key)?)) 233 } 234 } 235