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 //! Trusty implementation of `RetrieveRpcArtifacts`. Currently, this supports
17 //! only IRPC V3.
18 
19 use crate::secure_storage_manager;
20 use hwbcc::{get_bcc, sign_data, HwBccMode, SigningAlgorithm, HWBCC_MAX_RESP_PAYLOAD_LENGTH};
21 use hwkey::{Hwkey, KdfVersion};
22 use kmr_common::{crypto, rpc_err, vec_try, Error};
23 use kmr_ta::device::{
24     CsrSigningAlgorithm, DiceInfo, PubDiceArtifacts, RetrieveRpcArtifacts, RpcV2Req,
25 };
26 use kmr_ta::rkp::serialize_cbor;
27 use kmr_wire::{cbor::value::Value, rpc};
28 
29 // This matches the value of kMasterKeyDerivationData in
30 // trusty/user/app/keymaster/trusty_remote_provisioning_context.cpp
31 const HBK_KEY_DERIVATION_DATA: &[u8] = b"RemoteKeyProvisioningMasterKey";
32 
33 // SignerName is a string identifier that indicates both the signing authority
34 // as well as the format of the UdsCertChain
35 const SIGNER_NAME: &str = "GSMIRkpSecp384r1";
36 
37 pub struct TrustyRpc;
38 
39 impl RetrieveRpcArtifacts for TrustyRpc {
derive_bytes_from_hbk( &self, hkdf: &dyn crypto::Hkdf, context: &[u8], output_len: usize, ) -> Result<Vec<u8>, Error>40     fn derive_bytes_from_hbk(
41         &self,
42         hkdf: &dyn crypto::Hkdf,
43         context: &[u8],
44         output_len: usize,
45     ) -> Result<Vec<u8>, Error> {
46         let hwkey_session =
47             Hwkey::open().map_err(|e| rpc_err!(Failed, "failed to connect to Hwkey: {:?}", e))?;
48         let mut key_buf = vec_try![0u8; output_len]?;
49         hwkey_session
50             .derive_key_req()
51             .unique_key()
52             .kdf(KdfVersion::Version(1))
53             .derive(HBK_KEY_DERIVATION_DATA, key_buf.as_mut_slice())
54             .map_err(|e| rpc_err!(Failed, "failed to derive hardware backed key: {:?}", e))?;
55         hkdf.hkdf(&[], &key_buf, context, output_len)
56     }
57 
get_dice_info<'a>(&self, _test_mode: rpc::TestMode) -> Result<DiceInfo, Error>58     fn get_dice_info<'a>(&self, _test_mode: rpc::TestMode) -> Result<DiceInfo, Error> {
59         let mut bcc_buf = [0u8; HWBCC_MAX_RESP_PAYLOAD_LENGTH];
60         // Note: Test mode is ignored as this currently supports only IRPC V3.
61         let bcc = get_bcc(HwBccMode::Release, &mut bcc_buf)
62             .map_err(|e| rpc_err!(Failed, "failed to get DICE Info: {:?}", e))?;
63         // Construct `UdsCerts` as an empty CBOR map if not exist
64         let uds_certs_data = match secure_storage_manager::read_uds_cert() {
65             Ok(uds_certs) => {
66                 let encoded_certs = uds_certs
67                     .into_iter()
68                     .map(|cert| Value::Bytes(cert.encoded_certificate))
69                     .collect::<Vec<_>>();
70                 serialize_cbor(&Value::Map(vec![(
71                     Value::Text(SIGNER_NAME.to_string()),
72                     Value::Array(encoded_certs),
73                 )]))
74             }
75             Err(err) => {
76                 log::warn!("Failed to read UDS certificates: {:?}", err);
77                 serialize_cbor(&Value::Map(Vec::new()))
78             }
79         }?;
80         let pub_dice_artifacts =
81             PubDiceArtifacts { uds_certs: uds_certs_data, dice_cert_chain: bcc.to_vec() };
82         let dice_info = DiceInfo {
83             pub_dice_artifacts,
84             signing_algorithm: CsrSigningAlgorithm::EdDSA,
85             rpc_v2_test_cdi_priv: None,
86         };
87         Ok(dice_info)
88     }
89 
sign_data( &self, _ec: &dyn crypto::Ec, _data: &[u8], _rpc_v2: Option<RpcV2Req>, ) -> Result<Vec<u8>, Error>90     fn sign_data(
91         &self,
92         _ec: &dyn crypto::Ec,
93         _data: &[u8],
94         _rpc_v2: Option<RpcV2Req>,
95     ) -> Result<Vec<u8>, Error> {
96         // This is marked unimplemented because we override `sign_data_in_cose_sign1` below.
97         Err(rpc_err!(Failed, "unimplemented"))
98     }
99 
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>100     fn sign_data_in_cose_sign1(
101         &self,
102         _ec: &dyn crypto::Ec,
103         signing_algorithm: &CsrSigningAlgorithm,
104         payload: &[u8],
105         aad: &[u8],
106         _rpc_v2: Option<RpcV2Req>,
107     ) -> Result<Vec<u8>, Error> {
108         match signing_algorithm {
109             CsrSigningAlgorithm::EdDSA => {}
110             _ => {
111                 return Err(rpc_err!(
112                     Failed,
113                     "requested signing algorithm: {:?}, but only ED25519 is supported.",
114                     signing_algorithm
115                 ));
116             }
117         }
118 
119         let mut cose_sign1_buf = [0u8; HWBCC_MAX_RESP_PAYLOAD_LENGTH];
120         // Note: Test mode is ignored as this currently supports only IRPC V3.
121         let cose_sign1 = sign_data(
122             HwBccMode::Release,
123             SigningAlgorithm::ED25519,
124             payload,
125             aad,
126             &mut cose_sign1_buf,
127         )
128         .map_err(|e| rpc_err!(Failed, "failed to get signed data: {:?}", e))?;
129         Ok(cose_sign1.to_vec())
130     }
131 }
132