blob: fd221985a7dbeeffc1650c261976679d00232a44 [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 Wang6a22be92023-02-15 10:08:36 +000020 bcc_handover_parse, retry_bcc_main_flow, BccHandover, Cdi, Config, DiceMode, Hash, Hidden,
21 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(
35 cdi_seal: &Cdi,
36 salt: &[u8],
37 info: &[u8],
38 keysize: usize,
39) -> Result<ZVec> {
40 let mut key = ZVec::new(keysize)?;
41 hkdf(&mut key, Md::sha256(), cdi_seal, salt, info)?;
42 Ok(key)
Shikha Panwar566c9672022-11-15 14:39:58 +000043}
44
Andrew Sculld64ae7d2022-10-05 17:41:43 +000045/// Artifacts that are mapped into the process address space from the driver.
46pub enum DiceDriver<'a> {
47 Real {
48 driver_path: PathBuf,
49 mmap_addr: *mut c_void,
50 mmap_size: usize,
Alice Wang6a22be92023-02-15 10:08:36 +000051 bcc_handover: BccHandover<'a>,
Andrew Sculld64ae7d2022-10-05 17:41:43 +000052 },
Alice Wang62f7e642023-02-10 09:55:13 +000053 Fake(OwnedDiceArtifacts),
Andrew Sculld64ae7d2022-10-05 17:41:43 +000054}
55
56impl DiceDriver<'_> {
57 pub fn new(driver_path: &Path) -> Result<Self> {
58 if driver_path.exists() {
59 log::info!("Using DICE values from driver");
60 } else if super::is_strict_boot() {
61 bail!("Strict boot requires DICE value from driver but none were found");
62 } else {
63 log::warn!("Using sample DICE values");
Alice Wangf4b8b002023-02-08 08:53:23 +000064 let dice_artifacts = diced_sample_inputs::make_sample_bcc_and_cdis()
Andrew Sculld64ae7d2022-10-05 17:41:43 +000065 .expect("Failed to create sample dice artifacts.");
Alice Wang62f7e642023-02-10 09:55:13 +000066 return Ok(Self::Fake(dice_artifacts));
Andrew Sculld64ae7d2022-10-05 17:41:43 +000067 };
68
69 let mut file = fs::File::open(driver_path)
70 .map_err(|error| Error::new(error).context("Opening driver"))?;
71 let mmap_size =
72 file.read_u64::<NativeEndian>()
73 .map_err(|error| Error::new(error).context("Reading driver"))? as usize;
74 // It's safe to map the driver as the service will only create a single
75 // mapping per process.
76 let mmap_addr = unsafe {
77 let fd = file.as_raw_fd();
78 mmap(null_mut(), mmap_size, PROT_READ, MAP_PRIVATE, fd, 0)
79 };
80 if mmap_addr == MAP_FAILED {
81 bail!("Failed to mmap {:?}", driver_path);
82 }
83 // The slice is created for the region of memory that was just
84 // successfully mapped into the process address space so it will be
85 // accessible and not referenced from anywhere else.
86 let mmap_buf =
87 unsafe { slice::from_raw_parts((mmap_addr as *const u8).as_ref().unwrap(), mmap_size) };
Alice Wang6a22be92023-02-15 10:08:36 +000088 let bcc_handover =
89 bcc_handover_parse(mmap_buf).map_err(|_| anyhow!("Failed to parse Bcc Handover"))?;
Andrew Sculld64ae7d2022-10-05 17:41:43 +000090 Ok(Self::Real {
91 driver_path: driver_path.to_path_buf(),
92 mmap_addr,
93 mmap_size,
Alice Wang6a22be92023-02-15 10:08:36 +000094 bcc_handover,
Andrew Sculld64ae7d2022-10-05 17:41:43 +000095 })
96 }
97
98 pub fn get_sealing_key(&self, identifier: &[u8]) -> Result<ZVec> {
99 // Deterministically derive a key to use for sealing data, rather than using the CDI
100 // directly, so we have the chance to rotate the key if needed. A salt isn't needed as the
101 // input key material is already cryptographically strong.
102 let cdi_seal = match self {
Alice Wang6a22be92023-02-15 10:08:36 +0000103 Self::Real { bcc_handover, .. } => bcc_handover.cdi_seal,
Alice Wang62f7e642023-02-10 09:55:13 +0000104 Self::Fake(fake) => &fake.cdi_values.cdi_seal,
Andrew Sculld64ae7d2022-10-05 17:41:43 +0000105 };
106 let salt = &[];
Alice Wang62f7e642023-02-10 09:55:13 +0000107 derive_sealing_key(cdi_seal, salt, identifier, 32)
Andrew Sculld64ae7d2022-10-05 17:41:43 +0000108 }
109
110 pub fn derive(
111 self,
Alice Wang5aeed332023-02-02 09:42:21 +0000112 code_hash: Hash,
Andrew Sculld64ae7d2022-10-05 17:41:43 +0000113 config_desc: &[u8],
Alice Wang5aeed332023-02-02 09:42:21 +0000114 authority_hash: Hash,
Andrew Sculld64ae7d2022-10-05 17:41:43 +0000115 debug: bool,
Alice Wang5aeed332023-02-02 09:42:21 +0000116 hidden: Hidden,
Alice Wang62f7e642023-02-10 09:55:13 +0000117 ) -> Result<OwnedDiceArtifacts> {
Alice Wanga7773662023-02-03 09:37:17 +0000118 let input_values = InputValues::new(
Andrew Sculld64ae7d2022-10-05 17:41:43 +0000119 code_hash,
120 Config::Descriptor(config_desc),
121 authority_hash,
Alice Wang31226132023-01-31 12:44:39 +0000122 if debug { DiceMode::kDiceModeDebug } else { DiceMode::kDiceModeNormal },
Andrew Sculld64ae7d2022-10-05 17:41:43 +0000123 hidden,
124 );
125 let (cdi_attest, cdi_seal, bcc) = match &self {
Alice Wang6a22be92023-02-15 10:08:36 +0000126 Self::Real { bcc_handover, .. } => (
127 bcc_handover.cdi_attest,
128 bcc_handover.cdi_seal,
129 bcc_handover.bcc.ok_or_else(|| anyhow!("bcc is none"))?,
130 ),
Alice Wang62f7e642023-02-10 09:55:13 +0000131 Self::Fake(fake) => {
132 (&fake.cdi_values.cdi_attest, &fake.cdi_values.cdi_seal, fake.bcc.as_slice())
133 }
Andrew Sculld64ae7d2022-10-05 17:41:43 +0000134 };
Alice Wangf4b8b002023-02-08 08:53:23 +0000135 let dice_artifacts = retry_bcc_main_flow(cdi_attest, cdi_seal, bcc, &input_values)
Andrew Sculld64ae7d2022-10-05 17:41:43 +0000136 .context("DICE derive from driver")?;
137 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 Wang62f7e642023-02-10 09:55:13 +0000143 Ok(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}