• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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