blob: 3f31419119116b5e7d4b446c8317da9fe7404ee9 [file] [log] [blame]
Janis Danisevskis41e67192021-11-05 09:00:19 -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 proxy dice node delegates all accesses to CDI_attest and CDI_seal to a parent
16//! node, here an implementation of android.hardware.security.dice.IDiceDevice.
17
18#![allow(dead_code)]
19
20use crate::DiceNodeImpl;
21use android_hardware_security_dice::aidl::android::hardware::security::dice::{
22 Bcc::Bcc, BccHandover::BccHandover, IDiceDevice::IDiceDevice,
23 InputValues::InputValues as BinderInputValues, Signature::Signature,
24};
25use anyhow::{Context, Result};
26use binder::public_api::Strong;
27use std::collections::HashMap;
28use std::sync::RwLock;
29
30/// The ProxyNodeHal implements a IDiceNode backend delegating crypto operations
31/// to the corresponding HAL.
32pub struct ProxyNodeHal {
33 parent: Strong<dyn IDiceDevice>,
34 demotion_db: RwLock<HashMap<BinderInputValues, Vec<BinderInputValues>>>,
35}
36
37impl ProxyNodeHal {
38 /// Creates a new proxy node with a reference to the parent service.
39 pub fn new(parent: Strong<dyn IDiceDevice>) -> Result<Self> {
40 Ok(ProxyNodeHal { parent, demotion_db: Default::default() })
41 }
42
43 fn get_effective_input_values(
44 &self,
45 client: BinderInputValues,
46 input_values: &[BinderInputValues],
47 ) -> Vec<BinderInputValues> {
48 let demotion_db = self.demotion_db.read().unwrap();
49
50 let client_arr = [client];
51
52 demotion_db
53 .get(&client_arr[0])
54 .map(|v| v.iter())
55 .unwrap_or_else(|| client_arr.iter())
56 .chain(input_values.iter())
57 .cloned()
58 .collect()
59 }
60}
61
62impl DiceNodeImpl for ProxyNodeHal {
63 fn sign(
64 &self,
65 client: BinderInputValues,
66 input_values: &[BinderInputValues],
67 message: &[u8],
68 ) -> Result<Signature> {
69 self.parent
70 .sign(&self.get_effective_input_values(client, input_values), message)
71 .context("In ProxyNodeHal::sign:")
72 }
73
74 fn get_attestation_chain(
75 &self,
76 client: BinderInputValues,
77 input_values: &[BinderInputValues],
78 ) -> Result<Bcc> {
79 self.parent
80 .getAttestationChain(&self.get_effective_input_values(client, input_values))
81 .context("In ProxyNodeHal::get_attestation_chain:")
82 }
83
84 fn derive(
85 &self,
86 client: BinderInputValues,
87 input_values: &[BinderInputValues],
88 ) -> Result<BccHandover> {
89 self.parent
90 .derive(&self.get_effective_input_values(client, input_values))
91 .context("In ProxyNodeHal::derive:")
92 }
93
94 fn demote(&self, client: BinderInputValues, input_values: &[BinderInputValues]) -> Result<()> {
95 let mut demotion_db = self.demotion_db.write().unwrap();
96
97 let client_arr = [client];
98
99 // The following statement consults demotion database which yields an optional demotion
100 // path. It then constructs an iterator over the following elements, then clones and
101 // collects them into a new vector:
102 // [ demotion path | client ], input_values
103 let new_path: Vec<BinderInputValues> = demotion_db
104 .get(&client_arr[0])
105 .map(|v| v.iter())
106 .unwrap_or_else(|| client_arr.iter())
107 .chain(input_values)
108 .cloned()
109 .collect();
110
111 let [client] = client_arr;
112 demotion_db.insert(client, new_path);
113 Ok(())
114 }
115
116 fn demote_self(&self, input_values: &[BinderInputValues]) -> Result<()> {
117 self.parent.demote(input_values).context("In ProxyNodeHal::demote_self:")
118 }
119}