blob: ac9484ab35a1f5fe80f458223df175ce64b6b4d4 [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//! Implement the android.security.dice.IDiceNode service.
16
17mod error;
18mod resident_node;
19
20pub use crate::resident_node::ResidentNode;
21use android_hardware_security_dice::aidl::android::hardware::security::dice::{
22 Bcc::Bcc, BccHandover::BccHandover, Config::Config as BinderConfig,
23 InputValues::InputValues as BinderInputValues, Mode::Mode, Signature::Signature,
24};
25use android_security_dice::aidl::android::security::dice::{
26 IDiceNode::BnDiceNode, IDiceNode::IDiceNode, ResponseCode::ResponseCode,
27};
28use anyhow::{Context, Result};
29use binder::{public_api::Result as BinderResult, BinderFeatures, Strong, ThreadState};
30pub use diced_open_dice_cbor as dice;
31use error::{map_or_log_err, Error};
32use libc::uid_t;
33use std::sync::Arc;
34
35/// A DiceNode backend implementation.
36/// All functions except demote_self derive effective dice artifacts staring from
37/// this node and iterating through `{ [client | demotion path], input_values }`
38/// in ascending order.
39pub trait DiceNodeImpl {
40 /// Signs the message using the effective dice artifacts and Ed25519Pure.
41 fn sign(
42 &self,
43 client: BinderInputValues,
44 input_values: &[BinderInputValues],
45 message: &[u8],
46 ) -> Result<Signature>;
47 /// Returns the effective attestation chain.
48 fn get_attestation_chain(
49 &self,
50 client: BinderInputValues,
51 input_values: &[BinderInputValues],
52 ) -> Result<Bcc>;
53 /// Returns the effective dice artifacts.
54 fn derive(
55 &self,
56 client: BinderInputValues,
57 input_values: &[BinderInputValues],
58 ) -> Result<BccHandover>;
59 /// Adds [ `client` | `input_values` ] to the demotion path of the given client.
60 /// This changes the effective dice artifacts for all subsequent API calls of the
61 /// given client.
62 fn demote(&self, client: BinderInputValues, input_values: &[BinderInputValues]) -> Result<()>;
63 /// This demotes the implementation itself. I.e. a resident node would replace its resident
64 /// with the effective artifacts derived using `input_values`. A proxy node would
65 /// simply call `demote` on its parent node. This is not reversible and changes
66 /// the effective dice artifacts of all clients.
67 fn demote_self(&self, input_values: &[BinderInputValues]) -> Result<()>;
68}
69
70/// Wraps a DiceNodeImpl and implements the actual IDiceNode AIDL API.
71pub struct DiceNode {
72 node_impl: Arc<dyn DiceNodeImpl + Sync + Send>,
73}
74
75fn client_input_values(uid: uid_t) -> Result<BinderInputValues> {
76 Ok(BinderInputValues {
77 codeHash: vec![0; dice::HASH_SIZE],
78 config: BinderConfig {
79 desc: dice::bcc::format_config_descriptor(Some(&format!("{}", uid)), None, true)
80 .context("In client_input_values: failed to format config descriptor")?,
81 },
82 authorityHash: vec![0; dice::HASH_SIZE],
83 authorityDescriptor: None,
84 hidden: vec![0; dice::HIDDEN_SIZE],
85 mode: Mode::NORMAL,
86 })
87}
88
89impl DiceNode {
90 /// Constructs an instance of DiceNode, wraps it with a BnDiceNode object and
91 /// returns a strong pointer to the binder. The result can be used to register
92 /// the service with service manager.
93 pub fn new_as_binder(
94 node_impl: Arc<dyn DiceNodeImpl + Sync + Send>,
95 ) -> Result<Strong<dyn IDiceNode>> {
96 let result = BnDiceNode::new_binder(
97 DiceNode { node_impl },
98 BinderFeatures { set_requesting_sid: true, ..BinderFeatures::default() },
99 );
100 Ok(result)
101 }
102
103 fn sign(&self, input_values: &[BinderInputValues], message: &[u8]) -> Result<Signature> {
104 let client =
105 client_input_values(ThreadState::get_calling_uid()).context("In DiceNode::sign:")?;
106 self.node_impl.sign(client, input_values, message)
107 }
108 fn get_attestation_chain(&self, input_values: &[BinderInputValues]) -> Result<Bcc> {
109 let client = client_input_values(ThreadState::get_calling_uid())
110 .context("In DiceNode::get_attestation_chain:")?;
111 self.node_impl.get_attestation_chain(client, input_values)
112 }
113 fn derive(&self, input_values: &[BinderInputValues]) -> Result<BccHandover> {
114 let client =
115 client_input_values(ThreadState::get_calling_uid()).context("In DiceNode::extend:")?;
116 self.node_impl.derive(client, input_values)
117 }
118 fn demote(&self, input_values: &[BinderInputValues]) -> Result<()> {
119 let client =
120 client_input_values(ThreadState::get_calling_uid()).context("In DiceNode::demote:")?;
121 self.node_impl.demote(client, input_values)
122 }
123}
124
125impl binder::Interface for DiceNode {}
126
127impl IDiceNode for DiceNode {
128 fn sign(&self, input_values: &[BinderInputValues], message: &[u8]) -> BinderResult<Signature> {
129 map_or_log_err(self.sign(input_values, message), Ok)
130 }
131 fn getAttestationChain(&self, input_values: &[BinderInputValues]) -> BinderResult<Bcc> {
132 map_or_log_err(self.get_attestation_chain(input_values), Ok)
133 }
134 fn derive(&self, input_values: &[BinderInputValues]) -> BinderResult<BccHandover> {
135 map_or_log_err(self.derive(input_values), Ok)
136 }
137 fn demote(&self, input_values: &[BinderInputValues]) -> BinderResult<()> {
138 map_or_log_err(self.demote(input_values), Ok)
139 }
140}