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