blob: a5764164066de0ccbd59422444acc5c14e5957c1 [file] [log] [blame]
Alan Stokes1125e012023-10-13 12:31:10 +01001// Copyright 2023 The Android Open Source Project
Andrew Sculld64ae7d2022-10-05 17:41:43 +00002//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
Alan Stokes1125e012023-10-13 12:31:10 +01007// http://www.apache.org/licenses/LICENSE-2.0
Andrew Sculld64ae7d2022-10-05 17:41:43 +00008//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
Alan Stokes1125e012023-10-13 12:31:10 +010015use crate::dice_driver::DiceDriver;
16use crate::{is_debuggable, MicrodroidData};
17use anyhow::{bail, Context, Result};
Alice Wanga04890b2023-03-01 11:45:09 +000018use ciborium::{cbor, ser};
Alan Stokes1125e012023-10-13 12:31:10 +010019use diced_open_dice::OwnedDiceArtifacts;
Alice Wang285a3d22023-03-01 11:36:29 +000020use microdroid_metadata::PayloadMetadata;
Alan Stokes1125e012023-10-13 12:31:10 +010021use openssl::sha::Sha512;
Andrew Sculld64ae7d2022-10-05 17:41:43 +000022
Alan Stokes1125e012023-10-13 12:31:10 +010023/// Perform an open DICE derivation for the payload.
24pub fn dice_derivation(
25 dice: DiceDriver,
26 verified_data: &MicrodroidData,
27 payload_metadata: &PayloadMetadata,
28) -> Result<OwnedDiceArtifacts> {
29 // Calculate compound digests of code and authorities
30 let mut code_hash_ctx = Sha512::new();
31 let mut authority_hash_ctx = Sha512::new();
32 code_hash_ctx.update(verified_data.apk_data.root_hash.as_ref());
33 authority_hash_ctx.update(verified_data.apk_data.pubkey.as_ref());
34 for extra_apk in &verified_data.extra_apks_data {
35 code_hash_ctx.update(extra_apk.root_hash.as_ref());
36 authority_hash_ctx.update(extra_apk.pubkey.as_ref());
Alice Wang7e6c9352023-02-15 15:44:13 +000037 }
Alan Stokes1125e012023-10-13 12:31:10 +010038 for apex in &verified_data.apex_data {
39 code_hash_ctx.update(apex.root_digest.as_ref());
40 authority_hash_ctx.update(apex.public_key.as_ref());
Andrew Sculld64ae7d2022-10-05 17:41:43 +000041 }
Alan Stokes1125e012023-10-13 12:31:10 +010042 let code_hash = code_hash_ctx.finish();
43 let authority_hash = authority_hash_ctx.finish();
Andrew Sculld64ae7d2022-10-05 17:41:43 +000044
Alan Stokes1125e012023-10-13 12:31:10 +010045 let config_descriptor = format_payload_config_descriptor(payload_metadata)?;
Andrew Sculld64ae7d2022-10-05 17:41:43 +000046
Alan Stokes1125e012023-10-13 12:31:10 +010047 // Check debuggability, conservatively assuming it is debuggable
48 let debuggable = is_debuggable()?;
Andrew Sculld64ae7d2022-10-05 17:41:43 +000049
Alan Stokes1125e012023-10-13 12:31:10 +010050 // Send the details to diced
51 let hidden = verified_data.salt.clone().try_into().unwrap();
52 dice.derive(code_hash, &config_descriptor, authority_hash, debuggable, hidden)
Andrew Sculld64ae7d2022-10-05 17:41:43 +000053}
Alice Wang285a3d22023-03-01 11:36:29 +000054
55/// Returns a configuration descriptor of the given payload following the BCC's specification:
56/// https://cs.android.com/android/platform/superproject/+/master:hardware/interfaces/security/rkp/aidl/android/hardware/security/keymint/ProtectedData.aidl
57/// {
58/// -70002: "Microdroid payload",
Alan Stokes331a3a12023-08-04 11:31:51 +010059/// ? -71000: tstr ; payload_config_path
Alice Wang285a3d22023-03-01 11:36:29 +000060/// ? -71001: PayloadConfig
61/// }
62/// PayloadConfig = {
Alan Stokes331a3a12023-08-04 11:31:51 +010063/// 1: tstr ; payload_binary_name
Alice Wang285a3d22023-03-01 11:36:29 +000064/// }
Alan Stokes1125e012023-10-13 12:31:10 +010065fn format_payload_config_descriptor(payload: &PayloadMetadata) -> Result<Vec<u8>> {
Alice Wanga04890b2023-03-01 11:45:09 +000066 const MICRODROID_PAYLOAD_COMPONENT_NAME: &str = "Microdroid payload";
Alice Wang285a3d22023-03-01 11:36:29 +000067
Ludovic Barman93ee3082023-06-20 12:18:43 +000068 let config_descriptor_cbor_value = match payload {
69 PayloadMetadata::ConfigPath(payload_config_path) => cbor!({
Alice Wanga04890b2023-03-01 11:45:09 +000070 -70002 => MICRODROID_PAYLOAD_COMPONENT_NAME,
71 -71000 => payload_config_path
72 }),
Ludovic Barman93ee3082023-06-20 12:18:43 +000073 PayloadMetadata::Config(payload_config) => cbor!({
Alice Wanga04890b2023-03-01 11:45:09 +000074 -70002 => MICRODROID_PAYLOAD_COMPONENT_NAME,
75 -71001 => {1 => payload_config.payload_binary_name}
76 }),
Ludovic Barman93ee3082023-06-20 12:18:43 +000077 _ => bail!("Failed to match the payload against a config type: {:?}", payload),
Alice Wang285a3d22023-03-01 11:36:29 +000078 }
Alice Wanga04890b2023-03-01 11:45:09 +000079 .context("Failed to build a CBOR Value from payload metadata")?;
80 let mut config_descriptor = Vec::new();
Ludovic Barman93ee3082023-06-20 12:18:43 +000081
Alice Wanga04890b2023-03-01 11:45:09 +000082 ser::into_writer(&config_descriptor_cbor_value, &mut config_descriptor)?;
Alice Wang285a3d22023-03-01 11:36:29 +000083 Ok(config_descriptor)
84}
85
Alice Wang285a3d22023-03-01 11:36:29 +000086#[cfg(test)]
87mod tests {
88 use super::*;
89 use microdroid_metadata::PayloadConfig;
90
91 #[test]
92 fn payload_metadata_with_path_formats_correctly() -> Result<()> {
Ludovic Barman93ee3082023-06-20 12:18:43 +000093 let payload_metadata = PayloadMetadata::ConfigPath("/config_path".to_string());
Alice Wang285a3d22023-03-01 11:36:29 +000094 let config_descriptor = format_payload_config_descriptor(&payload_metadata)?;
95 static EXPECTED_CONFIG_DESCRIPTOR: &[u8] = &[
96 0xa2, 0x3a, 0x00, 0x01, 0x11, 0x71, 0x72, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x64, 0x72,
97 0x6f, 0x69, 0x64, 0x20, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x3a, 0x00, 0x01,
98 0x15, 0x57, 0x6c, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x61, 0x74,
99 0x68,
100 ];
101 assert_eq!(EXPECTED_CONFIG_DESCRIPTOR, &config_descriptor);
102 Ok(())
103 }
104
105 #[test]
106 fn payload_metadata_with_config_formats_correctly() -> Result<()> {
107 let payload_config = PayloadConfig {
108 payload_binary_name: "payload_binary".to_string(),
109 ..Default::default()
110 };
Ludovic Barman93ee3082023-06-20 12:18:43 +0000111 let payload_metadata = PayloadMetadata::Config(payload_config);
Alice Wang285a3d22023-03-01 11:36:29 +0000112 let config_descriptor = format_payload_config_descriptor(&payload_metadata)?;
113 static EXPECTED_CONFIG_DESCRIPTOR: &[u8] = &[
114 0xa2, 0x3a, 0x00, 0x01, 0x11, 0x71, 0x72, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x64, 0x72,
115 0x6f, 0x69, 0x64, 0x20, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x3a, 0x00, 0x01,
116 0x15, 0x58, 0xa1, 0x01, 0x6e, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x62,
117 0x69, 0x6e, 0x61, 0x72, 0x79,
118 ];
119 assert_eq!(EXPECTED_CONFIG_DESCRIPTOR, &config_descriptor);
120 Ok(())
121 }
122}