1*9860b763SAndroid Build Coastguard Worker // Copyright 2022, The Android Open Source Project
2*9860b763SAndroid Build Coastguard Worker //
3*9860b763SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*9860b763SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*9860b763SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*9860b763SAndroid Build Coastguard Worker //
7*9860b763SAndroid Build Coastguard Worker // http://www.apache.org/licenses/LICENSE-2.0
8*9860b763SAndroid Build Coastguard Worker //
9*9860b763SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*9860b763SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*9860b763SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*9860b763SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*9860b763SAndroid Build Coastguard Worker // limitations under the License.
14*9860b763SAndroid Build Coastguard Worker
15*9860b763SAndroid Build Coastguard Worker //! Functionality for remote key provisioning
16*9860b763SAndroid Build Coastguard Worker
17*9860b763SAndroid Build Coastguard Worker use super::KeyMintTa;
18*9860b763SAndroid Build Coastguard Worker use crate::coset::{
19*9860b763SAndroid Build Coastguard Worker cbor::value::Value, iana, AsCborValue, CborSerializable, CoseKey, CoseMac0, CoseMac0Builder,
20*9860b763SAndroid Build Coastguard Worker HeaderBuilder, Label,
21*9860b763SAndroid Build Coastguard Worker };
22*9860b763SAndroid Build Coastguard Worker use crate::RpcInfo;
23*9860b763SAndroid Build Coastguard Worker use alloc::string::{String, ToString};
24*9860b763SAndroid Build Coastguard Worker use alloc::{vec, vec::Vec};
25*9860b763SAndroid Build Coastguard Worker use kmr_common::crypto::{
26*9860b763SAndroid Build Coastguard Worker ec::{CoseKeyPurpose, RKP_TEST_KEY_CBOR_MARKER},
27*9860b763SAndroid Build Coastguard Worker hmac_sha256, KeyMaterial,
28*9860b763SAndroid Build Coastguard Worker };
29*9860b763SAndroid Build Coastguard Worker use kmr_common::{keyblob, km_err, rpc_err, try_to_vec, Error, FallibleAllocExt};
30*9860b763SAndroid Build Coastguard Worker use kmr_wire::{
31*9860b763SAndroid Build Coastguard Worker cbor,
32*9860b763SAndroid Build Coastguard Worker cbor::cbor,
33*9860b763SAndroid Build Coastguard Worker keymint::{
34*9860b763SAndroid Build Coastguard Worker Algorithm, Digest, EcCurve, KeyParam, KeyPurpose, SecurityLevel, VerifiedBootState,
35*9860b763SAndroid Build Coastguard Worker UNDEFINED_NOT_AFTER, UNDEFINED_NOT_BEFORE,
36*9860b763SAndroid Build Coastguard Worker },
37*9860b763SAndroid Build Coastguard Worker read_to_value, rpc,
38*9860b763SAndroid Build Coastguard Worker rpc::{
39*9860b763SAndroid Build Coastguard Worker DeviceInfo, EekCurve, HardwareInfo, MacedPublicKey, ProtectedData,
40*9860b763SAndroid Build Coastguard Worker MINIMUM_SUPPORTED_KEYS_IN_CSR,
41*9860b763SAndroid Build Coastguard Worker },
42*9860b763SAndroid Build Coastguard Worker rpc::{AUTH_REQ_SCHEMA_V1, CERT_TYPE_KEYMINT, IRPC_V2, IRPC_V3},
43*9860b763SAndroid Build Coastguard Worker types::KeySizeInBits,
44*9860b763SAndroid Build Coastguard Worker CborError,
45*9860b763SAndroid Build Coastguard Worker };
46*9860b763SAndroid Build Coastguard Worker
47*9860b763SAndroid Build Coastguard Worker const RPC_P256_KEYGEN_PARAMS: [KeyParam; 8] = [
48*9860b763SAndroid Build Coastguard Worker KeyParam::Purpose(KeyPurpose::AttestKey),
49*9860b763SAndroid Build Coastguard Worker KeyParam::Algorithm(Algorithm::Ec),
50*9860b763SAndroid Build Coastguard Worker KeyParam::KeySize(KeySizeInBits(256)),
51*9860b763SAndroid Build Coastguard Worker KeyParam::EcCurve(EcCurve::P256),
52*9860b763SAndroid Build Coastguard Worker KeyParam::NoAuthRequired,
53*9860b763SAndroid Build Coastguard Worker KeyParam::Digest(Digest::Sha256),
54*9860b763SAndroid Build Coastguard Worker KeyParam::CertificateNotBefore(UNDEFINED_NOT_BEFORE),
55*9860b763SAndroid Build Coastguard Worker KeyParam::CertificateNotAfter(UNDEFINED_NOT_AFTER),
56*9860b763SAndroid Build Coastguard Worker ];
57*9860b763SAndroid Build Coastguard Worker
58*9860b763SAndroid Build Coastguard Worker const MAX_CHALLENGE_SIZE_V2: usize = 64;
59*9860b763SAndroid Build Coastguard Worker
60*9860b763SAndroid Build Coastguard Worker impl KeyMintTa {
61*9860b763SAndroid Build Coastguard Worker /// Return the UDS certs for the device, encoded in CBOR as per `AdditionalDKSignatures`
62*9860b763SAndroid Build Coastguard Worker /// structure in ProtectedData.aidl for IRPC HAL version 2 and as per `UdsCerts` structure in
63*9860b763SAndroid Build Coastguard Worker /// IRPC HAL version 3.
uds_certs(&self) -> Result<Vec<u8>, Error>64*9860b763SAndroid Build Coastguard Worker pub fn uds_certs(&self) -> Result<Vec<u8>, Error> {
65*9860b763SAndroid Build Coastguard Worker let dice_info =
66*9860b763SAndroid Build Coastguard Worker self.get_dice_info().ok_or_else(|| rpc_err!(Failed, "DICE info not available."))?;
67*9860b763SAndroid Build Coastguard Worker try_to_vec(&dice_info.pub_dice_artifacts.uds_certs)
68*9860b763SAndroid Build Coastguard Worker }
69*9860b763SAndroid Build Coastguard Worker
70*9860b763SAndroid Build Coastguard Worker /// Return the CBOR-encoded `DeviceInfo`.
rpc_device_info(&self) -> Result<Vec<u8>, Error>71*9860b763SAndroid Build Coastguard Worker pub fn rpc_device_info(&self) -> Result<Vec<u8>, Error> {
72*9860b763SAndroid Build Coastguard Worker let info = self.rpc_device_info_cbor()?;
73*9860b763SAndroid Build Coastguard Worker serialize_cbor(&info)
74*9860b763SAndroid Build Coastguard Worker }
75*9860b763SAndroid Build Coastguard Worker
rpc_device_info_cbor(&self) -> Result<Value, Error>76*9860b763SAndroid Build Coastguard Worker fn rpc_device_info_cbor(&self) -> Result<Value, Error> {
77*9860b763SAndroid Build Coastguard Worker // First make sure all the relevant info is available.
78*9860b763SAndroid Build Coastguard Worker let ids = self.get_attestation_ids().ok_or_else(|| {
79*9860b763SAndroid Build Coastguard Worker km_err!(AttestationIdsNotProvisioned, "attestation ID info not available")
80*9860b763SAndroid Build Coastguard Worker })?;
81*9860b763SAndroid Build Coastguard Worker let boot_info = self
82*9860b763SAndroid Build Coastguard Worker .boot_info
83*9860b763SAndroid Build Coastguard Worker .as_ref()
84*9860b763SAndroid Build Coastguard Worker .ok_or_else(|| km_err!(HardwareNotYetAvailable, "boot info not available"))?;
85*9860b763SAndroid Build Coastguard Worker let hal_info = self
86*9860b763SAndroid Build Coastguard Worker .hal_info
87*9860b763SAndroid Build Coastguard Worker .as_ref()
88*9860b763SAndroid Build Coastguard Worker .ok_or_else(|| km_err!(HardwareNotYetAvailable, "HAL info not available"))?;
89*9860b763SAndroid Build Coastguard Worker
90*9860b763SAndroid Build Coastguard Worker let brand = String::from_utf8_lossy(&ids.brand);
91*9860b763SAndroid Build Coastguard Worker let manufacturer = String::from_utf8_lossy(&ids.manufacturer);
92*9860b763SAndroid Build Coastguard Worker let product = String::from_utf8_lossy(&ids.product);
93*9860b763SAndroid Build Coastguard Worker let model = String::from_utf8_lossy(&ids.model);
94*9860b763SAndroid Build Coastguard Worker let device = String::from_utf8_lossy(&ids.device);
95*9860b763SAndroid Build Coastguard Worker
96*9860b763SAndroid Build Coastguard Worker let bootloader_state = if boot_info.device_boot_locked { "locked" } else { "unlocked" };
97*9860b763SAndroid Build Coastguard Worker let vbmeta_digest = cbor::value::Value::Bytes(try_to_vec(&boot_info.verified_boot_hash)?);
98*9860b763SAndroid Build Coastguard Worker let vb_state = match boot_info.verified_boot_state {
99*9860b763SAndroid Build Coastguard Worker VerifiedBootState::Verified => "green",
100*9860b763SAndroid Build Coastguard Worker VerifiedBootState::SelfSigned => "yellow",
101*9860b763SAndroid Build Coastguard Worker VerifiedBootState::Unverified => "orange",
102*9860b763SAndroid Build Coastguard Worker VerifiedBootState::Failed => "red",
103*9860b763SAndroid Build Coastguard Worker };
104*9860b763SAndroid Build Coastguard Worker let security_level = match self.hw_info.security_level {
105*9860b763SAndroid Build Coastguard Worker SecurityLevel::TrustedEnvironment => "tee",
106*9860b763SAndroid Build Coastguard Worker SecurityLevel::Strongbox => "strongbox",
107*9860b763SAndroid Build Coastguard Worker l => {
108*9860b763SAndroid Build Coastguard Worker return Err(km_err!(
109*9860b763SAndroid Build Coastguard Worker HardwareTypeUnavailable,
110*9860b763SAndroid Build Coastguard Worker "security level {:?} not supported",
111*9860b763SAndroid Build Coastguard Worker l
112*9860b763SAndroid Build Coastguard Worker ))
113*9860b763SAndroid Build Coastguard Worker }
114*9860b763SAndroid Build Coastguard Worker };
115*9860b763SAndroid Build Coastguard Worker
116*9860b763SAndroid Build Coastguard Worker let fused = match &self.rpc_info {
117*9860b763SAndroid Build Coastguard Worker RpcInfo::V2(rpc_info_v2) => rpc_info_v2.fused,
118*9860b763SAndroid Build Coastguard Worker RpcInfo::V3(rpc_info_v3) => rpc_info_v3.fused,
119*9860b763SAndroid Build Coastguard Worker };
120*9860b763SAndroid Build Coastguard Worker // The DeviceInfo.aidl file specifies that map keys should be ordered according
121*9860b763SAndroid Build Coastguard Worker // to RFC 7049 canonicalization rules, which are:
122*9860b763SAndroid Build Coastguard Worker // - shorter-encoded key < longer-encoded key
123*9860b763SAndroid Build Coastguard Worker // - lexicographic comparison for same-length keys
124*9860b763SAndroid Build Coastguard Worker // Note that this is *different* than the ordering required in RFC 8949 s4.2.1.
125*9860b763SAndroid Build Coastguard Worker let info = cbor!({
126*9860b763SAndroid Build Coastguard Worker "brand" => brand,
127*9860b763SAndroid Build Coastguard Worker "fused" => i32::from(fused),
128*9860b763SAndroid Build Coastguard Worker "model" => model,
129*9860b763SAndroid Build Coastguard Worker "device" => device,
130*9860b763SAndroid Build Coastguard Worker "product" => product,
131*9860b763SAndroid Build Coastguard Worker "vb_state" => vb_state,
132*9860b763SAndroid Build Coastguard Worker "os_version" => hal_info.os_version.to_string(),
133*9860b763SAndroid Build Coastguard Worker "manufacturer" => manufacturer,
134*9860b763SAndroid Build Coastguard Worker "vbmeta_digest" => vbmeta_digest,
135*9860b763SAndroid Build Coastguard Worker "security_level" => security_level,
136*9860b763SAndroid Build Coastguard Worker "boot_patch_level" => boot_info.boot_patchlevel,
137*9860b763SAndroid Build Coastguard Worker "bootloader_state" => bootloader_state,
138*9860b763SAndroid Build Coastguard Worker "system_patch_level" => hal_info.os_patchlevel,
139*9860b763SAndroid Build Coastguard Worker "vendor_patch_level" => hal_info.vendor_patchlevel,
140*9860b763SAndroid Build Coastguard Worker })?;
141*9860b763SAndroid Build Coastguard Worker Ok(info)
142*9860b763SAndroid Build Coastguard Worker }
143*9860b763SAndroid Build Coastguard Worker
get_rpc_hardware_info(&self) -> Result<HardwareInfo, Error>144*9860b763SAndroid Build Coastguard Worker pub(crate) fn get_rpc_hardware_info(&self) -> Result<HardwareInfo, Error> {
145*9860b763SAndroid Build Coastguard Worker match &self.rpc_info {
146*9860b763SAndroid Build Coastguard Worker RpcInfo::V2(rpc_info_v2) => Ok(HardwareInfo {
147*9860b763SAndroid Build Coastguard Worker version_number: IRPC_V2,
148*9860b763SAndroid Build Coastguard Worker rpc_author_name: rpc_info_v2.author_name.to_string(),
149*9860b763SAndroid Build Coastguard Worker supported_eek_curve: rpc_info_v2.supported_eek_curve,
150*9860b763SAndroid Build Coastguard Worker unique_id: Some(rpc_info_v2.unique_id.to_string()),
151*9860b763SAndroid Build Coastguard Worker supported_num_keys_in_csr: MINIMUM_SUPPORTED_KEYS_IN_CSR,
152*9860b763SAndroid Build Coastguard Worker }),
153*9860b763SAndroid Build Coastguard Worker RpcInfo::V3(rpc_info_v3) => Ok(HardwareInfo {
154*9860b763SAndroid Build Coastguard Worker version_number: IRPC_V3,
155*9860b763SAndroid Build Coastguard Worker rpc_author_name: rpc_info_v3.author_name.to_string(),
156*9860b763SAndroid Build Coastguard Worker supported_eek_curve: EekCurve::None,
157*9860b763SAndroid Build Coastguard Worker unique_id: Some(rpc_info_v3.unique_id.to_string()),
158*9860b763SAndroid Build Coastguard Worker supported_num_keys_in_csr: rpc_info_v3.supported_num_of_keys_in_csr,
159*9860b763SAndroid Build Coastguard Worker }),
160*9860b763SAndroid Build Coastguard Worker }
161*9860b763SAndroid Build Coastguard Worker }
162*9860b763SAndroid Build Coastguard Worker
generate_ecdsa_p256_keypair( &mut self, test_mode: rpc::TestMode, ) -> Result<(MacedPublicKey, Vec<u8>), Error>163*9860b763SAndroid Build Coastguard Worker pub(crate) fn generate_ecdsa_p256_keypair(
164*9860b763SAndroid Build Coastguard Worker &mut self,
165*9860b763SAndroid Build Coastguard Worker test_mode: rpc::TestMode,
166*9860b763SAndroid Build Coastguard Worker ) -> Result<(MacedPublicKey, Vec<u8>), Error> {
167*9860b763SAndroid Build Coastguard Worker if self.rpc_info.get_version() > IRPC_V2 && test_mode == rpc::TestMode(true) {
168*9860b763SAndroid Build Coastguard Worker return Err(rpc_err!(
169*9860b763SAndroid Build Coastguard Worker Removed,
170*9860b763SAndroid Build Coastguard Worker "generate_ecdsa_p256_keypair does not support test mode in IRPC V3+ HAL."
171*9860b763SAndroid Build Coastguard Worker ));
172*9860b763SAndroid Build Coastguard Worker }
173*9860b763SAndroid Build Coastguard Worker
174*9860b763SAndroid Build Coastguard Worker let (key_material, chars) = self.generate_key_material(&RPC_P256_KEYGEN_PARAMS)?;
175*9860b763SAndroid Build Coastguard Worker
176*9860b763SAndroid Build Coastguard Worker let pub_cose_key = match key_material {
177*9860b763SAndroid Build Coastguard Worker KeyMaterial::Ec(curve, curve_type, ref key) => key.public_cose_key(
178*9860b763SAndroid Build Coastguard Worker &*self.imp.ec,
179*9860b763SAndroid Build Coastguard Worker curve,
180*9860b763SAndroid Build Coastguard Worker curve_type,
181*9860b763SAndroid Build Coastguard Worker CoseKeyPurpose::Sign,
182*9860b763SAndroid Build Coastguard Worker None,
183*9860b763SAndroid Build Coastguard Worker test_mode,
184*9860b763SAndroid Build Coastguard Worker )?,
185*9860b763SAndroid Build Coastguard Worker _ => return Err(km_err!(InvalidKeyBlob, "expected key material of type variant EC.")),
186*9860b763SAndroid Build Coastguard Worker };
187*9860b763SAndroid Build Coastguard Worker let pub_cose_key_encoded = pub_cose_key.to_vec().map_err(CborError::from)?;
188*9860b763SAndroid Build Coastguard Worker let maced_pub_key =
189*9860b763SAndroid Build Coastguard Worker build_maced_pub_key(pub_cose_key_encoded, |data| -> Result<Vec<u8>, Error> {
190*9860b763SAndroid Build Coastguard Worker // In test mode, use an all-zero HMAC key.
191*9860b763SAndroid Build Coastguard Worker if test_mode == rpc::TestMode(true) {
192*9860b763SAndroid Build Coastguard Worker return hmac_sha256(&*self.imp.hmac, &[0; 32], data);
193*9860b763SAndroid Build Coastguard Worker }
194*9860b763SAndroid Build Coastguard Worker self.dev.rpc.compute_hmac_sha256(&*self.imp.hmac, &*self.imp.hkdf, data)
195*9860b763SAndroid Build Coastguard Worker })?;
196*9860b763SAndroid Build Coastguard Worker
197*9860b763SAndroid Build Coastguard Worker let key_result = self.finish_keyblob_creation(
198*9860b763SAndroid Build Coastguard Worker &RPC_P256_KEYGEN_PARAMS,
199*9860b763SAndroid Build Coastguard Worker None,
200*9860b763SAndroid Build Coastguard Worker chars,
201*9860b763SAndroid Build Coastguard Worker key_material,
202*9860b763SAndroid Build Coastguard Worker keyblob::SlotPurpose::KeyGeneration,
203*9860b763SAndroid Build Coastguard Worker )?;
204*9860b763SAndroid Build Coastguard Worker
205*9860b763SAndroid Build Coastguard Worker Ok((MacedPublicKey { maced_key: maced_pub_key }, key_result.key_blob))
206*9860b763SAndroid Build Coastguard Worker }
207*9860b763SAndroid Build Coastguard Worker
generate_cert_req( &self, _test_mode: rpc::TestMode, _keys_to_sign: Vec<MacedPublicKey>, _eek_chain: &[u8], _challenge: &[u8], ) -> Result<(DeviceInfo, ProtectedData, Vec<u8>), Error>208*9860b763SAndroid Build Coastguard Worker pub(crate) fn generate_cert_req(
209*9860b763SAndroid Build Coastguard Worker &self,
210*9860b763SAndroid Build Coastguard Worker _test_mode: rpc::TestMode,
211*9860b763SAndroid Build Coastguard Worker _keys_to_sign: Vec<MacedPublicKey>,
212*9860b763SAndroid Build Coastguard Worker _eek_chain: &[u8],
213*9860b763SAndroid Build Coastguard Worker _challenge: &[u8],
214*9860b763SAndroid Build Coastguard Worker ) -> Result<(DeviceInfo, ProtectedData, Vec<u8>), Error> {
215*9860b763SAndroid Build Coastguard Worker if self.rpc_info.get_version() > IRPC_V2 {
216*9860b763SAndroid Build Coastguard Worker return Err(rpc_err!(Removed, "generate_cert_req is not supported in IRPC V3+ HAL."));
217*9860b763SAndroid Build Coastguard Worker }
218*9860b763SAndroid Build Coastguard Worker let _device_info = self.rpc_device_info()?;
219*9860b763SAndroid Build Coastguard Worker Err(km_err!(Unimplemented, "GenerateCertificateRequest is only required for RKP before v3"))
220*9860b763SAndroid Build Coastguard Worker }
221*9860b763SAndroid Build Coastguard Worker
generate_cert_req_v2( &self, keys_to_sign: Vec<MacedPublicKey>, challenge: &[u8], ) -> Result<Vec<u8>, Error>222*9860b763SAndroid Build Coastguard Worker pub(crate) fn generate_cert_req_v2(
223*9860b763SAndroid Build Coastguard Worker &self,
224*9860b763SAndroid Build Coastguard Worker keys_to_sign: Vec<MacedPublicKey>,
225*9860b763SAndroid Build Coastguard Worker challenge: &[u8],
226*9860b763SAndroid Build Coastguard Worker ) -> Result<Vec<u8>, Error> {
227*9860b763SAndroid Build Coastguard Worker if self.rpc_info.get_version() < IRPC_V3 {
228*9860b763SAndroid Build Coastguard Worker return Err(km_err!(
229*9860b763SAndroid Build Coastguard Worker Unimplemented,
230*9860b763SAndroid Build Coastguard Worker "generate_cert_req_v2 is not implemented for IRPC HAL V2 and below."
231*9860b763SAndroid Build Coastguard Worker ));
232*9860b763SAndroid Build Coastguard Worker }
233*9860b763SAndroid Build Coastguard Worker if challenge.len() > MAX_CHALLENGE_SIZE_V2 {
234*9860b763SAndroid Build Coastguard Worker return Err(km_err!(
235*9860b763SAndroid Build Coastguard Worker InvalidArgument,
236*9860b763SAndroid Build Coastguard Worker "Challenge is too big. Actual: {:?}. Maximum: {:?}.",
237*9860b763SAndroid Build Coastguard Worker challenge.len(),
238*9860b763SAndroid Build Coastguard Worker MAX_CHALLENGE_SIZE_V2
239*9860b763SAndroid Build Coastguard Worker ));
240*9860b763SAndroid Build Coastguard Worker }
241*9860b763SAndroid Build Coastguard Worker // Validate mac and extract the public keys to sign from the MacedPublicKeys
242*9860b763SAndroid Build Coastguard Worker let mut pub_cose_keys: Vec<Value> = Vec::new();
243*9860b763SAndroid Build Coastguard Worker for key_to_sign in keys_to_sign {
244*9860b763SAndroid Build Coastguard Worker let maced_pub_key = key_to_sign.maced_key;
245*9860b763SAndroid Build Coastguard Worker let cose_mac0 = CoseMac0::from_slice(&maced_pub_key).map_err(CborError::from)?;
246*9860b763SAndroid Build Coastguard Worker // Decode the public cose key from payload and check for test keys in production.
247*9860b763SAndroid Build Coastguard Worker // TODO: if implementing IRPC V2, create a helper function to check for test keys that
248*9860b763SAndroid Build Coastguard Worker // takes an indication of whether test mode is allowed
249*9860b763SAndroid Build Coastguard Worker if let Some(pub_cose_key_data) = &cose_mac0.payload {
250*9860b763SAndroid Build Coastguard Worker let pub_cose_key_cbor = read_to_value(pub_cose_key_data)?;
251*9860b763SAndroid Build Coastguard Worker let pub_cose_key =
252*9860b763SAndroid Build Coastguard Worker CoseKey::from_cbor_value(pub_cose_key_cbor.clone()).map_err(CborError::from)?;
253*9860b763SAndroid Build Coastguard Worker let params = pub_cose_key.params;
254*9860b763SAndroid Build Coastguard Worker for param in params {
255*9860b763SAndroid Build Coastguard Worker if param.0 == Label::Int(RKP_TEST_KEY_CBOR_MARKER) {
256*9860b763SAndroid Build Coastguard Worker return Err(rpc_err!(
257*9860b763SAndroid Build Coastguard Worker TestKeyInProductionRequest,
258*9860b763SAndroid Build Coastguard Worker "test key found in the request for generating CSR IRPC V3"
259*9860b763SAndroid Build Coastguard Worker ));
260*9860b763SAndroid Build Coastguard Worker }
261*9860b763SAndroid Build Coastguard Worker }
262*9860b763SAndroid Build Coastguard Worker pub_cose_keys.try_push(pub_cose_key_cbor)?;
263*9860b763SAndroid Build Coastguard Worker } else {
264*9860b763SAndroid Build Coastguard Worker return Err(rpc_err!(Failed, "no payload found in a MacedPublicKey"));
265*9860b763SAndroid Build Coastguard Worker }
266*9860b763SAndroid Build Coastguard Worker
267*9860b763SAndroid Build Coastguard Worker cose_mac0.verify_tag(&[], |expected_tag, data| -> Result<(), Error> {
268*9860b763SAndroid Build Coastguard Worker let computed_tag =
269*9860b763SAndroid Build Coastguard Worker self.dev.rpc.compute_hmac_sha256(&*self.imp.hmac, &*self.imp.hkdf, data)?;
270*9860b763SAndroid Build Coastguard Worker if self.imp.compare.eq(expected_tag, &computed_tag) {
271*9860b763SAndroid Build Coastguard Worker Ok(())
272*9860b763SAndroid Build Coastguard Worker } else {
273*9860b763SAndroid Build Coastguard Worker Err(rpc_err!(InvalidMac, "invalid tag found in a MacedPublicKey"))
274*9860b763SAndroid Build Coastguard Worker }
275*9860b763SAndroid Build Coastguard Worker })?;
276*9860b763SAndroid Build Coastguard Worker }
277*9860b763SAndroid Build Coastguard Worker // Construct the `CsrPayload`
278*9860b763SAndroid Build Coastguard Worker let rpc_device_info = self.rpc_device_info_cbor()?;
279*9860b763SAndroid Build Coastguard Worker let csr_payload = cbor!([
280*9860b763SAndroid Build Coastguard Worker Value::Integer(self.rpc_info.get_version().into()),
281*9860b763SAndroid Build Coastguard Worker Value::Text(String::from(CERT_TYPE_KEYMINT)),
282*9860b763SAndroid Build Coastguard Worker rpc_device_info,
283*9860b763SAndroid Build Coastguard Worker Value::Array(pub_cose_keys),
284*9860b763SAndroid Build Coastguard Worker ])?;
285*9860b763SAndroid Build Coastguard Worker let csr_payload_data = serialize_cbor(&csr_payload)?;
286*9860b763SAndroid Build Coastguard Worker // Construct the payload for `SignedData`
287*9860b763SAndroid Build Coastguard Worker let signed_data_payload =
288*9860b763SAndroid Build Coastguard Worker cbor!([Value::Bytes(challenge.to_vec()), Value::Bytes(csr_payload_data)])?;
289*9860b763SAndroid Build Coastguard Worker let signed_data_payload_data = serialize_cbor(&signed_data_payload)?;
290*9860b763SAndroid Build Coastguard Worker
291*9860b763SAndroid Build Coastguard Worker // Process DICE info.
292*9860b763SAndroid Build Coastguard Worker let dice_info =
293*9860b763SAndroid Build Coastguard Worker self.get_dice_info().ok_or_else(|| rpc_err!(Failed, "DICE info not available."))?;
294*9860b763SAndroid Build Coastguard Worker let uds_certs = read_to_value(&dice_info.pub_dice_artifacts.uds_certs)?;
295*9860b763SAndroid Build Coastguard Worker let dice_cert_chain = read_to_value(&dice_info.pub_dice_artifacts.dice_cert_chain)?;
296*9860b763SAndroid Build Coastguard Worker
297*9860b763SAndroid Build Coastguard Worker // Get `SignedData`
298*9860b763SAndroid Build Coastguard Worker let signed_data_cbor = read_to_value(&self.dev.rpc.sign_data_in_cose_sign1(
299*9860b763SAndroid Build Coastguard Worker &*self.imp.ec,
300*9860b763SAndroid Build Coastguard Worker &dice_info.signing_algorithm,
301*9860b763SAndroid Build Coastguard Worker &signed_data_payload_data,
302*9860b763SAndroid Build Coastguard Worker &[],
303*9860b763SAndroid Build Coastguard Worker None,
304*9860b763SAndroid Build Coastguard Worker )?)?;
305*9860b763SAndroid Build Coastguard Worker
306*9860b763SAndroid Build Coastguard Worker // Construct `AuthenticatedRequest<CsrPayload>`
307*9860b763SAndroid Build Coastguard Worker let authn_req = cbor!([
308*9860b763SAndroid Build Coastguard Worker Value::Integer(AUTH_REQ_SCHEMA_V1.into()),
309*9860b763SAndroid Build Coastguard Worker uds_certs,
310*9860b763SAndroid Build Coastguard Worker dice_cert_chain,
311*9860b763SAndroid Build Coastguard Worker signed_data_cbor,
312*9860b763SAndroid Build Coastguard Worker ])?;
313*9860b763SAndroid Build Coastguard Worker serialize_cbor(&authn_req)
314*9860b763SAndroid Build Coastguard Worker }
315*9860b763SAndroid Build Coastguard Worker }
316*9860b763SAndroid Build Coastguard Worker
317*9860b763SAndroid Build Coastguard Worker /// Helper function to construct `MacedPublicKey` in MacedPublicKey.aidl
build_maced_pub_key<F>(pub_cose_key: Vec<u8>, compute_mac: F) -> Result<Vec<u8>, Error> where F: FnOnce(&[u8]) -> Result<Vec<u8>, Error>,318*9860b763SAndroid Build Coastguard Worker fn build_maced_pub_key<F>(pub_cose_key: Vec<u8>, compute_mac: F) -> Result<Vec<u8>, Error>
319*9860b763SAndroid Build Coastguard Worker where
320*9860b763SAndroid Build Coastguard Worker F: FnOnce(&[u8]) -> Result<Vec<u8>, Error>,
321*9860b763SAndroid Build Coastguard Worker {
322*9860b763SAndroid Build Coastguard Worker let protected = HeaderBuilder::new().algorithm(iana::Algorithm::HMAC_256_256).build();
323*9860b763SAndroid Build Coastguard Worker let cose_mac_0 = CoseMac0Builder::new()
324*9860b763SAndroid Build Coastguard Worker .protected(protected)
325*9860b763SAndroid Build Coastguard Worker .payload(pub_cose_key)
326*9860b763SAndroid Build Coastguard Worker .try_create_tag(&[], compute_mac)?
327*9860b763SAndroid Build Coastguard Worker .build();
328*9860b763SAndroid Build Coastguard Worker Ok(cose_mac_0.to_vec().map_err(CborError::from)?)
329*9860b763SAndroid Build Coastguard Worker }
330*9860b763SAndroid Build Coastguard Worker
331*9860b763SAndroid Build Coastguard Worker /// Helper function to serialize a `cbor::value::Value` into bytes.
serialize_cbor(cbor_value: &Value) -> Result<Vec<u8>, Error>332*9860b763SAndroid Build Coastguard Worker pub fn serialize_cbor(cbor_value: &Value) -> Result<Vec<u8>, Error> {
333*9860b763SAndroid Build Coastguard Worker let mut buf = Vec::new();
334*9860b763SAndroid Build Coastguard Worker cbor::ser::into_writer(cbor_value, &mut buf)
335*9860b763SAndroid Build Coastguard Worker .map_err(|_e| Error::Cbor(CborError::EncodeFailed))?;
336*9860b763SAndroid Build Coastguard Worker Ok(buf)
337*9860b763SAndroid Build Coastguard Worker }
338