blob: 9e70ace674d4406937aab3135a355afac8bc6408 [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;
Janis Danisevskis2ded9cb2021-10-20 08:39:30 -070018mod permission;
Janis Danisevskis41e67192021-11-05 09:00:19 -070019mod proxy_node_hal;
Janis Danisevskisc51dff82021-10-20 09:51:16 -070020mod resident_node;
21
Janis Danisevskis41e67192021-11-05 09:00:19 -070022pub use crate::proxy_node_hal::ProxyNodeHal;
Janis Danisevskisc51dff82021-10-20 09:51:16 -070023pub use crate::resident_node::ResidentNode;
24use android_hardware_security_dice::aidl::android::hardware::security::dice::{
25 Bcc::Bcc, BccHandover::BccHandover, Config::Config as BinderConfig,
26 InputValues::InputValues as BinderInputValues, Mode::Mode, Signature::Signature,
27};
28use android_security_dice::aidl::android::security::dice::{
Janis Danisevskis99652dc2021-10-20 15:59:33 -070029 IDiceMaintenance::BnDiceMaintenance, IDiceMaintenance::IDiceMaintenance, IDiceNode::BnDiceNode,
30 IDiceNode::IDiceNode, ResponseCode::ResponseCode,
Janis Danisevskisc51dff82021-10-20 09:51:16 -070031};
32use anyhow::{Context, Result};
Stephen Crane23cf7242022-01-19 17:49:46 +000033use binder::{BinderFeatures, Result as BinderResult, Strong, ThreadState};
Janis Danisevskisc51dff82021-10-20 09:51:16 -070034pub use diced_open_dice_cbor as dice;
35use error::{map_or_log_err, Error};
Janis Danisevskis2ded9cb2021-10-20 08:39:30 -070036use keystore2_selinux as selinux;
Janis Danisevskisc51dff82021-10-20 09:51:16 -070037use libc::uid_t;
Janis Danisevskis2ded9cb2021-10-20 08:39:30 -070038use permission::Permission;
Alice Wang9c40eca2023-02-03 13:10:24 +000039use std::ffi::CString;
Janis Danisevskisc51dff82021-10-20 09:51:16 -070040use std::sync::Arc;
41
42/// A DiceNode backend implementation.
43/// All functions except demote_self derive effective dice artifacts staring from
44/// this node and iterating through `{ [client | demotion path], input_values }`
45/// in ascending order.
46pub trait DiceNodeImpl {
47 /// Signs the message using the effective dice artifacts and Ed25519Pure.
48 fn sign(
49 &self,
50 client: BinderInputValues,
51 input_values: &[BinderInputValues],
52 message: &[u8],
53 ) -> Result<Signature>;
54 /// Returns the effective attestation chain.
55 fn get_attestation_chain(
56 &self,
57 client: BinderInputValues,
58 input_values: &[BinderInputValues],
59 ) -> Result<Bcc>;
60 /// Returns the effective dice artifacts.
61 fn derive(
62 &self,
63 client: BinderInputValues,
64 input_values: &[BinderInputValues],
65 ) -> Result<BccHandover>;
66 /// Adds [ `client` | `input_values` ] to the demotion path of the given client.
67 /// This changes the effective dice artifacts for all subsequent API calls of the
68 /// given client.
69 fn demote(&self, client: BinderInputValues, input_values: &[BinderInputValues]) -> Result<()>;
70 /// This demotes the implementation itself. I.e. a resident node would replace its resident
71 /// with the effective artifacts derived using `input_values`. A proxy node would
72 /// simply call `demote` on its parent node. This is not reversible and changes
73 /// the effective dice artifacts of all clients.
74 fn demote_self(&self, input_values: &[BinderInputValues]) -> Result<()>;
75}
76
77/// Wraps a DiceNodeImpl and implements the actual IDiceNode AIDL API.
78pub struct DiceNode {
79 node_impl: Arc<dyn DiceNodeImpl + Sync + Send>,
80}
81
Janis Danisevskis2ded9cb2021-10-20 08:39:30 -070082/// This function uses its namesake in the permission module and in
83/// combination with with_calling_sid from the binder crate to check
84/// if the caller has the given keystore permission.
85pub fn check_caller_permission<T: selinux::ClassPermission>(perm: T) -> Result<()> {
86 ThreadState::with_calling_sid(|calling_sid| {
87 let target_context =
88 selinux::getcon().context("In check_caller_permission: getcon failed.")?;
89
90 selinux::check_permission(
91 calling_sid.ok_or(Error::Rc(ResponseCode::SYSTEM_ERROR)).context(
92 "In check_keystore_permission: Cannot check permission without calling_sid.",
93 )?,
94 &target_context,
95 perm,
96 )
97 })
98}
99
Janis Danisevskisc51dff82021-10-20 09:51:16 -0700100fn client_input_values(uid: uid_t) -> Result<BinderInputValues> {
Alice Wang9c40eca2023-02-03 13:10:24 +0000101 let desc = CString::new(format!("{}", uid)).unwrap();
Janis Danisevskisc51dff82021-10-20 09:51:16 -0700102 Ok(BinderInputValues {
Janis Danisevskisd9513f42021-12-16 17:15:13 -0800103 codeHash: [0; dice::HASH_SIZE],
Janis Danisevskisc51dff82021-10-20 09:51:16 -0700104 config: BinderConfig {
Alice Wang9c40eca2023-02-03 13:10:24 +0000105 desc: dice::retry_bcc_format_config_descriptor(Some(desc.as_c_str()), None, true)
106 .unwrap(),
Janis Danisevskisc51dff82021-10-20 09:51:16 -0700107 },
Janis Danisevskisd9513f42021-12-16 17:15:13 -0800108 authorityHash: [0; dice::HASH_SIZE],
Janis Danisevskisc51dff82021-10-20 09:51:16 -0700109 authorityDescriptor: None,
Janis Danisevskisd9513f42021-12-16 17:15:13 -0800110 hidden: [0; dice::HIDDEN_SIZE],
Janis Danisevskisc51dff82021-10-20 09:51:16 -0700111 mode: Mode::NORMAL,
112 })
113}
114
115impl DiceNode {
116 /// Constructs an instance of DiceNode, wraps it with a BnDiceNode object and
117 /// returns a strong pointer to the binder. The result can be used to register
118 /// the service with service manager.
119 pub fn new_as_binder(
120 node_impl: Arc<dyn DiceNodeImpl + Sync + Send>,
121 ) -> Result<Strong<dyn IDiceNode>> {
122 let result = BnDiceNode::new_binder(
123 DiceNode { node_impl },
124 BinderFeatures { set_requesting_sid: true, ..BinderFeatures::default() },
125 );
126 Ok(result)
127 }
128
129 fn sign(&self, input_values: &[BinderInputValues], message: &[u8]) -> Result<Signature> {
Janis Danisevskis2ded9cb2021-10-20 08:39:30 -0700130 check_caller_permission(Permission::UseSign).context("In DiceNode::sign:")?;
Janis Danisevskisc51dff82021-10-20 09:51:16 -0700131 let client =
132 client_input_values(ThreadState::get_calling_uid()).context("In DiceNode::sign:")?;
133 self.node_impl.sign(client, input_values, message)
134 }
135 fn get_attestation_chain(&self, input_values: &[BinderInputValues]) -> Result<Bcc> {
Janis Danisevskis2ded9cb2021-10-20 08:39:30 -0700136 check_caller_permission(Permission::GetAttestationChain)
137 .context("In DiceNode::get_attestation_chain:")?;
Janis Danisevskisc51dff82021-10-20 09:51:16 -0700138 let client = client_input_values(ThreadState::get_calling_uid())
139 .context("In DiceNode::get_attestation_chain:")?;
140 self.node_impl.get_attestation_chain(client, input_values)
141 }
142 fn derive(&self, input_values: &[BinderInputValues]) -> Result<BccHandover> {
Janis Danisevskis2ded9cb2021-10-20 08:39:30 -0700143 check_caller_permission(Permission::Derive).context("In DiceNode::derive:")?;
Janis Danisevskisc51dff82021-10-20 09:51:16 -0700144 let client =
145 client_input_values(ThreadState::get_calling_uid()).context("In DiceNode::extend:")?;
146 self.node_impl.derive(client, input_values)
147 }
148 fn demote(&self, input_values: &[BinderInputValues]) -> Result<()> {
Janis Danisevskis2ded9cb2021-10-20 08:39:30 -0700149 check_caller_permission(Permission::Demote).context("In DiceNode::demote:")?;
Janis Danisevskisc51dff82021-10-20 09:51:16 -0700150 let client =
151 client_input_values(ThreadState::get_calling_uid()).context("In DiceNode::demote:")?;
152 self.node_impl.demote(client, input_values)
153 }
154}
155
156impl binder::Interface for DiceNode {}
157
158impl IDiceNode for DiceNode {
159 fn sign(&self, input_values: &[BinderInputValues], message: &[u8]) -> BinderResult<Signature> {
160 map_or_log_err(self.sign(input_values, message), Ok)
161 }
162 fn getAttestationChain(&self, input_values: &[BinderInputValues]) -> BinderResult<Bcc> {
163 map_or_log_err(self.get_attestation_chain(input_values), Ok)
164 }
165 fn derive(&self, input_values: &[BinderInputValues]) -> BinderResult<BccHandover> {
166 map_or_log_err(self.derive(input_values), Ok)
167 }
168 fn demote(&self, input_values: &[BinderInputValues]) -> BinderResult<()> {
169 map_or_log_err(self.demote(input_values), Ok)
170 }
171}
Janis Danisevskis99652dc2021-10-20 15:59:33 -0700172
173/// Wraps a DiceNodeImpl and implements the IDiceMaintenance AIDL API.
174pub struct DiceMaintenance {
175 node_impl: Arc<dyn DiceNodeImpl + Sync + Send>,
176}
177
178impl DiceMaintenance {
179 /// Constructs an instance of DiceMaintenance, wraps it with a BnDiceMaintenance object and
180 /// returns a strong pointer to the binder. The result can be used to register the service
181 /// with service manager.
182 pub fn new_as_binder(
183 node_impl: Arc<dyn DiceNodeImpl + Sync + Send>,
184 ) -> Result<Strong<dyn IDiceMaintenance>> {
185 let result = BnDiceMaintenance::new_binder(
186 DiceMaintenance { node_impl },
187 BinderFeatures { set_requesting_sid: true, ..BinderFeatures::default() },
188 );
189 Ok(result)
190 }
191
192 fn demote_self(&self, input_values: &[BinderInputValues]) -> Result<()> {
193 check_caller_permission(Permission::DemoteSelf)
194 .context("In DiceMaintenance::demote_self:")?;
195 self.node_impl.demote_self(input_values)
196 }
197}
198
199impl binder::Interface for DiceMaintenance {}
200
201impl IDiceMaintenance for DiceMaintenance {
202 fn demoteSelf(&self, input_values: &[BinderInputValues]) -> BinderResult<()> {
203 map_or_log_err(self.demote_self(input_values), Ok)
204 }
205}