blob: b41111a8703b039e7c2b39cdd9e7b88035d37312 [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 Danisevskisc51dff82021-10-20 09:51:16 -070019
Janis Danisevskisc51dff82021-10-20 09:51:16 -070020use android_hardware_security_dice::aidl::android::hardware::security::dice::{
21 Bcc::Bcc, BccHandover::BccHandover, Config::Config as BinderConfig,
22 InputValues::InputValues as BinderInputValues, Mode::Mode, Signature::Signature,
23};
24use android_security_dice::aidl::android::security::dice::{
Janis Danisevskis99652dc2021-10-20 15:59:33 -070025 IDiceMaintenance::BnDiceMaintenance, IDiceMaintenance::IDiceMaintenance, IDiceNode::BnDiceNode,
26 IDiceNode::IDiceNode, ResponseCode::ResponseCode,
Janis Danisevskisc51dff82021-10-20 09:51:16 -070027};
28use anyhow::{Context, Result};
Stephen Crane23cf7242022-01-19 17:49:46 +000029use binder::{BinderFeatures, Result as BinderResult, Strong, ThreadState};
Janis Danisevskisc51dff82021-10-20 09:51:16 -070030pub use diced_open_dice_cbor as dice;
31use error::{map_or_log_err, Error};
Janis Danisevskis2ded9cb2021-10-20 08:39:30 -070032use keystore2_selinux as selinux;
Janis Danisevskisc51dff82021-10-20 09:51:16 -070033use libc::uid_t;
Janis Danisevskis2ded9cb2021-10-20 08:39:30 -070034use permission::Permission;
Alice Wang9c40eca2023-02-03 13:10:24 +000035use std::ffi::CString;
Janis Danisevskisc51dff82021-10-20 09:51:16 -070036use std::sync::Arc;
37
38/// A DiceNode backend implementation.
39/// All functions except demote_self derive effective dice artifacts staring from
40/// this node and iterating through `{ [client | demotion path], input_values }`
41/// in ascending order.
42pub trait DiceNodeImpl {
43 /// Signs the message using the effective dice artifacts and Ed25519Pure.
44 fn sign(
45 &self,
46 client: BinderInputValues,
47 input_values: &[BinderInputValues],
48 message: &[u8],
49 ) -> Result<Signature>;
50 /// Returns the effective attestation chain.
51 fn get_attestation_chain(
52 &self,
53 client: BinderInputValues,
54 input_values: &[BinderInputValues],
55 ) -> Result<Bcc>;
56 /// Returns the effective dice artifacts.
57 fn derive(
58 &self,
59 client: BinderInputValues,
60 input_values: &[BinderInputValues],
61 ) -> Result<BccHandover>;
62 /// Adds [ `client` | `input_values` ] to the demotion path of the given client.
63 /// This changes the effective dice artifacts for all subsequent API calls of the
64 /// given client.
65 fn demote(&self, client: BinderInputValues, input_values: &[BinderInputValues]) -> Result<()>;
66 /// This demotes the implementation itself. I.e. a resident node would replace its resident
67 /// with the effective artifacts derived using `input_values`. A proxy node would
68 /// simply call `demote` on its parent node. This is not reversible and changes
69 /// the effective dice artifacts of all clients.
70 fn demote_self(&self, input_values: &[BinderInputValues]) -> Result<()>;
71}
72
73/// Wraps a DiceNodeImpl and implements the actual IDiceNode AIDL API.
74pub struct DiceNode {
75 node_impl: Arc<dyn DiceNodeImpl + Sync + Send>,
76}
77
Janis Danisevskis2ded9cb2021-10-20 08:39:30 -070078/// This function uses its namesake in the permission module and in
79/// combination with with_calling_sid from the binder crate to check
80/// if the caller has the given keystore permission.
81pub fn check_caller_permission<T: selinux::ClassPermission>(perm: T) -> Result<()> {
82 ThreadState::with_calling_sid(|calling_sid| {
83 let target_context =
84 selinux::getcon().context("In check_caller_permission: getcon failed.")?;
85
86 selinux::check_permission(
87 calling_sid.ok_or(Error::Rc(ResponseCode::SYSTEM_ERROR)).context(
88 "In check_keystore_permission: Cannot check permission without calling_sid.",
89 )?,
90 &target_context,
91 perm,
92 )
93 })
94}
95
Janis Danisevskisc51dff82021-10-20 09:51:16 -070096fn client_input_values(uid: uid_t) -> Result<BinderInputValues> {
Alice Wang9c40eca2023-02-03 13:10:24 +000097 let desc = CString::new(format!("{}", uid)).unwrap();
Janis Danisevskisc51dff82021-10-20 09:51:16 -070098 Ok(BinderInputValues {
Janis Danisevskisd9513f42021-12-16 17:15:13 -080099 codeHash: [0; dice::HASH_SIZE],
Janis Danisevskisc51dff82021-10-20 09:51:16 -0700100 config: BinderConfig {
Alice Wang9c40eca2023-02-03 13:10:24 +0000101 desc: dice::retry_bcc_format_config_descriptor(Some(desc.as_c_str()), None, true)
102 .unwrap(),
Janis Danisevskisc51dff82021-10-20 09:51:16 -0700103 },
Janis Danisevskisd9513f42021-12-16 17:15:13 -0800104 authorityHash: [0; dice::HASH_SIZE],
Janis Danisevskisc51dff82021-10-20 09:51:16 -0700105 authorityDescriptor: None,
Janis Danisevskisd9513f42021-12-16 17:15:13 -0800106 hidden: [0; dice::HIDDEN_SIZE],
Janis Danisevskisc51dff82021-10-20 09:51:16 -0700107 mode: Mode::NORMAL,
108 })
109}
110
111impl DiceNode {
112 /// Constructs an instance of DiceNode, wraps it with a BnDiceNode object and
113 /// returns a strong pointer to the binder. The result can be used to register
114 /// the service with service manager.
115 pub fn new_as_binder(
116 node_impl: Arc<dyn DiceNodeImpl + Sync + Send>,
117 ) -> Result<Strong<dyn IDiceNode>> {
118 let result = BnDiceNode::new_binder(
119 DiceNode { node_impl },
120 BinderFeatures { set_requesting_sid: true, ..BinderFeatures::default() },
121 );
122 Ok(result)
123 }
124
125 fn sign(&self, input_values: &[BinderInputValues], message: &[u8]) -> Result<Signature> {
Janis Danisevskis2ded9cb2021-10-20 08:39:30 -0700126 check_caller_permission(Permission::UseSign).context("In DiceNode::sign:")?;
Janis Danisevskisc51dff82021-10-20 09:51:16 -0700127 let client =
128 client_input_values(ThreadState::get_calling_uid()).context("In DiceNode::sign:")?;
129 self.node_impl.sign(client, input_values, message)
130 }
131 fn get_attestation_chain(&self, input_values: &[BinderInputValues]) -> Result<Bcc> {
Janis Danisevskis2ded9cb2021-10-20 08:39:30 -0700132 check_caller_permission(Permission::GetAttestationChain)
133 .context("In DiceNode::get_attestation_chain:")?;
Janis Danisevskisc51dff82021-10-20 09:51:16 -0700134 let client = client_input_values(ThreadState::get_calling_uid())
135 .context("In DiceNode::get_attestation_chain:")?;
136 self.node_impl.get_attestation_chain(client, input_values)
137 }
138 fn derive(&self, input_values: &[BinderInputValues]) -> Result<BccHandover> {
Janis Danisevskis2ded9cb2021-10-20 08:39:30 -0700139 check_caller_permission(Permission::Derive).context("In DiceNode::derive:")?;
Janis Danisevskisc51dff82021-10-20 09:51:16 -0700140 let client =
141 client_input_values(ThreadState::get_calling_uid()).context("In DiceNode::extend:")?;
142 self.node_impl.derive(client, input_values)
143 }
144 fn demote(&self, input_values: &[BinderInputValues]) -> Result<()> {
Janis Danisevskis2ded9cb2021-10-20 08:39:30 -0700145 check_caller_permission(Permission::Demote).context("In DiceNode::demote:")?;
Janis Danisevskisc51dff82021-10-20 09:51:16 -0700146 let client =
147 client_input_values(ThreadState::get_calling_uid()).context("In DiceNode::demote:")?;
148 self.node_impl.demote(client, input_values)
149 }
150}
151
152impl binder::Interface for DiceNode {}
153
154impl IDiceNode for DiceNode {
155 fn sign(&self, input_values: &[BinderInputValues], message: &[u8]) -> BinderResult<Signature> {
156 map_or_log_err(self.sign(input_values, message), Ok)
157 }
158 fn getAttestationChain(&self, input_values: &[BinderInputValues]) -> BinderResult<Bcc> {
159 map_or_log_err(self.get_attestation_chain(input_values), Ok)
160 }
161 fn derive(&self, input_values: &[BinderInputValues]) -> BinderResult<BccHandover> {
162 map_or_log_err(self.derive(input_values), Ok)
163 }
164 fn demote(&self, input_values: &[BinderInputValues]) -> BinderResult<()> {
165 map_or_log_err(self.demote(input_values), Ok)
166 }
167}
Janis Danisevskis99652dc2021-10-20 15:59:33 -0700168
169/// Wraps a DiceNodeImpl and implements the IDiceMaintenance AIDL API.
170pub struct DiceMaintenance {
171 node_impl: Arc<dyn DiceNodeImpl + Sync + Send>,
172}
173
174impl DiceMaintenance {
175 /// Constructs an instance of DiceMaintenance, wraps it with a BnDiceMaintenance object and
176 /// returns a strong pointer to the binder. The result can be used to register the service
177 /// with service manager.
178 pub fn new_as_binder(
179 node_impl: Arc<dyn DiceNodeImpl + Sync + Send>,
180 ) -> Result<Strong<dyn IDiceMaintenance>> {
181 let result = BnDiceMaintenance::new_binder(
182 DiceMaintenance { node_impl },
183 BinderFeatures { set_requesting_sid: true, ..BinderFeatures::default() },
184 );
185 Ok(result)
186 }
187
188 fn demote_self(&self, input_values: &[BinderInputValues]) -> Result<()> {
189 check_caller_permission(Permission::DemoteSelf)
190 .context("In DiceMaintenance::demote_self:")?;
191 self.node_impl.demote_self(input_values)
192 }
193}
194
195impl binder::Interface for DiceMaintenance {}
196
197impl IDiceMaintenance for DiceMaintenance {
198 fn demoteSelf(&self, input_values: &[BinderInputValues]) -> BinderResult<()> {
199 map_or_log_err(self.demote_self(input_values), Ok)
200 }
201}