blob: 0bd5d0dc297147f82a91edc20f52f871389d57cc [file] [log] [blame]
Janis Danisevskisc51dff82021-10-20 09:51:16 -07001// Copyright 2021, 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//! A resident dice node keeps CDI_attest and CDI_seal memory resident and can serve
16//! its clients directly by performing all crypto operations including derivations and
17//! certificate generation itself.
18
19use crate::DiceNodeImpl;
20use android_hardware_security_dice::aidl::android::hardware::security::dice::{
21 Bcc::Bcc, BccHandover::BccHandover, InputValues::InputValues as BinderInputValues,
22 Signature::Signature,
23};
24use anyhow::{Context, Result};
25use dice::{ContextImpl, OpenDiceCborContext};
26use diced_open_dice_cbor as dice;
Alice Wang93e6e372023-02-02 14:36:17 +000027use diced_utils::{self as utils, ResidentArtifacts};
Janis Danisevskisc51dff82021-10-20 09:51:16 -070028use std::collections::HashMap;
29use std::convert::TryInto;
30use std::sync::RwLock;
31
32/// The ResidentNode implements a IDiceNode backend with memory resident DICE secrets.
33pub struct ResidentNode {
34 artifacts: RwLock<ResidentArtifacts>,
35 demotion_db: RwLock<HashMap<BinderInputValues, Vec<BinderInputValues>>>,
36}
37
38impl ResidentNode {
39 /// Creates a new Resident node with the given dice secrets and certificate chain.
40 pub fn new(
41 cdi_attest: &[u8; dice::CDI_SIZE],
42 cdi_seal: &[u8; dice::CDI_SIZE],
43 bcc: Vec<u8>,
44 ) -> Result<Self> {
45 Ok(ResidentNode {
46 artifacts: RwLock::new(
47 ResidentArtifacts::new(cdi_attest, cdi_seal, &bcc)
48 .context("In ResidentNode::new: Trying to initialize ResidentArtifacts")?,
49 ),
50 demotion_db: Default::default(),
51 })
52 }
53
54 fn get_effective_artifacts(
55 &self,
56 client: BinderInputValues,
57 input_values: &[BinderInputValues],
58 ) -> Result<ResidentArtifacts> {
59 let artifacts = self.artifacts.read().unwrap().try_clone()?;
60 let demotion_db = self.demotion_db.read().unwrap();
61
62 let client_arr = [client];
63
Alice Wang93e6e372023-02-02 14:36:17 +000064 let input_values = demotion_db
Janis Danisevskisc51dff82021-10-20 09:51:16 -070065 .get(&client_arr[0])
66 .map(|v| v.iter())
67 .unwrap_or_else(|| client_arr.iter())
Alice Wang93e6e372023-02-02 14:36:17 +000068 .chain(input_values.iter());
69 artifacts.execute_steps(input_values).context("In get_effective_artifacts:")
Janis Danisevskisc51dff82021-10-20 09:51:16 -070070 }
71}
72
73impl DiceNodeImpl for ResidentNode {
74 fn sign(
75 &self,
76 client: BinderInputValues,
77 input_values: &[BinderInputValues],
78 message: &[u8],
79 ) -> Result<Signature> {
80 let (cdi_attest, _, _) = self
81 .get_effective_artifacts(client, input_values)
82 .context("In ResidentNode::sign: Failed to get effective_artifacts.")?
83 .into_tuple();
84 let mut dice = OpenDiceCborContext::new();
85 let seed = dice
86 .derive_cdi_private_key_seed(cdi_attest[..].try_into().with_context(|| {
87 format!(
88 "In ResidentNode::sign: Failed to convert cdi_attest (length: {}).",
89 cdi_attest.len()
90 )
91 })?)
92 .context("In ResidentNode::sign: Failed to derive seed from cdi_attest.")?;
93 let (_public_key, private_key) = dice
94 .keypair_from_seed(seed[..].try_into().with_context(|| {
95 format!("In ResidentNode::sign: Failed to convert seed (length: {}).", seed.len())
96 })?)
97 .context("In ResidentNode::sign: Failed to derive keypair from seed.")?;
98 Ok(Signature {
99 data: dice
100 .sign(
101 message,
102 private_key[..].try_into().with_context(|| {
103 format!(
104 "In ResidentNode::sign: Failed to convert private_key (length: {}).",
105 private_key.len()
106 )
107 })?,
108 )
109 .context("In ResidentNode::sign: Failed to sign.")?,
110 })
111 }
112
113 fn get_attestation_chain(
114 &self,
115 client: BinderInputValues,
116 input_values: &[BinderInputValues],
117 ) -> Result<Bcc> {
118 let (_, _, bcc) = self
119 .get_effective_artifacts(client, input_values)
120 .context("In ResidentNode::get_attestation_chain: Failed to get effective_artifacts.")?
121 .into_tuple();
122
123 Ok(Bcc { data: bcc })
124 }
125
126 fn derive(
127 &self,
128 client: BinderInputValues,
129 input_values: &[BinderInputValues],
130 ) -> Result<BccHandover> {
131 let (cdi_attest, cdi_seal, bcc) =
132 self.get_effective_artifacts(client, input_values)?.into_tuple();
133
134 utils::make_bcc_handover(
135 &cdi_attest[..]
136 .try_into()
137 .context("In ResidentNode::derive: Trying to convert cdi_attest to sized array.")?,
138 &cdi_seal[..]
139 .try_into()
140 .context("In ResidentNode::derive: Trying to convert cdi_attest to sized array.")?,
141 &bcc,
142 )
143 .context("In ResidentNode::derive: Trying to format bcc handover.")
144 }
145
146 fn demote(&self, client: BinderInputValues, input_values: &[BinderInputValues]) -> Result<()> {
147 let mut demotion_db = self.demotion_db.write().unwrap();
148
149 let client_arr = [client];
150
151 // The following statement consults demotion database which yields an optional demotion
152 // path. It then constructs an iterator over the following elements, then clones and
153 // collects them into a new vector:
154 // [ demotion path | client ], input_values
155 let new_path: Vec<BinderInputValues> = demotion_db
156 .get(&client_arr[0])
157 .map(|v| v.iter())
158 .unwrap_or_else(|| client_arr.iter())
159 .chain(input_values)
160 .cloned()
161 .collect();
162
163 let [client] = client_arr;
164 demotion_db.insert(client, new_path);
165 Ok(())
166 }
167
168 fn demote_self(&self, input_values: &[BinderInputValues]) -> Result<()> {
169 let mut artifacts = self.artifacts.write().unwrap();
170
Janis Danisevskisc51dff82021-10-20 09:51:16 -0700171 *artifacts = artifacts
172 .try_clone()
173 .context("In ResidentNode::demote_self: Failed to clone resident artifacts")?
Alice Wang93e6e372023-02-02 14:36:17 +0000174 .execute_steps(input_values)
Janis Danisevskisc51dff82021-10-20 09:51:16 -0700175 .context("In ResidentNode::demote_self:")?;
176 Ok(())
177 }
178}