blob: f012c1b407cef72ab74265107ae6456ae3ffe52a [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;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070023use android_system_keystore2::aidl::android::system::keystore2::{
24 Domain::Domain, KeyDescriptor::KeyDescriptor, KeyPermission::KeyPermission,
25};
Janis Danisevskisa2f48502021-10-18 16:07:09 -070026use anyhow::Context as AnyhowContext;
27use keystore2_selinux as selinux;
28use lazy_static::lazy_static;
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;
Janis Danisevskis78bd48c2020-07-21 12:27:13 -070033
Janis Danisevskis78bd48c2020-07-21 12:27:13 -070034// Replace getcon with a mock in the test situation
35#[cfg(not(test))]
36use selinux::getcon;
37#[cfg(test)]
38use tests::test_getcon as getcon;
39
Janis Danisevskis4ad056f2020-08-05 19:46:46 +000040lazy_static! {
41 // Panicking here is allowed because keystore cannot function without this backend
42 // and it would happen early and indicate a gross misconfiguration of the device.
43 static ref KEYSTORE2_KEY_LABEL_BACKEND: selinux::KeystoreKeyBackend =
44 selinux::KeystoreKeyBackend::new().unwrap();
45}
46
47fn lookup_keystore2_key_context(namespace: i64) -> anyhow::Result<selinux::Context> {
48 KEYSTORE2_KEY_LABEL_BACKEND.lookup(&namespace.to_string())
49}
50
Janis Danisevskis39d57e72021-10-19 16:56:20 -070051implement_class!(
Janis Danisevskis78bd48c2020-07-21 12:27:13 -070052 /// KeyPerm provides a convenient abstraction from the SELinux class `keystore2_key`.
53 /// At the same time it maps `KeyPermissions` from the Keystore 2.0 AIDL Grant interface to
Janis Danisevskis39d57e72021-10-19 16:56:20 -070054 /// the SELinux permissions.
55 #[repr(i32)]
56 #[selinux(class_name = keystore2_key)]
Chris Wailes263de9f2022-08-11 15:00:51 -070057 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
Janis Danisevskis39d57e72021-10-19 16:56:20 -070058 pub enum KeyPerm {
59 /// Checked when convert_storage_key_to_ephemeral is called.
60 #[selinux(name = convert_storage_key_to_ephemeral)]
61 ConvertStorageKeyToEphemeral = KeyPermission::CONVERT_STORAGE_KEY_TO_EPHEMERAL.0,
62 /// Checked when the caller tries do delete a key.
63 #[selinux(name = delete)]
64 Delete = KeyPermission::DELETE.0,
65 /// Checked when the caller tries to use a unique id.
66 #[selinux(name = gen_unique_id)]
67 GenUniqueId = KeyPermission::GEN_UNIQUE_ID.0,
68 /// Checked when the caller tries to load a key.
69 #[selinux(name = get_info)]
70 GetInfo = KeyPermission::GET_INFO.0,
71 /// Checked when the caller attempts to grant a key to another uid.
72 /// Also used for gating key migration attempts.
73 #[selinux(name = grant)]
74 Grant = KeyPermission::GRANT.0,
75 /// Checked when the caller attempts to use Domain::BLOB.
76 #[selinux(name = manage_blob)]
77 ManageBlob = KeyPermission::MANAGE_BLOB.0,
78 /// Checked when the caller tries to create a key which implies rebinding
79 /// an alias to the new key.
80 #[selinux(name = rebind)]
81 Rebind = KeyPermission::REBIND.0,
82 /// Checked when the caller attempts to create a forced operation.
83 #[selinux(name = req_forced_op)]
84 ReqForcedOp = KeyPermission::REQ_FORCED_OP.0,
85 /// Checked when the caller attempts to update public key artifacts.
86 #[selinux(name = update)]
87 Update = KeyPermission::UPDATE.0,
88 /// Checked when the caller attempts to use a private or public key.
89 #[selinux(name = use)]
90 Use = KeyPermission::USE.0,
Eran Messeri653932e2022-06-14 17:04:10 +010091 /// Does nothing, and is not checked. For use of device identifiers,
92 /// the caller must hold the READ_PRIVILEGED_PHONE_STATE Android
93 /// permission.
Janis Danisevskis39d57e72021-10-19 16:56:20 -070094 #[selinux(name = use_dev_id)]
95 UseDevId = KeyPermission::USE_DEV_ID.0,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -070096 }
97);
98
Janis Danisevskis56af0312021-10-18 16:11:41 -070099implement_class!(
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700100 /// KeystorePerm provides a convenient abstraction from the SELinux class `keystore2`.
101 /// Using the implement_permission macro we get the same features as `KeyPerm`.
Janis Danisevskis56af0312021-10-18 16:11:41 -0700102 #[selinux(class_name = keystore2)]
Chris Wailes263de9f2022-08-11 15:00:51 -0700103 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700104 pub enum KeystorePerm {
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700105 /// Checked when a new auth token is installed.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700106 #[selinux(name = add_auth)]
107 AddAuth,
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700108 /// Checked when an app is uninstalled or wiped.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700109 #[selinux(name = clear_ns)]
110 ClearNs,
Hasini Gunasinghe9ee18412021-03-11 20:12:44 +0000111 /// Checked when the user state is queried from Keystore 2.0.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700112 #[selinux(name = get_state)]
113 GetState,
Janis Danisevskisee10b5f2020-09-22 16:42:35 -0700114 /// Checked when Keystore 2.0 is asked to list a namespace that the caller
115 /// does not have the get_info permission for.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700116 #[selinux(name = list)]
117 List,
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700118 /// Checked when Keystore 2.0 gets locked.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700119 #[selinux(name = lock)]
120 Lock,
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700121 /// Checked when Keystore 2.0 shall be reset.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700122 #[selinux(name = reset)]
123 Reset,
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700124 /// Checked when Keystore 2.0 shall be unlocked.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700125 #[selinux(name = unlock)]
126 Unlock,
Hasini Gunasinghe803c2d42021-01-27 00:48:40 +0000127 /// Checked when user is added or removed.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700128 #[selinux(name = change_user)]
129 ChangeUser,
Hasini Gunasinghe803c2d42021-01-27 00:48:40 +0000130 /// Checked when password of the user is changed.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700131 #[selinux(name = change_password)]
132 ChangePassword,
Hasini Gunasinghe803c2d42021-01-27 00:48:40 +0000133 /// Checked when a UID is cleared.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700134 #[selinux(name = clear_uid)]
135 ClearUID,
Hasini Gunasinghe5fc95252020-12-04 00:35:08 +0000136 /// Checked when Credstore calls IKeystoreAuthorization to obtain auth tokens.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700137 #[selinux(name = get_auth_token)]
138 GetAuthToken,
Satya Tangirala5b9e5b12021-03-09 12:54:21 -0800139 /// Checked when earlyBootEnded() is called.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700140 #[selinux(name = early_boot_ended)]
141 EarlyBootEnded,
Janis Danisevskis333b7c02021-03-23 18:57:41 -0700142 /// Checked when IKeystoreMaintenance::onDeviceOffBody is called.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700143 #[selinux(name = report_off_body)]
144 ReportOffBody,
145 /// Checked when IkeystoreMetrics::pullMetrics is called.
146 #[selinux(name = pull_metrics)]
147 PullMetrics,
Paul Crowley46c703e2021-08-06 15:13:53 -0700148 /// Checked when IKeystoreMaintenance::deleteAllKeys is called.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700149 #[selinux(name = delete_all_keys)]
150 DeleteAllKeys,
Seth Moore7ee79f92021-12-07 11:42:49 -0800151 /// Checked on calls to IRemotelyProvisionedKeyPool::getAttestationKey
152 #[selinux(name = get_attestation_key)]
153 GetAttestationKey,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700154 }
155);
156
157/// Represents a set of `KeyPerm` permissions.
158/// `IntoIterator` is implemented for this struct allowing the iteration through all the
159/// permissions in the set.
160/// It also implements a function `includes(self, other)` that checks if the permissions
161/// in `other` are included in `self`.
162///
163/// KeyPermSet can be created with the macro `key_perm_set![]`.
164///
165/// ## Example
166/// ```
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700167/// let perms1 = key_perm_set![KeyPerm::Use, KeyPerm::ManageBlob, KeyPerm::Grant];
168/// let perms2 = key_perm_set![KeyPerm::Use, KeyPerm::ManageBlob];
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700169///
170/// assert!(perms1.includes(perms2))
171/// assert!(!perms2.includes(perms1))
172///
173/// let i = perms1.into_iter();
174/// // iteration in ascending order of the permission's numeric representation.
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700175/// assert_eq(Some(KeyPerm::ManageBlob), i.next());
176/// assert_eq(Some(KeyPerm::Grant), i.next());
177/// assert_eq(Some(KeyPerm::Use), i.next());
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700178/// assert_eq(None, i.next());
179/// ```
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700180#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
181pub struct KeyPermSet(pub i32);
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700182
183mod perm {
184 use super::*;
185
186 pub struct IntoIter {
187 vec: KeyPermSet,
188 pos: u8,
189 }
190
191 impl IntoIter {
192 pub fn new(v: KeyPermSet) -> Self {
193 Self { vec: v, pos: 0 }
194 }
195 }
196
197 impl std::iter::Iterator for IntoIter {
198 type Item = KeyPerm;
199
200 fn next(&mut self) -> Option<Self::Item> {
201 loop {
202 if self.pos == 32 {
203 return None;
204 }
205 let p = self.vec.0 & (1 << self.pos);
206 self.pos += 1;
207 if p != 0 {
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700208 return Some(KeyPerm::from(p));
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700209 }
210 }
211 }
212 }
213}
214
215impl From<KeyPerm> for KeyPermSet {
216 fn from(p: KeyPerm) -> Self {
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700217 Self(p as i32)
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700218 }
219}
220
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700221/// allow conversion from the AIDL wire type i32 to a permission set.
222impl From<i32> for KeyPermSet {
223 fn from(p: i32) -> Self {
224 Self(p)
225 }
226}
227
228impl From<KeyPermSet> for i32 {
229 fn from(p: KeyPermSet) -> i32 {
230 p.0
231 }
232}
233
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700234impl KeyPermSet {
235 /// Returns true iff this permission set has all of the permissions that are in `other`.
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700236 pub fn includes<T: Into<KeyPermSet>>(&self, other: T) -> bool {
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700237 let o: KeyPermSet = other.into();
238 (self.0 & o.0) == o.0
239 }
240}
241
242/// This macro can be used to create a `KeyPermSet` from a list of `KeyPerm` values.
243///
244/// ## Example
245/// ```
246/// let v = key_perm_set![Perm::delete(), Perm::manage_blob()];
247/// ```
248#[macro_export]
249macro_rules! key_perm_set {
250 () => { KeyPermSet(0) };
251 ($head:expr $(, $tail:expr)* $(,)?) => {
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700252 KeyPermSet($head as i32 $(| $tail as i32)*)
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700253 };
254}
255
256impl IntoIterator for KeyPermSet {
257 type Item = KeyPerm;
258 type IntoIter = perm::IntoIter;
259
260 fn into_iter(self) -> Self::IntoIter {
261 Self::IntoIter::new(self)
262 }
263}
264
Janis Danisevskis56af0312021-10-18 16:11:41 -0700265/// Uses `selinux::check_permission` to check if the given caller context `caller_cxt` may access
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700266/// the given permision `perm` of the `keystore2` security class.
Janis Danisevskis935e6c62020-08-18 12:52:27 -0700267pub fn check_keystore_permission(caller_ctx: &CStr, perm: KeystorePerm) -> anyhow::Result<()> {
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700268 let target_context = getcon().context("check_keystore_permission: getcon failed.")?;
Janis Danisevskis56af0312021-10-18 16:11:41 -0700269 selinux::check_permission(caller_ctx, &target_context, perm)
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700270}
271
Janis Danisevskis56af0312021-10-18 16:11:41 -0700272/// Uses `selinux::check_permission` to check if the given caller context `caller_cxt` has
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700273/// all the permissions indicated in `access_vec` for the target domain indicated by the key
274/// descriptor `key` in the security class `keystore2_key`.
275///
276/// Also checks if the caller has the grant permission for the given target domain.
277///
278/// Attempts to grant the grant permission are always denied.
279///
280/// The only viable target domains are
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700281/// * `Domain::APP` in which case u:r:keystore:s0 is used as target context and
282/// * `Domain::SELINUX` in which case the `key.nspace` parameter is looked up in
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700283/// SELinux keystore key backend, and the result is used
284/// as target context.
285pub fn check_grant_permission(
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 {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700291 Domain::APP => getcon().context("check_grant_permission: getcon failed.")?,
292 Domain::SELINUX => lookup_keystore2_key_context(key.nspace)
293 .context("check_grant_permission: Domain::SELINUX: Failed to lookup namespace.")?,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700294 _ => return Err(KsError::sys()).context(format!("Cannot grant {:?}.", key.domain)),
295 };
296
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700297 selinux::check_permission(caller_ctx, &target_context, KeyPerm::Grant)
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700298 .context("Grant permission is required when granting.")?;
299
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700300 if access_vec.includes(KeyPerm::Grant) {
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700301 return Err(selinux::Error::perm()).context("Grant permission cannot be granted.");
302 }
303
304 for p in access_vec.into_iter() {
Janis Danisevskis56af0312021-10-18 16:11:41 -0700305 selinux::check_permission(caller_ctx, &target_context, p).context(format!(
306 "check_grant_permission: check_permission failed. \
307 The caller may have tried to grant a permission that they don't possess. {:?}",
308 p
309 ))?
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700310 }
311 Ok(())
312}
313
Janis Danisevskis56af0312021-10-18 16:11:41 -0700314/// Uses `selinux::check_permission` to check if the given caller context `caller_cxt`
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700315/// has the permissions indicated by `perm` for the target domain indicated by the key
316/// descriptor `key` in the security class `keystore2_key`.
317///
318/// The behavior differs slightly depending on the selected target domain:
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700319/// * `Domain::APP` u:r:keystore:s0 is used as target context.
320/// * `Domain::SELINUX` `key.nspace` parameter is looked up in the SELinux keystore key
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700321/// backend, and the result is used as target context.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700322/// * `Domain::BLOB` Same as SELinux but the "manage_blob" permission is always checked additionally
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700323/// to the one supplied in `perm`.
Janis Danisevskis56af0312021-10-18 16:11:41 -0700324/// * `Domain::GRANT` Does not use selinux::check_permission. Instead the `access_vector`
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700325/// parameter is queried for permission, which must be supplied in this case.
326///
327/// ## Return values.
328/// * Ok(()) If the requested permissions were granted.
329/// * Err(selinux::Error::perm()) If the requested permissions were denied.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700330/// * Err(KsError::sys()) This error is produced if `Domain::GRANT` is selected but no `access_vec`
331/// was supplied. It is also produced if `Domain::KEY_ID` was selected, and
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700332/// on various unexpected backend failures.
333pub fn check_key_permission(
Janis Danisevskis45760022021-01-19 16:34:10 -0800334 caller_uid: u32,
Janis Danisevskis935e6c62020-08-18 12:52:27 -0700335 caller_ctx: &CStr,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700336 perm: KeyPerm,
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700337 key: &KeyDescriptor,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700338 access_vector: &Option<KeyPermSet>,
339) -> anyhow::Result<()> {
Janis Danisevskis45760022021-01-19 16:34:10 -0800340 // If an access vector was supplied, the key is either accessed by GRANT or by KEY_ID.
341 // In the former case, key.domain was set to GRANT and we check the failure cases
342 // further below. If the access is requested by KEY_ID, key.domain would have been
343 // resolved to APP or SELINUX depending on where the key actually resides.
344 // Either way we can return here immediately if the access vector covers the requested
345 // permission. If it does not, we can still check if the caller has access by means of
346 // ownership.
347 if let Some(access_vector) = access_vector {
348 if access_vector.includes(perm) {
349 return Ok(());
350 }
351 }
352
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700353 let target_context = match key.domain {
354 // apps get the default keystore context
Janis Danisevskis45760022021-01-19 16:34:10 -0800355 Domain::APP => {
356 if caller_uid as i64 != key.nspace {
357 return Err(selinux::Error::perm())
358 .context("Trying to access key without ownership.");
359 }
360 getcon().context("check_key_permission: getcon failed.")?
361 }
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700362 Domain::SELINUX => lookup_keystore2_key_context(key.nspace)
363 .context("check_key_permission: Domain::SELINUX: Failed to lookup namespace.")?,
364 Domain::GRANT => {
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700365 match access_vector {
Janis Danisevskis45760022021-01-19 16:34:10 -0800366 Some(_) => {
367 return Err(selinux::Error::perm())
Janis Danisevskis56af0312021-10-18 16:11:41 -0700368 .context(format!("\"{}\" not granted", perm.name()));
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700369 }
370 None => {
371 // If DOMAIN_GRANT was selected an access vector must be supplied.
372 return Err(KsError::sys()).context(
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700373 "Cannot check permission for Domain::GRANT without access vector.",
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700374 );
375 }
376 }
377 }
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700378 Domain::KEY_ID => {
379 // We should never be called with `Domain::KEY_ID. The database
380 // lookup should have converted this into one of `Domain::APP`
381 // or `Domain::SELINUX`.
382 return Err(KsError::sys()).context("Cannot check permission for Domain::KEY_ID.");
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700383 }
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700384 Domain::BLOB => {
385 let tctx = lookup_keystore2_key_context(key.nspace)
386 .context("Domain::BLOB: Failed to lookup namespace.")?;
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700387 // If DOMAIN_KEY_BLOB was specified, we check for the "manage_blob"
388 // permission in addition to the requested permission.
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700389 selinux::check_permission(caller_ctx, &tctx, KeyPerm::ManageBlob)?;
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700390
391 tctx
392 }
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700393 _ => {
Rajesh Nyamagoudcaee93e2022-05-26 00:20:38 +0000394 return Err(KsError::Rc(ResponseCode::INVALID_ARGUMENT))
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700395 .context(format!("Unknown domain value: \"{:?}\".", key.domain))
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700396 }
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700397 };
398
Janis Danisevskis56af0312021-10-18 16:11:41 -0700399 selinux::check_permission(caller_ctx, &target_context, perm)
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700400}
401
402#[cfg(test)]
403mod tests {
404 use super::*;
405 use anyhow::anyhow;
406 use anyhow::Result;
407 use keystore2_selinux::*;
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700408
409 const ALL_PERMS: KeyPermSet = key_perm_set![
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700410 KeyPerm::ManageBlob,
411 KeyPerm::Delete,
412 KeyPerm::UseDevId,
413 KeyPerm::ReqForcedOp,
414 KeyPerm::GenUniqueId,
415 KeyPerm::Grant,
416 KeyPerm::GetInfo,
417 KeyPerm::Rebind,
418 KeyPerm::Update,
419 KeyPerm::Use,
420 KeyPerm::ConvertStorageKeyToEphemeral,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700421 ];
422
Janis Danisevskisa31dd9e2021-01-30 00:13:17 -0800423 const SYSTEM_SERVER_PERMISSIONS_NO_GRANT: KeyPermSet = key_perm_set![
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700424 KeyPerm::Delete,
425 KeyPerm::UseDevId,
426 // No KeyPerm::Grant
427 KeyPerm::GetInfo,
428 KeyPerm::Rebind,
429 KeyPerm::Update,
430 KeyPerm::Use,
Janis Danisevskisa31dd9e2021-01-30 00:13:17 -0800431 ];
432
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700433 const NOT_GRANT_PERMS: KeyPermSet = key_perm_set![
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700434 KeyPerm::ManageBlob,
435 KeyPerm::Delete,
436 KeyPerm::UseDevId,
437 KeyPerm::ReqForcedOp,
438 KeyPerm::GenUniqueId,
439 // No KeyPerm::Grant
440 KeyPerm::GetInfo,
441 KeyPerm::Rebind,
442 KeyPerm::Update,
443 KeyPerm::Use,
444 KeyPerm::ConvertStorageKeyToEphemeral,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700445 ];
446
447 const UNPRIV_PERMS: KeyPermSet = key_perm_set![
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700448 KeyPerm::Delete,
449 KeyPerm::GetInfo,
450 KeyPerm::Rebind,
451 KeyPerm::Update,
452 KeyPerm::Use,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700453 ];
454
455 /// The su_key namespace as defined in su.te and keystore_key_contexts of the
456 /// SePolicy (system/sepolicy).
457 const SU_KEY_NAMESPACE: i32 = 0;
458 /// The shell_key namespace as defined in shell.te and keystore_key_contexts of the
459 /// SePolicy (system/sepolicy).
460 const SHELL_KEY_NAMESPACE: i32 = 1;
461
462 pub fn test_getcon() -> Result<Context> {
463 Context::new("u:object_r:keystore:s0")
464 }
465
466 // This macro evaluates the given expression and checks that
467 // a) evaluated to Result::Err() and that
468 // b) the wrapped error is selinux::Error::perm() (permission denied).
469 // We use a macro here because a function would mask which invocation caused the failure.
470 //
471 // TODO b/164121720 Replace this macro with a function when `track_caller` is available.
472 macro_rules! assert_perm_failed {
473 ($test_function:expr) => {
474 let result = $test_function;
475 assert!(result.is_err(), "Permission check should have failed.");
476 assert_eq!(
477 Some(&selinux::Error::perm()),
478 result.err().unwrap().root_cause().downcast_ref::<selinux::Error>()
479 );
480 };
481 }
482
483 fn check_context() -> Result<(selinux::Context, i32, bool)> {
484 // Calling the non mocked selinux::getcon here intended.
485 let context = selinux::getcon()?;
486 match context.to_str().unwrap() {
487 "u:r:su:s0" => Ok((context, SU_KEY_NAMESPACE, true)),
488 "u:r:shell:s0" => Ok((context, SHELL_KEY_NAMESPACE, false)),
489 c => Err(anyhow!(format!(
490 "This test must be run as \"su\" or \"shell\". Current context: \"{}\"",
491 c
492 ))),
493 }
494 }
495
496 #[test]
497 fn check_keystore_permission_test() -> Result<()> {
498 let system_server_ctx = Context::new("u:r:system_server:s0")?;
Janis Danisevskisa916d992021-10-19 15:46:09 -0700499 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::AddAuth).is_ok());
500 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::ClearNs).is_ok());
501 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::GetState).is_ok());
502 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::Lock).is_ok());
503 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::Reset).is_ok());
504 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::Unlock).is_ok());
505 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::ChangeUser).is_ok());
506 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::ChangePassword).is_ok());
507 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::ClearUID).is_ok());
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700508 let shell_ctx = Context::new("u:r:shell:s0")?;
Janis Danisevskisa916d992021-10-19 15:46:09 -0700509 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::AddAuth));
510 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::ClearNs));
511 assert!(check_keystore_permission(&shell_ctx, KeystorePerm::GetState).is_ok());
512 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::List));
513 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::Lock));
514 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::Reset));
515 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::Unlock));
516 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::ChangeUser));
517 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::ChangePassword));
518 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::ClearUID));
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700519 Ok(())
520 }
521
522 #[test]
523 fn check_grant_permission_app() -> Result<()> {
524 let system_server_ctx = Context::new("u:r:system_server:s0")?;
525 let shell_ctx = Context::new("u:r:shell:s0")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700526 let key = KeyDescriptor { domain: Domain::APP, nspace: 0, alias: None, blob: None };
Janis Danisevskisa31dd9e2021-01-30 00:13:17 -0800527 check_grant_permission(&system_server_ctx, SYSTEM_SERVER_PERMISSIONS_NO_GRANT, &key)
528 .expect("Grant permission check failed.");
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700529
Janis Danisevskisa31dd9e2021-01-30 00:13:17 -0800530 // attempts to grant the grant permission must always fail even when privileged.
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700531 assert_perm_failed!(check_grant_permission(
532 &system_server_ctx,
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700533 KeyPerm::Grant.into(),
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700534 &key
535 ));
536 // unprivileged grant attempts always fail. shell does not have the grant permission.
537 assert_perm_failed!(check_grant_permission(&shell_ctx, UNPRIV_PERMS, &key));
538 Ok(())
539 }
540
541 #[test]
542 fn check_grant_permission_selinux() -> Result<()> {
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700543 let (sctx, namespace, is_su) = check_context()?;
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700544 let key = KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700545 domain: Domain::SELINUX,
546 nspace: namespace as i64,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700547 alias: None,
548 blob: None,
549 };
550 if is_su {
551 assert!(check_grant_permission(&sctx, NOT_GRANT_PERMS, &key).is_ok());
552 // attempts to grant the grant permission must always fail even when privileged.
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700553 assert_perm_failed!(check_grant_permission(&sctx, KeyPerm::Grant.into(), &key));
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700554 } else {
555 // unprivileged grant attempts always fail. shell does not have the grant permission.
556 assert_perm_failed!(check_grant_permission(&sctx, UNPRIV_PERMS, &key));
557 }
558 Ok(())
559 }
560
561 #[test]
562 fn check_key_permission_domain_grant() -> Result<()> {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700563 let key = KeyDescriptor { domain: Domain::GRANT, nspace: 0, alias: None, blob: None };
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700564
565 assert_perm_failed!(check_key_permission(
Janis Danisevskis45760022021-01-19 16:34:10 -0800566 0,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700567 &selinux::Context::new("ignored").unwrap(),
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700568 KeyPerm::Grant,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700569 &key,
570 &Some(UNPRIV_PERMS)
571 ));
572
573 check_key_permission(
Janis Danisevskis45760022021-01-19 16:34:10 -0800574 0,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700575 &selinux::Context::new("ignored").unwrap(),
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700576 KeyPerm::Use,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700577 &key,
578 &Some(ALL_PERMS),
579 )
580 }
581
582 #[test]
583 fn check_key_permission_domain_app() -> Result<()> {
584 let system_server_ctx = Context::new("u:r:system_server:s0")?;
585 let shell_ctx = Context::new("u:r:shell:s0")?;
586 let gmscore_app = Context::new("u:r:gmscore_app:s0")?;
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700587
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700588 let key = KeyDescriptor { domain: Domain::APP, nspace: 0, alias: None, blob: None };
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700589
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700590 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::Use, &key, &None).is_ok());
591 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::Delete, &key, &None).is_ok());
592 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::GetInfo, &key, &None).is_ok());
593 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::Rebind, &key, &None).is_ok());
594 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::Update, &key, &None).is_ok());
595 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::Grant, &key, &None).is_ok());
596 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::UseDevId, &key, &None).is_ok());
597 assert!(check_key_permission(0, &gmscore_app, KeyPerm::GenUniqueId, &key, &None).is_ok());
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700598
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700599 assert!(check_key_permission(0, &shell_ctx, KeyPerm::Use, &key, &None).is_ok());
600 assert!(check_key_permission(0, &shell_ctx, KeyPerm::Delete, &key, &None).is_ok());
601 assert!(check_key_permission(0, &shell_ctx, KeyPerm::GetInfo, &key, &None).is_ok());
602 assert!(check_key_permission(0, &shell_ctx, KeyPerm::Rebind, &key, &None).is_ok());
603 assert!(check_key_permission(0, &shell_ctx, KeyPerm::Update, &key, &None).is_ok());
604 assert_perm_failed!(check_key_permission(0, &shell_ctx, KeyPerm::Grant, &key, &None));
605 assert_perm_failed!(check_key_permission(0, &shell_ctx, KeyPerm::ReqForcedOp, &key, &None));
606 assert_perm_failed!(check_key_permission(0, &shell_ctx, KeyPerm::ManageBlob, &key, &None));
607 assert_perm_failed!(check_key_permission(0, &shell_ctx, KeyPerm::UseDevId, &key, &None));
608 assert_perm_failed!(check_key_permission(0, &shell_ctx, KeyPerm::GenUniqueId, &key, &None));
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700609
Janis Danisevskis45760022021-01-19 16:34:10 -0800610 // Also make sure that the permission fails if the caller is not the owner.
611 assert_perm_failed!(check_key_permission(
612 1, // the owner is 0
613 &system_server_ctx,
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700614 KeyPerm::Use,
Janis Danisevskis45760022021-01-19 16:34:10 -0800615 &key,
616 &None
617 ));
618 // Unless there was a grant.
619 assert!(check_key_permission(
620 1,
621 &system_server_ctx,
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700622 KeyPerm::Use,
Janis Danisevskis45760022021-01-19 16:34:10 -0800623 &key,
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700624 &Some(key_perm_set![KeyPerm::Use])
Janis Danisevskis45760022021-01-19 16:34:10 -0800625 )
626 .is_ok());
627 // But fail if the grant did not cover the requested permission.
628 assert_perm_failed!(check_key_permission(
629 1,
630 &system_server_ctx,
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700631 KeyPerm::Use,
Janis Danisevskis45760022021-01-19 16:34:10 -0800632 &key,
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700633 &Some(key_perm_set![KeyPerm::GetInfo])
Janis Danisevskis45760022021-01-19 16:34:10 -0800634 ));
635
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700636 Ok(())
637 }
638
639 #[test]
640 fn check_key_permission_domain_selinux() -> Result<()> {
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700641 let (sctx, namespace, is_su) = check_context()?;
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700642 let key = KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700643 domain: Domain::SELINUX,
644 nspace: namespace as i64,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700645 alias: None,
646 blob: None,
647 };
648
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700649 assert!(check_key_permission(0, &sctx, KeyPerm::Use, &key, &None).is_ok());
650 assert!(check_key_permission(0, &sctx, KeyPerm::Delete, &key, &None).is_ok());
651 assert!(check_key_permission(0, &sctx, KeyPerm::GetInfo, &key, &None).is_ok());
652 assert!(check_key_permission(0, &sctx, KeyPerm::Rebind, &key, &None).is_ok());
653 assert!(check_key_permission(0, &sctx, KeyPerm::Update, &key, &None).is_ok());
Chris Wailes3877f292021-07-26 19:24:18 -0700654
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700655 if is_su {
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700656 assert!(check_key_permission(0, &sctx, KeyPerm::Grant, &key, &None).is_ok());
657 assert!(check_key_permission(0, &sctx, KeyPerm::ManageBlob, &key, &None).is_ok());
658 assert!(check_key_permission(0, &sctx, KeyPerm::UseDevId, &key, &None).is_ok());
659 assert!(check_key_permission(0, &sctx, KeyPerm::GenUniqueId, &key, &None).is_ok());
660 assert!(check_key_permission(0, &sctx, KeyPerm::ReqForcedOp, &key, &None).is_ok());
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700661 } else {
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700662 assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::Grant, &key, &None));
663 assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::ReqForcedOp, &key, &None));
664 assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::ManageBlob, &key, &None));
665 assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::UseDevId, &key, &None));
666 assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::GenUniqueId, &key, &None));
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700667 }
668 Ok(())
669 }
670
671 #[test]
672 fn check_key_permission_domain_blob() -> Result<()> {
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700673 let (sctx, namespace, is_su) = check_context()?;
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700674 let key = KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700675 domain: Domain::BLOB,
676 nspace: namespace as i64,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700677 alias: None,
678 blob: None,
679 };
680
681 if is_su {
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700682 check_key_permission(0, &sctx, KeyPerm::Use, &key, &None)
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700683 } else {
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700684 assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::Use, &key, &None));
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700685 Ok(())
686 }
687 }
688
689 #[test]
690 fn check_key_permission_domain_key_id() -> Result<()> {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700691 let key = KeyDescriptor { domain: Domain::KEY_ID, nspace: 0, alias: None, blob: None };
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700692
693 assert_eq!(
694 Some(&KsError::sys()),
695 check_key_permission(
Janis Danisevskis45760022021-01-19 16:34:10 -0800696 0,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700697 &selinux::Context::new("ignored").unwrap(),
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700698 KeyPerm::Use,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700699 &key,
700 &None
701 )
702 .err()
703 .unwrap()
704 .root_cause()
705 .downcast_ref::<KsError>()
706 );
707 Ok(())
708 }
709
710 #[test]
711 fn key_perm_set_all_test() {
712 let v = key_perm_set![
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700713 KeyPerm::ManageBlob,
714 KeyPerm::Delete,
715 KeyPerm::UseDevId,
716 KeyPerm::ReqForcedOp,
717 KeyPerm::GenUniqueId,
718 KeyPerm::Grant,
719 KeyPerm::GetInfo,
720 KeyPerm::Rebind,
721 KeyPerm::Update,
722 KeyPerm::Use // Test if the macro accepts missing comma at the end of the list.
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700723 ];
724 let mut i = v.into_iter();
Janis Danisevskis56af0312021-10-18 16:11:41 -0700725 assert_eq!(i.next().unwrap().name(), "delete");
726 assert_eq!(i.next().unwrap().name(), "gen_unique_id");
727 assert_eq!(i.next().unwrap().name(), "get_info");
728 assert_eq!(i.next().unwrap().name(), "grant");
729 assert_eq!(i.next().unwrap().name(), "manage_blob");
730 assert_eq!(i.next().unwrap().name(), "rebind");
731 assert_eq!(i.next().unwrap().name(), "req_forced_op");
732 assert_eq!(i.next().unwrap().name(), "update");
733 assert_eq!(i.next().unwrap().name(), "use");
734 assert_eq!(i.next().unwrap().name(), "use_dev_id");
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700735 assert_eq!(None, i.next());
736 }
737 #[test]
738 fn key_perm_set_sparse_test() {
739 let v = key_perm_set![
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700740 KeyPerm::ManageBlob,
741 KeyPerm::ReqForcedOp,
742 KeyPerm::GenUniqueId,
743 KeyPerm::Update,
744 KeyPerm::Use, // Test if macro accepts the comma at the end of the list.
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700745 ];
746 let mut i = v.into_iter();
Janis Danisevskis56af0312021-10-18 16:11:41 -0700747 assert_eq!(i.next().unwrap().name(), "gen_unique_id");
748 assert_eq!(i.next().unwrap().name(), "manage_blob");
749 assert_eq!(i.next().unwrap().name(), "req_forced_op");
750 assert_eq!(i.next().unwrap().name(), "update");
751 assert_eq!(i.next().unwrap().name(), "use");
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700752 assert_eq!(None, i.next());
753 }
754 #[test]
755 fn key_perm_set_empty_test() {
756 let v = key_perm_set![];
757 let mut i = v.into_iter();
758 assert_eq!(None, i.next());
759 }
760 #[test]
761 fn key_perm_set_include_subset_test() {
762 let v1 = key_perm_set![
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700763 KeyPerm::ManageBlob,
764 KeyPerm::Delete,
765 KeyPerm::UseDevId,
766 KeyPerm::ReqForcedOp,
767 KeyPerm::GenUniqueId,
768 KeyPerm::Grant,
769 KeyPerm::GetInfo,
770 KeyPerm::Rebind,
771 KeyPerm::Update,
772 KeyPerm::Use,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700773 ];
774 let v2 = key_perm_set![
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700775 KeyPerm::ManageBlob,
776 KeyPerm::Delete,
777 KeyPerm::Rebind,
778 KeyPerm::Update,
779 KeyPerm::Use,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700780 ];
781 assert!(v1.includes(v2));
782 assert!(!v2.includes(v1));
783 }
784 #[test]
785 fn key_perm_set_include_equal_test() {
786 let v1 = key_perm_set![
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700787 KeyPerm::ManageBlob,
788 KeyPerm::Delete,
789 KeyPerm::Rebind,
790 KeyPerm::Update,
791 KeyPerm::Use,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700792 ];
793 let v2 = key_perm_set![
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700794 KeyPerm::ManageBlob,
795 KeyPerm::Delete,
796 KeyPerm::Rebind,
797 KeyPerm::Update,
798 KeyPerm::Use,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700799 ];
800 assert!(v1.includes(v2));
801 assert!(v2.includes(v1));
802 }
803 #[test]
804 fn key_perm_set_include_overlap_test() {
805 let v1 = key_perm_set![
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700806 KeyPerm::ManageBlob,
807 KeyPerm::Delete,
808 KeyPerm::Grant, // only in v1
809 KeyPerm::Rebind,
810 KeyPerm::Update,
811 KeyPerm::Use,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700812 ];
813 let v2 = key_perm_set![
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700814 KeyPerm::ManageBlob,
815 KeyPerm::Delete,
816 KeyPerm::ReqForcedOp, // only in v2
817 KeyPerm::Rebind,
818 KeyPerm::Update,
819 KeyPerm::Use,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700820 ];
821 assert!(!v1.includes(v2));
822 assert!(!v2.includes(v1));
823 }
824 #[test]
825 fn key_perm_set_include_no_overlap_test() {
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700826 let v1 = key_perm_set![KeyPerm::ManageBlob, KeyPerm::Delete, KeyPerm::Grant,];
827 let v2 =
828 key_perm_set![KeyPerm::ReqForcedOp, KeyPerm::Rebind, KeyPerm::Update, KeyPerm::Use,];
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700829 assert!(!v1.includes(v2));
830 assert!(!v2.includes(v1));
831 }
832}