blob: 023774f198c5891783d11866f6fd5a22f7acf4a4 [file] [log] [blame]
Janis Danisevskis78bd48c2020-07-21 12:27:13 -07001// Copyright 2020, 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//! This crate provides access control primitives for Keystore 2.0.
16//! It provides high level functions for checking permissions in the keystore2 and keystore2_key
17//! SELinux classes based on the keystore2_selinux backend.
18//! It also provides KeystorePerm and KeyPerm as convenience wrappers for the SELinux permission
19//! defined by keystore2 and keystore2_key respectively.
20
Janis Danisevskisa2f48502021-10-18 16:07:09 -070021use crate::error::Error as KsError;
Rajesh Nyamagoudcaee93e2022-05-26 00:20:38 +000022use crate::error::ResponseCode;
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +000023use crate::ks_err;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070024use android_system_keystore2::aidl::android::system::keystore2::{
25 Domain::Domain, KeyDescriptor::KeyDescriptor, KeyPermission::KeyPermission,
26};
Janis Danisevskisa2f48502021-10-18 16:07:09 -070027use anyhow::Context as AnyhowContext;
28use keystore2_selinux as selinux;
Janis Danisevskis56af0312021-10-18 16:11:41 -070029use selinux::{implement_class, Backend, ClassPermission};
Janis Danisevskis78bd48c2020-07-21 12:27:13 -070030use std::cmp::PartialEq;
31use std::convert::From;
Janis Danisevskis935e6c62020-08-18 12:52:27 -070032use std::ffi::CStr;
Andrew Walbrana4bc1a92024-09-03 13:08:17 +010033use std::sync::LazyLock;
Janis Danisevskis78bd48c2020-07-21 12:27:13 -070034
Janis Danisevskis78bd48c2020-07-21 12:27:13 -070035// Replace getcon with a mock in the test situation
36#[cfg(not(test))]
37use selinux::getcon;
38#[cfg(test)]
39use tests::test_getcon as getcon;
40
David Drysdale2566fb32024-07-09 14:46:37 +010041#[cfg(test)]
42mod tests;
43
Andrew Walbrana4bc1a92024-09-03 13:08:17 +010044// Panicking here is allowed because keystore cannot function without this backend
45// and it would happen early and indicate a gross misconfiguration of the device.
46static KEYSTORE2_KEY_LABEL_BACKEND: LazyLock<selinux::KeystoreKeyBackend> =
47 LazyLock::new(|| selinux::KeystoreKeyBackend::new().unwrap());
Janis Danisevskis4ad056f2020-08-05 19:46:46 +000048
49fn lookup_keystore2_key_context(namespace: i64) -> anyhow::Result<selinux::Context> {
50 KEYSTORE2_KEY_LABEL_BACKEND.lookup(&namespace.to_string())
51}
52
Janis Danisevskis39d57e72021-10-19 16:56:20 -070053implement_class!(
Janis Danisevskis78bd48c2020-07-21 12:27:13 -070054 /// KeyPerm provides a convenient abstraction from the SELinux class `keystore2_key`.
55 /// At the same time it maps `KeyPermissions` from the Keystore 2.0 AIDL Grant interface to
Janis Danisevskis39d57e72021-10-19 16:56:20 -070056 /// the SELinux permissions.
57 #[repr(i32)]
58 #[selinux(class_name = keystore2_key)]
Chris Wailes263de9f2022-08-11 15:00:51 -070059 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
Janis Danisevskis39d57e72021-10-19 16:56:20 -070060 pub enum KeyPerm {
61 /// Checked when convert_storage_key_to_ephemeral is called.
62 #[selinux(name = convert_storage_key_to_ephemeral)]
63 ConvertStorageKeyToEphemeral = KeyPermission::CONVERT_STORAGE_KEY_TO_EPHEMERAL.0,
64 /// Checked when the caller tries do delete a key.
65 #[selinux(name = delete)]
66 Delete = KeyPermission::DELETE.0,
67 /// Checked when the caller tries to use a unique id.
68 #[selinux(name = gen_unique_id)]
69 GenUniqueId = KeyPermission::GEN_UNIQUE_ID.0,
70 /// Checked when the caller tries to load a key.
71 #[selinux(name = get_info)]
72 GetInfo = KeyPermission::GET_INFO.0,
73 /// Checked when the caller attempts to grant a key to another uid.
74 /// Also used for gating key migration attempts.
75 #[selinux(name = grant)]
76 Grant = KeyPermission::GRANT.0,
77 /// Checked when the caller attempts to use Domain::BLOB.
78 #[selinux(name = manage_blob)]
79 ManageBlob = KeyPermission::MANAGE_BLOB.0,
80 /// Checked when the caller tries to create a key which implies rebinding
81 /// an alias to the new key.
82 #[selinux(name = rebind)]
83 Rebind = KeyPermission::REBIND.0,
84 /// Checked when the caller attempts to create a forced operation.
85 #[selinux(name = req_forced_op)]
86 ReqForcedOp = KeyPermission::REQ_FORCED_OP.0,
87 /// Checked when the caller attempts to update public key artifacts.
88 #[selinux(name = update)]
89 Update = KeyPermission::UPDATE.0,
90 /// Checked when the caller attempts to use a private or public key.
91 #[selinux(name = use)]
92 Use = KeyPermission::USE.0,
Eran Messeri653932e2022-06-14 17:04:10 +010093 /// Does nothing, and is not checked. For use of device identifiers,
94 /// the caller must hold the READ_PRIVILEGED_PHONE_STATE Android
95 /// permission.
Janis Danisevskis39d57e72021-10-19 16:56:20 -070096 #[selinux(name = use_dev_id)]
97 UseDevId = KeyPermission::USE_DEV_ID.0,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -070098 }
99);
100
Janis Danisevskis56af0312021-10-18 16:11:41 -0700101implement_class!(
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700102 /// KeystorePerm provides a convenient abstraction from the SELinux class `keystore2`.
103 /// Using the implement_permission macro we get the same features as `KeyPerm`.
Janis Danisevskis56af0312021-10-18 16:11:41 -0700104 #[selinux(class_name = keystore2)]
Chris Wailes263de9f2022-08-11 15:00:51 -0700105 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700106 pub enum KeystorePerm {
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700107 /// Checked when a new auth token is installed.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700108 #[selinux(name = add_auth)]
109 AddAuth,
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700110 /// Checked when an app is uninstalled or wiped.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700111 #[selinux(name = clear_ns)]
112 ClearNs,
Janis Danisevskisee10b5f2020-09-22 16:42:35 -0700113 /// Checked when Keystore 2.0 is asked to list a namespace that the caller
114 /// does not have the get_info permission for.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700115 #[selinux(name = list)]
116 List,
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700117 /// Checked when Keystore 2.0 gets locked.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700118 #[selinux(name = lock)]
119 Lock,
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700120 /// Checked when Keystore 2.0 shall be reset.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700121 #[selinux(name = reset)]
122 Reset,
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700123 /// Checked when Keystore 2.0 shall be unlocked.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700124 #[selinux(name = unlock)]
125 Unlock,
Hasini Gunasinghe803c2d42021-01-27 00:48:40 +0000126 /// Checked when user is added or removed.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700127 #[selinux(name = change_user)]
128 ChangeUser,
Hasini Gunasinghe803c2d42021-01-27 00:48:40 +0000129 /// Checked when password of the user is changed.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700130 #[selinux(name = change_password)]
131 ChangePassword,
Hasini Gunasinghe803c2d42021-01-27 00:48:40 +0000132 /// Checked when a UID is cleared.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700133 #[selinux(name = clear_uid)]
134 ClearUID,
Hasini Gunasinghe5fc95252020-12-04 00:35:08 +0000135 /// Checked when Credstore calls IKeystoreAuthorization to obtain auth tokens.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700136 #[selinux(name = get_auth_token)]
137 GetAuthToken,
Satya Tangirala5b9e5b12021-03-09 12:54:21 -0800138 /// Checked when earlyBootEnded() is called.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700139 #[selinux(name = early_boot_ended)]
140 EarlyBootEnded,
Eric Biggersb5613da2024-03-13 19:31:42 +0000141 /// Checked when IKeystoreMetrics::pullMetrics is called.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700142 #[selinux(name = pull_metrics)]
143 PullMetrics,
Paul Crowley46c703e2021-08-06 15:13:53 -0700144 /// Checked when IKeystoreMaintenance::deleteAllKeys is called.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700145 #[selinux(name = delete_all_keys)]
146 DeleteAllKeys,
Seth Moore7ee79f92021-12-07 11:42:49 -0800147 /// Checked on calls to IRemotelyProvisionedKeyPool::getAttestationKey
148 #[selinux(name = get_attestation_key)]
149 GetAttestationKey,
James Willcoxd215da82023-10-03 21:31:31 +0000150 /// Checked on IKeystoreAuthorization::getLastAuthTime() is called.
151 #[selinux(name = get_last_auth_time)]
152 GetLastAuthTime,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700153 }
154);
155
156/// Represents a set of `KeyPerm` permissions.
157/// `IntoIterator` is implemented for this struct allowing the iteration through all the
158/// permissions in the set.
159/// It also implements a function `includes(self, other)` that checks if the permissions
160/// in `other` are included in `self`.
161///
162/// KeyPermSet can be created with the macro `key_perm_set![]`.
163///
164/// ## Example
165/// ```
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700166/// let perms1 = key_perm_set![KeyPerm::Use, KeyPerm::ManageBlob, KeyPerm::Grant];
167/// let perms2 = key_perm_set![KeyPerm::Use, KeyPerm::ManageBlob];
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700168///
169/// assert!(perms1.includes(perms2))
170/// assert!(!perms2.includes(perms1))
171///
172/// let i = perms1.into_iter();
173/// // iteration in ascending order of the permission's numeric representation.
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700174/// assert_eq(Some(KeyPerm::ManageBlob), i.next());
175/// assert_eq(Some(KeyPerm::Grant), i.next());
176/// assert_eq(Some(KeyPerm::Use), i.next());
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700177/// assert_eq(None, i.next());
178/// ```
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700179#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
180pub struct KeyPermSet(pub i32);
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700181
182mod perm {
183 use super::*;
184
185 pub struct IntoIter {
186 vec: KeyPermSet,
187 pos: u8,
188 }
189
190 impl IntoIter {
191 pub fn new(v: KeyPermSet) -> Self {
192 Self { vec: v, pos: 0 }
193 }
194 }
195
196 impl std::iter::Iterator for IntoIter {
197 type Item = KeyPerm;
198
199 fn next(&mut self) -> Option<Self::Item> {
200 loop {
201 if self.pos == 32 {
202 return None;
203 }
204 let p = self.vec.0 & (1 << self.pos);
205 self.pos += 1;
206 if p != 0 {
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700207 return Some(KeyPerm::from(p));
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700208 }
209 }
210 }
211 }
212}
213
214impl From<KeyPerm> for KeyPermSet {
215 fn from(p: KeyPerm) -> Self {
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700216 Self(p as i32)
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700217 }
218}
219
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700220/// allow conversion from the AIDL wire type i32 to a permission set.
221impl From<i32> for KeyPermSet {
222 fn from(p: i32) -> Self {
223 Self(p)
224 }
225}
226
227impl From<KeyPermSet> for i32 {
228 fn from(p: KeyPermSet) -> i32 {
229 p.0
230 }
231}
232
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700233impl KeyPermSet {
234 /// Returns true iff this permission set has all of the permissions that are in `other`.
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700235 pub fn includes<T: Into<KeyPermSet>>(&self, other: T) -> bool {
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700236 let o: KeyPermSet = other.into();
237 (self.0 & o.0) == o.0
238 }
239}
240
241/// This macro can be used to create a `KeyPermSet` from a list of `KeyPerm` values.
242///
243/// ## Example
244/// ```
245/// let v = key_perm_set![Perm::delete(), Perm::manage_blob()];
246/// ```
247#[macro_export]
248macro_rules! key_perm_set {
249 () => { KeyPermSet(0) };
250 ($head:expr $(, $tail:expr)* $(,)?) => {
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700251 KeyPermSet($head as i32 $(| $tail as i32)*)
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700252 };
253}
254
255impl IntoIterator for KeyPermSet {
256 type Item = KeyPerm;
257 type IntoIter = perm::IntoIter;
258
259 fn into_iter(self) -> Self::IntoIter {
260 Self::IntoIter::new(self)
261 }
262}
263
Janis Danisevskis56af0312021-10-18 16:11:41 -0700264/// Uses `selinux::check_permission` to check if the given caller context `caller_cxt` may access
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700265/// the given permision `perm` of the `keystore2` security class.
Janis Danisevskis935e6c62020-08-18 12:52:27 -0700266pub fn check_keystore_permission(caller_ctx: &CStr, perm: KeystorePerm) -> anyhow::Result<()> {
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700267 let target_context = getcon().context("check_keystore_permission: getcon failed.")?;
Janis Danisevskis56af0312021-10-18 16:11:41 -0700268 selinux::check_permission(caller_ctx, &target_context, perm)
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700269}
270
Janis Danisevskis56af0312021-10-18 16:11:41 -0700271/// Uses `selinux::check_permission` to check if the given caller context `caller_cxt` has
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700272/// all the permissions indicated in `access_vec` for the target domain indicated by the key
273/// descriptor `key` in the security class `keystore2_key`.
274///
275/// Also checks if the caller has the grant permission for the given target domain.
276///
277/// Attempts to grant the grant permission are always denied.
278///
279/// The only viable target domains are
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700280/// * `Domain::APP` in which case u:r:keystore:s0 is used as target context and
281/// * `Domain::SELINUX` in which case the `key.nspace` parameter is looked up in
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700282/// SELinux keystore key backend, and the result is used
283/// as target context.
284pub fn check_grant_permission(
David Drysdale8e92e742024-10-22 13:07:07 +0100285 caller_uid: u32,
Janis Danisevskis935e6c62020-08-18 12:52:27 -0700286 caller_ctx: &CStr,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700287 access_vec: KeyPermSet,
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700288 key: &KeyDescriptor,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700289) -> anyhow::Result<()> {
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700290 let target_context = match key.domain {
David Drysdale8e92e742024-10-22 13:07:07 +0100291 Domain::APP => {
292 if caller_uid as i64 != key.nspace {
293 return Err(selinux::Error::perm())
294 .context("Trying to access key without ownership.");
295 }
296 getcon().context("check_grant_permission: getcon failed.")?
297 }
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700298 Domain::SELINUX => lookup_keystore2_key_context(key.nspace)
299 .context("check_grant_permission: Domain::SELINUX: Failed to lookup namespace.")?,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700300 _ => return Err(KsError::sys()).context(format!("Cannot grant {:?}.", key.domain)),
301 };
302
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700303 selinux::check_permission(caller_ctx, &target_context, KeyPerm::Grant)
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700304 .context("Grant permission is required when granting.")?;
305
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700306 if access_vec.includes(KeyPerm::Grant) {
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700307 return Err(selinux::Error::perm()).context("Grant permission cannot be granted.");
308 }
309
310 for p in access_vec.into_iter() {
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000311 selinux::check_permission(caller_ctx, &target_context, p).context(ks_err!(
312 "check_permission failed. \
Janis Danisevskis56af0312021-10-18 16:11:41 -0700313 The caller may have tried to grant a permission that they don't possess. {:?}",
314 p
315 ))?
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700316 }
317 Ok(())
318}
319
Janis Danisevskis56af0312021-10-18 16:11:41 -0700320/// Uses `selinux::check_permission` to check if the given caller context `caller_cxt`
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700321/// has the permissions indicated by `perm` for the target domain indicated by the key
322/// descriptor `key` in the security class `keystore2_key`.
323///
324/// The behavior differs slightly depending on the selected target domain:
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700325/// * `Domain::APP` u:r:keystore:s0 is used as target context.
326/// * `Domain::SELINUX` `key.nspace` parameter is looked up in the SELinux keystore key
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700327/// backend, and the result is used as target context.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700328/// * `Domain::BLOB` Same as SELinux but the "manage_blob" permission is always checked additionally
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700329/// to the one supplied in `perm`.
Janis Danisevskis56af0312021-10-18 16:11:41 -0700330/// * `Domain::GRANT` Does not use selinux::check_permission. Instead the `access_vector`
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700331/// parameter is queried for permission, which must be supplied in this case.
332///
333/// ## Return values.
334/// * Ok(()) If the requested permissions were granted.
335/// * Err(selinux::Error::perm()) If the requested permissions were denied.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700336/// * Err(KsError::sys()) This error is produced if `Domain::GRANT` is selected but no `access_vec`
337/// was supplied. It is also produced if `Domain::KEY_ID` was selected, and
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700338/// on various unexpected backend failures.
339pub fn check_key_permission(
Janis Danisevskis45760022021-01-19 16:34:10 -0800340 caller_uid: u32,
Janis Danisevskis935e6c62020-08-18 12:52:27 -0700341 caller_ctx: &CStr,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700342 perm: KeyPerm,
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700343 key: &KeyDescriptor,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700344 access_vector: &Option<KeyPermSet>,
345) -> anyhow::Result<()> {
Janis Danisevskis45760022021-01-19 16:34:10 -0800346 // If an access vector was supplied, the key is either accessed by GRANT or by KEY_ID.
347 // In the former case, key.domain was set to GRANT and we check the failure cases
348 // further below. If the access is requested by KEY_ID, key.domain would have been
349 // resolved to APP or SELINUX depending on where the key actually resides.
350 // Either way we can return here immediately if the access vector covers the requested
351 // permission. If it does not, we can still check if the caller has access by means of
352 // ownership.
353 if let Some(access_vector) = access_vector {
354 if access_vector.includes(perm) {
355 return Ok(());
356 }
357 }
358
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700359 let target_context = match key.domain {
360 // apps get the default keystore context
Janis Danisevskis45760022021-01-19 16:34:10 -0800361 Domain::APP => {
362 if caller_uid as i64 != key.nspace {
363 return Err(selinux::Error::perm())
364 .context("Trying to access key without ownership.");
365 }
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000366 getcon().context(ks_err!("getcon failed."))?
Janis Danisevskis45760022021-01-19 16:34:10 -0800367 }
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700368 Domain::SELINUX => lookup_keystore2_key_context(key.nspace)
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000369 .context(ks_err!("Domain::SELINUX: Failed to lookup namespace."))?,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700370 Domain::GRANT => {
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700371 match access_vector {
Janis Danisevskis45760022021-01-19 16:34:10 -0800372 Some(_) => {
373 return Err(selinux::Error::perm())
Janis Danisevskis56af0312021-10-18 16:11:41 -0700374 .context(format!("\"{}\" not granted", perm.name()));
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700375 }
376 None => {
377 // If DOMAIN_GRANT was selected an access vector must be supplied.
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000378 return Err(KsError::sys()).context(ks_err!(
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700379 "Cannot check permission for Domain::GRANT without access vector.",
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000380 ));
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700381 }
382 }
383 }
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700384 Domain::KEY_ID => {
385 // We should never be called with `Domain::KEY_ID. The database
386 // lookup should have converted this into one of `Domain::APP`
387 // or `Domain::SELINUX`.
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000388 return Err(KsError::sys())
389 .context(ks_err!("Cannot check permission for Domain::KEY_ID.",));
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700390 }
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700391 Domain::BLOB => {
392 let tctx = lookup_keystore2_key_context(key.nspace)
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000393 .context(ks_err!("Domain::BLOB: Failed to lookup namespace."))?;
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700394 // If DOMAIN_KEY_BLOB was specified, we check for the "manage_blob"
395 // permission in addition to the requested permission.
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700396 selinux::check_permission(caller_ctx, &tctx, KeyPerm::ManageBlob)?;
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700397
398 tctx
399 }
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700400 _ => {
Rajesh Nyamagoudcaee93e2022-05-26 00:20:38 +0000401 return Err(KsError::Rc(ResponseCode::INVALID_ARGUMENT))
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700402 .context(format!("Unknown domain value: \"{:?}\".", key.domain))
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700403 }
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700404 };
405
Janis Danisevskis56af0312021-10-18 16:11:41 -0700406 selinux::check_permission(caller_ctx, &target_context, perm)
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700407}