blob: 4d6a7bc881d7fb47e97546167110d5b9e5f87ea1 [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 {
Janis Danisevskisc51dff82021-10-20 09:51:16 -070039 fn get_effective_artifacts(
40 &self,
41 client: BinderInputValues,
42 input_values: &[BinderInputValues],
43 ) -> Result<ResidentArtifacts> {
44 let artifacts = self.artifacts.read().unwrap().try_clone()?;
45 let demotion_db = self.demotion_db.read().unwrap();
46
47 let client_arr = [client];
48
Alice Wang93e6e372023-02-02 14:36:17 +000049 let input_values = demotion_db
Janis Danisevskisc51dff82021-10-20 09:51:16 -070050 .get(&client_arr[0])
51 .map(|v| v.iter())
52 .unwrap_or_else(|| client_arr.iter())
Alice Wang93e6e372023-02-02 14:36:17 +000053 .chain(input_values.iter());
54 artifacts.execute_steps(input_values).context("In get_effective_artifacts:")
Janis Danisevskisc51dff82021-10-20 09:51:16 -070055 }
56}
57
58impl DiceNodeImpl for ResidentNode {
59 fn sign(
60 &self,
61 client: BinderInputValues,
62 input_values: &[BinderInputValues],
63 message: &[u8],
64 ) -> Result<Signature> {
65 let (cdi_attest, _, _) = self
66 .get_effective_artifacts(client, input_values)
67 .context("In ResidentNode::sign: Failed to get effective_artifacts.")?
68 .into_tuple();
69 let mut dice = OpenDiceCborContext::new();
Alice Wang7cc59562023-02-08 13:17:10 +000070 let seed =
71 dice::derive_cdi_private_key_seed(cdi_attest[..].try_into().with_context(|| {
Janis Danisevskisc51dff82021-10-20 09:51:16 -070072 format!(
73 "In ResidentNode::sign: Failed to convert cdi_attest (length: {}).",
74 cdi_attest.len()
75 )
76 })?)
77 .context("In ResidentNode::sign: Failed to derive seed from cdi_attest.")?;
78 let (_public_key, private_key) = dice
79 .keypair_from_seed(seed[..].try_into().with_context(|| {
80 format!("In ResidentNode::sign: Failed to convert seed (length: {}).", seed.len())
81 })?)
82 .context("In ResidentNode::sign: Failed to derive keypair from seed.")?;
83 Ok(Signature {
84 data: dice
85 .sign(
86 message,
87 private_key[..].try_into().with_context(|| {
88 format!(
89 "In ResidentNode::sign: Failed to convert private_key (length: {}).",
90 private_key.len()
91 )
92 })?,
93 )
94 .context("In ResidentNode::sign: Failed to sign.")?,
95 })
96 }
97
98 fn get_attestation_chain(
99 &self,
100 client: BinderInputValues,
101 input_values: &[BinderInputValues],
102 ) -> Result<Bcc> {
103 let (_, _, bcc) = self
104 .get_effective_artifacts(client, input_values)
105 .context("In ResidentNode::get_attestation_chain: Failed to get effective_artifacts.")?
106 .into_tuple();
107
108 Ok(Bcc { data: bcc })
109 }
110
111 fn derive(
112 &self,
113 client: BinderInputValues,
114 input_values: &[BinderInputValues],
115 ) -> Result<BccHandover> {
116 let (cdi_attest, cdi_seal, bcc) =
117 self.get_effective_artifacts(client, input_values)?.into_tuple();
118
119 utils::make_bcc_handover(
120 &cdi_attest[..]
121 .try_into()
122 .context("In ResidentNode::derive: Trying to convert cdi_attest to sized array.")?,
123 &cdi_seal[..]
124 .try_into()
125 .context("In ResidentNode::derive: Trying to convert cdi_attest to sized array.")?,
126 &bcc,
127 )
128 .context("In ResidentNode::derive: Trying to format bcc handover.")
129 }
130
131 fn demote(&self, client: BinderInputValues, input_values: &[BinderInputValues]) -> Result<()> {
132 let mut demotion_db = self.demotion_db.write().unwrap();
133
134 let client_arr = [client];
135
136 // The following statement consults demotion database which yields an optional demotion
137 // path. It then constructs an iterator over the following elements, then clones and
138 // collects them into a new vector:
139 // [ demotion path | client ], input_values
140 let new_path: Vec<BinderInputValues> = demotion_db
141 .get(&client_arr[0])
142 .map(|v| v.iter())
143 .unwrap_or_else(|| client_arr.iter())
144 .chain(input_values)
145 .cloned()
146 .collect();
147
148 let [client] = client_arr;
149 demotion_db.insert(client, new_path);
150 Ok(())
151 }
152
153 fn demote_self(&self, input_values: &[BinderInputValues]) -> Result<()> {
154 let mut artifacts = self.artifacts.write().unwrap();
155
Janis Danisevskisc51dff82021-10-20 09:51:16 -0700156 *artifacts = artifacts
157 .try_clone()
158 .context("In ResidentNode::demote_self: Failed to clone resident artifacts")?
Alice Wang93e6e372023-02-02 14:36:17 +0000159 .execute_steps(input_values)
Janis Danisevskisc51dff82021-10-20 09:51:16 -0700160 .context("In ResidentNode::demote_self:")?;
161 Ok(())
162 }
163}