blob: c3136e8a21fe0723fcc15a3644ee4c8b0312d14d [file] [log] [blame]
Andrew Sculld64ae7d2022-10-05 17:41:43 +00001// Copyright 2022, The Android Open Source Project
2//
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//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
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
15//! Logic for handling the DICE values and boot operations.
16
Alice Wang6a22be92023-02-15 10:08:36 +000017use anyhow::{anyhow, bail, Context, Error, Result};
Andrew Sculld64ae7d2022-10-05 17:41:43 +000018use byteorder::{NativeEndian, ReadBytesExt};
Alice Wangf4b8b002023-02-08 08:53:23 +000019use diced_open_dice::{
Alice Wang7e6c9352023-02-15 15:44:13 +000020 bcc_handover_parse, retry_bcc_main_flow, BccHandover, Config, DiceArtifacts, DiceMode, Hash,
21 Hidden, InputValues, OwnedDiceArtifacts,
Andrew Sculld64ae7d2022-10-05 17:41:43 +000022};
23use keystore2_crypto::ZVec;
24use libc::{c_void, mmap, munmap, MAP_FAILED, MAP_PRIVATE, PROT_READ};
25use openssl::hkdf::hkdf;
26use openssl::md::Md;
27use std::fs;
28use std::os::unix::io::AsRawFd;
29use std::path::{Path, PathBuf};
30use std::ptr::null_mut;
31use std::slice;
32
Alice Wang62f7e642023-02-10 09:55:13 +000033/// Derives a sealing key from the DICE sealing CDI.
34pub fn derive_sealing_key(
Alice Wang7e6c9352023-02-15 15:44:13 +000035 dice_artifacts: &dyn DiceArtifacts,
Alice Wang62f7e642023-02-10 09:55:13 +000036 salt: &[u8],
37 info: &[u8],
Alice Wang7e6c9352023-02-15 15:44:13 +000038 key: &mut [u8],
39) -> Result<()> {
40 Ok(hkdf(key, Md::sha256(), dice_artifacts.cdi_seal(), salt, info)?)
Shikha Panwar566c9672022-11-15 14:39:58 +000041}
42
Andrew Sculld64ae7d2022-10-05 17:41:43 +000043/// Artifacts that are mapped into the process address space from the driver.
44pub enum DiceDriver<'a> {
45 Real {
46 driver_path: PathBuf,
47 mmap_addr: *mut c_void,
48 mmap_size: usize,
Alice Wang6a22be92023-02-15 10:08:36 +000049 bcc_handover: BccHandover<'a>,
Andrew Sculld64ae7d2022-10-05 17:41:43 +000050 },
Alice Wang62f7e642023-02-10 09:55:13 +000051 Fake(OwnedDiceArtifacts),
Andrew Sculld64ae7d2022-10-05 17:41:43 +000052}
53
54impl DiceDriver<'_> {
Alice Wang7e6c9352023-02-15 15:44:13 +000055 fn dice_artifacts(&self) -> &dyn DiceArtifacts {
56 match self {
57 Self::Real { bcc_handover, .. } => bcc_handover,
58 Self::Fake(owned_dice_artifacts) => owned_dice_artifacts,
59 }
60 }
61
Andrew Sculld64ae7d2022-10-05 17:41:43 +000062 pub fn new(driver_path: &Path) -> Result<Self> {
63 if driver_path.exists() {
64 log::info!("Using DICE values from driver");
65 } else if super::is_strict_boot() {
66 bail!("Strict boot requires DICE value from driver but none were found");
67 } else {
68 log::warn!("Using sample DICE values");
Alice Wangf4b8b002023-02-08 08:53:23 +000069 let dice_artifacts = diced_sample_inputs::make_sample_bcc_and_cdis()
Andrew Sculld64ae7d2022-10-05 17:41:43 +000070 .expect("Failed to create sample dice artifacts.");
Alice Wang62f7e642023-02-10 09:55:13 +000071 return Ok(Self::Fake(dice_artifacts));
Andrew Sculld64ae7d2022-10-05 17:41:43 +000072 };
73
74 let mut file = fs::File::open(driver_path)
75 .map_err(|error| Error::new(error).context("Opening driver"))?;
76 let mmap_size =
77 file.read_u64::<NativeEndian>()
78 .map_err(|error| Error::new(error).context("Reading driver"))? as usize;
79 // It's safe to map the driver as the service will only create a single
80 // mapping per process.
81 let mmap_addr = unsafe {
82 let fd = file.as_raw_fd();
83 mmap(null_mut(), mmap_size, PROT_READ, MAP_PRIVATE, fd, 0)
84 };
85 if mmap_addr == MAP_FAILED {
86 bail!("Failed to mmap {:?}", driver_path);
87 }
88 // The slice is created for the region of memory that was just
89 // successfully mapped into the process address space so it will be
90 // accessible and not referenced from anywhere else.
91 let mmap_buf =
92 unsafe { slice::from_raw_parts((mmap_addr as *const u8).as_ref().unwrap(), mmap_size) };
Alice Wang6a22be92023-02-15 10:08:36 +000093 let bcc_handover =
94 bcc_handover_parse(mmap_buf).map_err(|_| anyhow!("Failed to parse Bcc Handover"))?;
Andrew Sculld64ae7d2022-10-05 17:41:43 +000095 Ok(Self::Real {
96 driver_path: driver_path.to_path_buf(),
97 mmap_addr,
98 mmap_size,
Alice Wang6a22be92023-02-15 10:08:36 +000099 bcc_handover,
Andrew Sculld64ae7d2022-10-05 17:41:43 +0000100 })
101 }
102
Alice Wang7e6c9352023-02-15 15:44:13 +0000103 /// Derives a sealing key of `key_length` bytes from the DICE sealing CDI.
104 pub fn get_sealing_key(&self, identifier: &[u8], key_length: usize) -> Result<ZVec> {
Andrew Sculld64ae7d2022-10-05 17:41:43 +0000105 // Deterministically derive a key to use for sealing data, rather than using the CDI
106 // directly, so we have the chance to rotate the key if needed. A salt isn't needed as the
107 // input key material is already cryptographically strong.
Alice Wang7e6c9352023-02-15 15:44:13 +0000108 let mut key = ZVec::new(key_length)?;
Andrew Sculld64ae7d2022-10-05 17:41:43 +0000109 let salt = &[];
Alice Wang7e6c9352023-02-15 15:44:13 +0000110 derive_sealing_key(self.dice_artifacts(), salt, identifier, &mut key)?;
111 Ok(key)
Andrew Sculld64ae7d2022-10-05 17:41:43 +0000112 }
113
114 pub fn derive(
115 self,
Alice Wang5aeed332023-02-02 09:42:21 +0000116 code_hash: Hash,
Andrew Sculld64ae7d2022-10-05 17:41:43 +0000117 config_desc: &[u8],
Alice Wang5aeed332023-02-02 09:42:21 +0000118 authority_hash: Hash,
Andrew Sculld64ae7d2022-10-05 17:41:43 +0000119 debug: bool,
Alice Wang5aeed332023-02-02 09:42:21 +0000120 hidden: Hidden,
Alice Wang62f7e642023-02-10 09:55:13 +0000121 ) -> Result<OwnedDiceArtifacts> {
Alice Wanga7773662023-02-03 09:37:17 +0000122 let input_values = InputValues::new(
Andrew Sculld64ae7d2022-10-05 17:41:43 +0000123 code_hash,
124 Config::Descriptor(config_desc),
125 authority_hash,
Alice Wang31226132023-01-31 12:44:39 +0000126 if debug { DiceMode::kDiceModeDebug } else { DiceMode::kDiceModeNormal },
Andrew Sculld64ae7d2022-10-05 17:41:43 +0000127 hidden,
128 );
Alice Wang7e6c9352023-02-15 15:44:13 +0000129 let current_dice_artifacts = self.dice_artifacts();
130 let next_dice_artifacts = retry_bcc_main_flow(
131 current_dice_artifacts.cdi_attest(),
132 current_dice_artifacts.cdi_seal(),
133 current_dice_artifacts.bcc().ok_or_else(|| anyhow!("bcc is none"))?,
134 &input_values,
135 )
136 .context("DICE derive from driver")?;
Andrew Sculld64ae7d2022-10-05 17:41:43 +0000137 if let Self::Real { driver_path, .. } = &self {
138 // Writing to the device wipes the artifacts. The string is ignored by the driver but
139 // included for documentation.
140 fs::write(driver_path, "wipe")
141 .map_err(|err| Error::new(err).context("Wiping driver"))?;
142 }
Alice Wang7e6c9352023-02-15 15:44:13 +0000143 Ok(next_dice_artifacts)
Andrew Sculld64ae7d2022-10-05 17:41:43 +0000144 }
145}
146
147impl Drop for DiceDriver<'_> {
148 fn drop(&mut self) {
149 if let &mut Self::Real { mmap_addr, mmap_size, .. } = self {
150 // All references to the mapped region have the same lifetime as self. Since self is
151 // being dropped, so are all the references to the mapped region meaning its safe to
152 // unmap.
153 let ret = unsafe { munmap(mmap_addr, mmap_size) };
154 if ret != 0 {
155 log::warn!("Failed to munmap ({})", ret);
156 }
157 }
158 }
159}