blob: d9bdf79174b693b4b2380efc71549bdc808304cd [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;
29use lazy_static::lazy_static;
Janis Danisevskis56af0312021-10-18 16:11:41 -070030use selinux::{implement_class, Backend, ClassPermission};
Janis Danisevskis78bd48c2020-07-21 12:27:13 -070031use std::cmp::PartialEq;
32use std::convert::From;
Janis Danisevskis935e6c62020-08-18 12:52:27 -070033use std::ffi::CStr;
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
Janis Danisevskis4ad056f2020-08-05 19:46:46 +000041lazy_static! {
42 // Panicking here is allowed because keystore cannot function without this backend
43 // and it would happen early and indicate a gross misconfiguration of the device.
44 static ref KEYSTORE2_KEY_LABEL_BACKEND: selinux::KeystoreKeyBackend =
45 selinux::KeystoreKeyBackend::new().unwrap();
46}
47
48fn lookup_keystore2_key_context(namespace: i64) -> anyhow::Result<selinux::Context> {
49 KEYSTORE2_KEY_LABEL_BACKEND.lookup(&namespace.to_string())
50}
51
Janis Danisevskis39d57e72021-10-19 16:56:20 -070052implement_class!(
Janis Danisevskis78bd48c2020-07-21 12:27:13 -070053 /// KeyPerm provides a convenient abstraction from the SELinux class `keystore2_key`.
54 /// At the same time it maps `KeyPermissions` from the Keystore 2.0 AIDL Grant interface to
Janis Danisevskis39d57e72021-10-19 16:56:20 -070055 /// the SELinux permissions.
56 #[repr(i32)]
57 #[selinux(class_name = keystore2_key)]
Chris Wailes263de9f2022-08-11 15:00:51 -070058 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
Janis Danisevskis39d57e72021-10-19 16:56:20 -070059 pub enum KeyPerm {
60 /// Checked when convert_storage_key_to_ephemeral is called.
61 #[selinux(name = convert_storage_key_to_ephemeral)]
62 ConvertStorageKeyToEphemeral = KeyPermission::CONVERT_STORAGE_KEY_TO_EPHEMERAL.0,
63 /// Checked when the caller tries do delete a key.
64 #[selinux(name = delete)]
65 Delete = KeyPermission::DELETE.0,
66 /// Checked when the caller tries to use a unique id.
67 #[selinux(name = gen_unique_id)]
68 GenUniqueId = KeyPermission::GEN_UNIQUE_ID.0,
69 /// Checked when the caller tries to load a key.
70 #[selinux(name = get_info)]
71 GetInfo = KeyPermission::GET_INFO.0,
72 /// Checked when the caller attempts to grant a key to another uid.
73 /// Also used for gating key migration attempts.
74 #[selinux(name = grant)]
75 Grant = KeyPermission::GRANT.0,
76 /// Checked when the caller attempts to use Domain::BLOB.
77 #[selinux(name = manage_blob)]
78 ManageBlob = KeyPermission::MANAGE_BLOB.0,
79 /// Checked when the caller tries to create a key which implies rebinding
80 /// an alias to the new key.
81 #[selinux(name = rebind)]
82 Rebind = KeyPermission::REBIND.0,
83 /// Checked when the caller attempts to create a forced operation.
84 #[selinux(name = req_forced_op)]
85 ReqForcedOp = KeyPermission::REQ_FORCED_OP.0,
86 /// Checked when the caller attempts to update public key artifacts.
87 #[selinux(name = update)]
88 Update = KeyPermission::UPDATE.0,
89 /// Checked when the caller attempts to use a private or public key.
90 #[selinux(name = use)]
91 Use = KeyPermission::USE.0,
Eran Messeri653932e2022-06-14 17:04:10 +010092 /// Does nothing, and is not checked. For use of device identifiers,
93 /// the caller must hold the READ_PRIVILEGED_PHONE_STATE Android
94 /// permission.
Janis Danisevskis39d57e72021-10-19 16:56:20 -070095 #[selinux(name = use_dev_id)]
96 UseDevId = KeyPermission::USE_DEV_ID.0,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -070097 }
98);
99
Janis Danisevskis56af0312021-10-18 16:11:41 -0700100implement_class!(
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700101 /// KeystorePerm provides a convenient abstraction from the SELinux class `keystore2`.
102 /// Using the implement_permission macro we get the same features as `KeyPerm`.
Janis Danisevskis56af0312021-10-18 16:11:41 -0700103 #[selinux(class_name = keystore2)]
Chris Wailes263de9f2022-08-11 15:00:51 -0700104 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700105 pub enum KeystorePerm {
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700106 /// Checked when a new auth token is installed.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700107 #[selinux(name = add_auth)]
108 AddAuth,
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700109 /// Checked when an app is uninstalled or wiped.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700110 #[selinux(name = clear_ns)]
111 ClearNs,
Hasini Gunasinghe9ee18412021-03-11 20:12:44 +0000112 /// Checked when the user state is queried from Keystore 2.0.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700113 #[selinux(name = get_state)]
114 GetState,
Janis Danisevskisee10b5f2020-09-22 16:42:35 -0700115 /// Checked when Keystore 2.0 is asked to list a namespace that the caller
116 /// does not have the get_info permission for.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700117 #[selinux(name = list)]
118 List,
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700119 /// Checked when Keystore 2.0 gets locked.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700120 #[selinux(name = lock)]
121 Lock,
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700122 /// Checked when Keystore 2.0 shall be reset.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700123 #[selinux(name = reset)]
124 Reset,
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700125 /// Checked when Keystore 2.0 shall be unlocked.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700126 #[selinux(name = unlock)]
127 Unlock,
Hasini Gunasinghe803c2d42021-01-27 00:48:40 +0000128 /// Checked when user is added or removed.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700129 #[selinux(name = change_user)]
130 ChangeUser,
Hasini Gunasinghe803c2d42021-01-27 00:48:40 +0000131 /// Checked when password of the user is changed.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700132 #[selinux(name = change_password)]
133 ChangePassword,
Hasini Gunasinghe803c2d42021-01-27 00:48:40 +0000134 /// Checked when a UID is cleared.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700135 #[selinux(name = clear_uid)]
136 ClearUID,
Hasini Gunasinghe5fc95252020-12-04 00:35:08 +0000137 /// Checked when Credstore calls IKeystoreAuthorization to obtain auth tokens.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700138 #[selinux(name = get_auth_token)]
139 GetAuthToken,
Satya Tangirala5b9e5b12021-03-09 12:54:21 -0800140 /// Checked when earlyBootEnded() is called.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700141 #[selinux(name = early_boot_ended)]
142 EarlyBootEnded,
Janis Danisevskis333b7c02021-03-23 18:57:41 -0700143 /// Checked when IKeystoreMaintenance::onDeviceOffBody is called.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700144 #[selinux(name = report_off_body)]
145 ReportOffBody,
146 /// Checked when IkeystoreMetrics::pullMetrics is called.
147 #[selinux(name = pull_metrics)]
148 PullMetrics,
Paul Crowley46c703e2021-08-06 15:13:53 -0700149 /// Checked when IKeystoreMaintenance::deleteAllKeys is called.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700150 #[selinux(name = delete_all_keys)]
151 DeleteAllKeys,
Seth Moore7ee79f92021-12-07 11:42:49 -0800152 /// Checked on calls to IRemotelyProvisionedKeyPool::getAttestationKey
153 #[selinux(name = get_attestation_key)]
154 GetAttestationKey,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700155 }
156);
157
158/// Represents a set of `KeyPerm` permissions.
159/// `IntoIterator` is implemented for this struct allowing the iteration through all the
160/// permissions in the set.
161/// It also implements a function `includes(self, other)` that checks if the permissions
162/// in `other` are included in `self`.
163///
164/// KeyPermSet can be created with the macro `key_perm_set![]`.
165///
166/// ## Example
167/// ```
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700168/// let perms1 = key_perm_set![KeyPerm::Use, KeyPerm::ManageBlob, KeyPerm::Grant];
169/// let perms2 = key_perm_set![KeyPerm::Use, KeyPerm::ManageBlob];
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700170///
171/// assert!(perms1.includes(perms2))
172/// assert!(!perms2.includes(perms1))
173///
174/// let i = perms1.into_iter();
175/// // iteration in ascending order of the permission's numeric representation.
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700176/// assert_eq(Some(KeyPerm::ManageBlob), i.next());
177/// assert_eq(Some(KeyPerm::Grant), i.next());
178/// assert_eq(Some(KeyPerm::Use), i.next());
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700179/// assert_eq(None, i.next());
180/// ```
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700181#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
182pub struct KeyPermSet(pub i32);
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700183
184mod perm {
185 use super::*;
186
187 pub struct IntoIter {
188 vec: KeyPermSet,
189 pos: u8,
190 }
191
192 impl IntoIter {
193 pub fn new(v: KeyPermSet) -> Self {
194 Self { vec: v, pos: 0 }
195 }
196 }
197
198 impl std::iter::Iterator for IntoIter {
199 type Item = KeyPerm;
200
201 fn next(&mut self) -> Option<Self::Item> {
202 loop {
203 if self.pos == 32 {
204 return None;
205 }
206 let p = self.vec.0 & (1 << self.pos);
207 self.pos += 1;
208 if p != 0 {
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700209 return Some(KeyPerm::from(p));
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700210 }
211 }
212 }
213 }
214}
215
216impl From<KeyPerm> for KeyPermSet {
217 fn from(p: KeyPerm) -> Self {
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700218 Self(p as i32)
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700219 }
220}
221
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700222/// allow conversion from the AIDL wire type i32 to a permission set.
223impl From<i32> for KeyPermSet {
224 fn from(p: i32) -> Self {
225 Self(p)
226 }
227}
228
229impl From<KeyPermSet> for i32 {
230 fn from(p: KeyPermSet) -> i32 {
231 p.0
232 }
233}
234
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700235impl KeyPermSet {
236 /// Returns true iff this permission set has all of the permissions that are in `other`.
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700237 pub fn includes<T: Into<KeyPermSet>>(&self, other: T) -> bool {
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700238 let o: KeyPermSet = other.into();
239 (self.0 & o.0) == o.0
240 }
241}
242
243/// This macro can be used to create a `KeyPermSet` from a list of `KeyPerm` values.
244///
245/// ## Example
246/// ```
247/// let v = key_perm_set![Perm::delete(), Perm::manage_blob()];
248/// ```
249#[macro_export]
250macro_rules! key_perm_set {
251 () => { KeyPermSet(0) };
252 ($head:expr $(, $tail:expr)* $(,)?) => {
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700253 KeyPermSet($head as i32 $(| $tail as i32)*)
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700254 };
255}
256
257impl IntoIterator for KeyPermSet {
258 type Item = KeyPerm;
259 type IntoIter = perm::IntoIter;
260
261 fn into_iter(self) -> Self::IntoIter {
262 Self::IntoIter::new(self)
263 }
264}
265
Janis Danisevskis56af0312021-10-18 16:11:41 -0700266/// Uses `selinux::check_permission` to check if the given caller context `caller_cxt` may access
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700267/// the given permision `perm` of the `keystore2` security class.
Janis Danisevskis935e6c62020-08-18 12:52:27 -0700268pub fn check_keystore_permission(caller_ctx: &CStr, perm: KeystorePerm) -> anyhow::Result<()> {
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700269 let target_context = getcon().context("check_keystore_permission: getcon failed.")?;
Janis Danisevskis56af0312021-10-18 16:11:41 -0700270 selinux::check_permission(caller_ctx, &target_context, perm)
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700271}
272
Janis Danisevskis56af0312021-10-18 16:11:41 -0700273/// Uses `selinux::check_permission` to check if the given caller context `caller_cxt` has
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700274/// all the permissions indicated in `access_vec` for the target domain indicated by the key
275/// descriptor `key` in the security class `keystore2_key`.
276///
277/// Also checks if the caller has the grant permission for the given target domain.
278///
279/// Attempts to grant the grant permission are always denied.
280///
281/// The only viable target domains are
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700282/// * `Domain::APP` in which case u:r:keystore:s0 is used as target context and
283/// * `Domain::SELINUX` in which case the `key.nspace` parameter is looked up in
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700284/// SELinux keystore key backend, and the result is used
285/// as target context.
286pub fn check_grant_permission(
Janis Danisevskis935e6c62020-08-18 12:52:27 -0700287 caller_ctx: &CStr,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700288 access_vec: KeyPermSet,
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700289 key: &KeyDescriptor,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700290) -> anyhow::Result<()> {
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700291 let target_context = match key.domain {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700292 Domain::APP => getcon().context("check_grant_permission: getcon failed.")?,
293 Domain::SELINUX => lookup_keystore2_key_context(key.nspace)
294 .context("check_grant_permission: Domain::SELINUX: Failed to lookup namespace.")?,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700295 _ => return Err(KsError::sys()).context(format!("Cannot grant {:?}.", key.domain)),
296 };
297
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700298 selinux::check_permission(caller_ctx, &target_context, KeyPerm::Grant)
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700299 .context("Grant permission is required when granting.")?;
300
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700301 if access_vec.includes(KeyPerm::Grant) {
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700302 return Err(selinux::Error::perm()).context("Grant permission cannot be granted.");
303 }
304
305 for p in access_vec.into_iter() {
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000306 selinux::check_permission(caller_ctx, &target_context, p).context(ks_err!(
307 "check_permission failed. \
Janis Danisevskis56af0312021-10-18 16:11:41 -0700308 The caller may have tried to grant a permission that they don't possess. {:?}",
309 p
310 ))?
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700311 }
312 Ok(())
313}
314
Janis Danisevskis56af0312021-10-18 16:11:41 -0700315/// Uses `selinux::check_permission` to check if the given caller context `caller_cxt`
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700316/// has the permissions indicated by `perm` for the target domain indicated by the key
317/// descriptor `key` in the security class `keystore2_key`.
318///
319/// The behavior differs slightly depending on the selected target domain:
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700320/// * `Domain::APP` u:r:keystore:s0 is used as target context.
321/// * `Domain::SELINUX` `key.nspace` parameter is looked up in the SELinux keystore key
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700322/// backend, and the result is used as target context.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700323/// * `Domain::BLOB` Same as SELinux but the "manage_blob" permission is always checked additionally
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700324/// to the one supplied in `perm`.
Janis Danisevskis56af0312021-10-18 16:11:41 -0700325/// * `Domain::GRANT` Does not use selinux::check_permission. Instead the `access_vector`
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700326/// parameter is queried for permission, which must be supplied in this case.
327///
328/// ## Return values.
329/// * Ok(()) If the requested permissions were granted.
330/// * Err(selinux::Error::perm()) If the requested permissions were denied.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700331/// * Err(KsError::sys()) This error is produced if `Domain::GRANT` is selected but no `access_vec`
332/// was supplied. It is also produced if `Domain::KEY_ID` was selected, and
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700333/// on various unexpected backend failures.
334pub fn check_key_permission(
Janis Danisevskis45760022021-01-19 16:34:10 -0800335 caller_uid: u32,
Janis Danisevskis935e6c62020-08-18 12:52:27 -0700336 caller_ctx: &CStr,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700337 perm: KeyPerm,
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700338 key: &KeyDescriptor,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700339 access_vector: &Option<KeyPermSet>,
340) -> anyhow::Result<()> {
Janis Danisevskis45760022021-01-19 16:34:10 -0800341 // If an access vector was supplied, the key is either accessed by GRANT or by KEY_ID.
342 // In the former case, key.domain was set to GRANT and we check the failure cases
343 // further below. If the access is requested by KEY_ID, key.domain would have been
344 // resolved to APP or SELINUX depending on where the key actually resides.
345 // Either way we can return here immediately if the access vector covers the requested
346 // permission. If it does not, we can still check if the caller has access by means of
347 // ownership.
348 if let Some(access_vector) = access_vector {
349 if access_vector.includes(perm) {
350 return Ok(());
351 }
352 }
353
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700354 let target_context = match key.domain {
355 // apps get the default keystore context
Janis Danisevskis45760022021-01-19 16:34:10 -0800356 Domain::APP => {
357 if caller_uid as i64 != key.nspace {
358 return Err(selinux::Error::perm())
359 .context("Trying to access key without ownership.");
360 }
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000361 getcon().context(ks_err!("getcon failed."))?
Janis Danisevskis45760022021-01-19 16:34:10 -0800362 }
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700363 Domain::SELINUX => lookup_keystore2_key_context(key.nspace)
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000364 .context(ks_err!("Domain::SELINUX: Failed to lookup namespace."))?,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700365 Domain::GRANT => {
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700366 match access_vector {
Janis Danisevskis45760022021-01-19 16:34:10 -0800367 Some(_) => {
368 return Err(selinux::Error::perm())
Janis Danisevskis56af0312021-10-18 16:11:41 -0700369 .context(format!("\"{}\" not granted", perm.name()));
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700370 }
371 None => {
372 // If DOMAIN_GRANT was selected an access vector must be supplied.
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000373 return Err(KsError::sys()).context(ks_err!(
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700374 "Cannot check permission for Domain::GRANT without access vector.",
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000375 ));
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700376 }
377 }
378 }
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700379 Domain::KEY_ID => {
380 // We should never be called with `Domain::KEY_ID. The database
381 // lookup should have converted this into one of `Domain::APP`
382 // or `Domain::SELINUX`.
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000383 return Err(KsError::sys())
384 .context(ks_err!("Cannot check permission for Domain::KEY_ID.",));
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700385 }
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700386 Domain::BLOB => {
387 let tctx = lookup_keystore2_key_context(key.nspace)
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000388 .context(ks_err!("Domain::BLOB: Failed to lookup namespace."))?;
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700389 // If DOMAIN_KEY_BLOB was specified, we check for the "manage_blob"
390 // permission in addition to the requested permission.
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700391 selinux::check_permission(caller_ctx, &tctx, KeyPerm::ManageBlob)?;
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700392
393 tctx
394 }
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700395 _ => {
Rajesh Nyamagoudcaee93e2022-05-26 00:20:38 +0000396 return Err(KsError::Rc(ResponseCode::INVALID_ARGUMENT))
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700397 .context(format!("Unknown domain value: \"{:?}\".", key.domain))
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700398 }
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700399 };
400
Janis Danisevskis56af0312021-10-18 16:11:41 -0700401 selinux::check_permission(caller_ctx, &target_context, perm)
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700402}
403
404#[cfg(test)]
405mod tests {
406 use super::*;
407 use anyhow::anyhow;
408 use anyhow::Result;
409 use keystore2_selinux::*;
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700410
411 const ALL_PERMS: KeyPermSet = key_perm_set![
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700412 KeyPerm::ManageBlob,
413 KeyPerm::Delete,
414 KeyPerm::UseDevId,
415 KeyPerm::ReqForcedOp,
416 KeyPerm::GenUniqueId,
417 KeyPerm::Grant,
418 KeyPerm::GetInfo,
419 KeyPerm::Rebind,
420 KeyPerm::Update,
421 KeyPerm::Use,
422 KeyPerm::ConvertStorageKeyToEphemeral,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700423 ];
424
Janis Danisevskisa31dd9e2021-01-30 00:13:17 -0800425 const SYSTEM_SERVER_PERMISSIONS_NO_GRANT: KeyPermSet = key_perm_set![
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700426 KeyPerm::Delete,
427 KeyPerm::UseDevId,
428 // No KeyPerm::Grant
429 KeyPerm::GetInfo,
430 KeyPerm::Rebind,
431 KeyPerm::Update,
432 KeyPerm::Use,
Janis Danisevskisa31dd9e2021-01-30 00:13:17 -0800433 ];
434
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700435 const NOT_GRANT_PERMS: KeyPermSet = key_perm_set![
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700436 KeyPerm::ManageBlob,
437 KeyPerm::Delete,
438 KeyPerm::UseDevId,
439 KeyPerm::ReqForcedOp,
440 KeyPerm::GenUniqueId,
441 // No KeyPerm::Grant
442 KeyPerm::GetInfo,
443 KeyPerm::Rebind,
444 KeyPerm::Update,
445 KeyPerm::Use,
446 KeyPerm::ConvertStorageKeyToEphemeral,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700447 ];
448
449 const UNPRIV_PERMS: KeyPermSet = key_perm_set![
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700450 KeyPerm::Delete,
451 KeyPerm::GetInfo,
452 KeyPerm::Rebind,
453 KeyPerm::Update,
454 KeyPerm::Use,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700455 ];
456
457 /// The su_key namespace as defined in su.te and keystore_key_contexts of the
458 /// SePolicy (system/sepolicy).
459 const SU_KEY_NAMESPACE: i32 = 0;
460 /// The shell_key namespace as defined in shell.te and keystore_key_contexts of the
461 /// SePolicy (system/sepolicy).
462 const SHELL_KEY_NAMESPACE: i32 = 1;
463
464 pub fn test_getcon() -> Result<Context> {
465 Context::new("u:object_r:keystore:s0")
466 }
467
468 // This macro evaluates the given expression and checks that
469 // a) evaluated to Result::Err() and that
470 // b) the wrapped error is selinux::Error::perm() (permission denied).
471 // We use a macro here because a function would mask which invocation caused the failure.
472 //
473 // TODO b/164121720 Replace this macro with a function when `track_caller` is available.
474 macro_rules! assert_perm_failed {
475 ($test_function:expr) => {
476 let result = $test_function;
477 assert!(result.is_err(), "Permission check should have failed.");
478 assert_eq!(
479 Some(&selinux::Error::perm()),
480 result.err().unwrap().root_cause().downcast_ref::<selinux::Error>()
481 );
482 };
483 }
484
485 fn check_context() -> Result<(selinux::Context, i32, bool)> {
486 // Calling the non mocked selinux::getcon here intended.
487 let context = selinux::getcon()?;
488 match context.to_str().unwrap() {
489 "u:r:su:s0" => Ok((context, SU_KEY_NAMESPACE, true)),
490 "u:r:shell:s0" => Ok((context, SHELL_KEY_NAMESPACE, false)),
491 c => Err(anyhow!(format!(
492 "This test must be run as \"su\" or \"shell\". Current context: \"{}\"",
493 c
494 ))),
495 }
496 }
497
498 #[test]
499 fn check_keystore_permission_test() -> Result<()> {
500 let system_server_ctx = Context::new("u:r:system_server:s0")?;
Janis Danisevskisa916d992021-10-19 15:46:09 -0700501 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::AddAuth).is_ok());
502 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::ClearNs).is_ok());
503 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::GetState).is_ok());
504 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::Lock).is_ok());
505 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::Reset).is_ok());
506 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::Unlock).is_ok());
507 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::ChangeUser).is_ok());
508 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::ChangePassword).is_ok());
509 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::ClearUID).is_ok());
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700510 let shell_ctx = Context::new("u:r:shell:s0")?;
Janis Danisevskisa916d992021-10-19 15:46:09 -0700511 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::AddAuth));
512 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::ClearNs));
513 assert!(check_keystore_permission(&shell_ctx, KeystorePerm::GetState).is_ok());
514 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::List));
515 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::Lock));
516 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::Reset));
517 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::Unlock));
518 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::ChangeUser));
519 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::ChangePassword));
520 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::ClearUID));
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700521 Ok(())
522 }
523
524 #[test]
525 fn check_grant_permission_app() -> Result<()> {
526 let system_server_ctx = Context::new("u:r:system_server:s0")?;
527 let shell_ctx = Context::new("u:r:shell:s0")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700528 let key = KeyDescriptor { domain: Domain::APP, nspace: 0, alias: None, blob: None };
Janis Danisevskisa31dd9e2021-01-30 00:13:17 -0800529 check_grant_permission(&system_server_ctx, SYSTEM_SERVER_PERMISSIONS_NO_GRANT, &key)
530 .expect("Grant permission check failed.");
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700531
Janis Danisevskisa31dd9e2021-01-30 00:13:17 -0800532 // attempts to grant the grant permission must always fail even when privileged.
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700533 assert_perm_failed!(check_grant_permission(
534 &system_server_ctx,
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700535 KeyPerm::Grant.into(),
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700536 &key
537 ));
538 // unprivileged grant attempts always fail. shell does not have the grant permission.
539 assert_perm_failed!(check_grant_permission(&shell_ctx, UNPRIV_PERMS, &key));
540 Ok(())
541 }
542
543 #[test]
544 fn check_grant_permission_selinux() -> Result<()> {
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700545 let (sctx, namespace, is_su) = check_context()?;
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700546 let key = KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700547 domain: Domain::SELINUX,
548 nspace: namespace as i64,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700549 alias: None,
550 blob: None,
551 };
552 if is_su {
553 assert!(check_grant_permission(&sctx, NOT_GRANT_PERMS, &key).is_ok());
554 // attempts to grant the grant permission must always fail even when privileged.
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700555 assert_perm_failed!(check_grant_permission(&sctx, KeyPerm::Grant.into(), &key));
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700556 } else {
557 // unprivileged grant attempts always fail. shell does not have the grant permission.
558 assert_perm_failed!(check_grant_permission(&sctx, UNPRIV_PERMS, &key));
559 }
560 Ok(())
561 }
562
563 #[test]
564 fn check_key_permission_domain_grant() -> Result<()> {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700565 let key = KeyDescriptor { domain: Domain::GRANT, nspace: 0, alias: None, blob: None };
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700566
567 assert_perm_failed!(check_key_permission(
Janis Danisevskis45760022021-01-19 16:34:10 -0800568 0,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700569 &selinux::Context::new("ignored").unwrap(),
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700570 KeyPerm::Grant,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700571 &key,
572 &Some(UNPRIV_PERMS)
573 ));
574
575 check_key_permission(
Janis Danisevskis45760022021-01-19 16:34:10 -0800576 0,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700577 &selinux::Context::new("ignored").unwrap(),
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700578 KeyPerm::Use,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700579 &key,
580 &Some(ALL_PERMS),
581 )
582 }
583
584 #[test]
585 fn check_key_permission_domain_app() -> Result<()> {
586 let system_server_ctx = Context::new("u:r:system_server:s0")?;
587 let shell_ctx = Context::new("u:r:shell:s0")?;
588 let gmscore_app = Context::new("u:r:gmscore_app:s0")?;
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700589
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700590 let key = KeyDescriptor { domain: Domain::APP, nspace: 0, alias: None, blob: None };
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700591
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700592 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::Use, &key, &None).is_ok());
593 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::Delete, &key, &None).is_ok());
594 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::GetInfo, &key, &None).is_ok());
595 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::Rebind, &key, &None).is_ok());
596 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::Update, &key, &None).is_ok());
597 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::Grant, &key, &None).is_ok());
598 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::UseDevId, &key, &None).is_ok());
599 assert!(check_key_permission(0, &gmscore_app, KeyPerm::GenUniqueId, &key, &None).is_ok());
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700600
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700601 assert!(check_key_permission(0, &shell_ctx, KeyPerm::Use, &key, &None).is_ok());
602 assert!(check_key_permission(0, &shell_ctx, KeyPerm::Delete, &key, &None).is_ok());
603 assert!(check_key_permission(0, &shell_ctx, KeyPerm::GetInfo, &key, &None).is_ok());
604 assert!(check_key_permission(0, &shell_ctx, KeyPerm::Rebind, &key, &None).is_ok());
605 assert!(check_key_permission(0, &shell_ctx, KeyPerm::Update, &key, &None).is_ok());
606 assert_perm_failed!(check_key_permission(0, &shell_ctx, KeyPerm::Grant, &key, &None));
607 assert_perm_failed!(check_key_permission(0, &shell_ctx, KeyPerm::ReqForcedOp, &key, &None));
608 assert_perm_failed!(check_key_permission(0, &shell_ctx, KeyPerm::ManageBlob, &key, &None));
609 assert_perm_failed!(check_key_permission(0, &shell_ctx, KeyPerm::UseDevId, &key, &None));
610 assert_perm_failed!(check_key_permission(0, &shell_ctx, KeyPerm::GenUniqueId, &key, &None));
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700611
Janis Danisevskis45760022021-01-19 16:34:10 -0800612 // Also make sure that the permission fails if the caller is not the owner.
613 assert_perm_failed!(check_key_permission(
614 1, // the owner is 0
615 &system_server_ctx,
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700616 KeyPerm::Use,
Janis Danisevskis45760022021-01-19 16:34:10 -0800617 &key,
618 &None
619 ));
620 // Unless there was a grant.
621 assert!(check_key_permission(
622 1,
623 &system_server_ctx,
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700624 KeyPerm::Use,
Janis Danisevskis45760022021-01-19 16:34:10 -0800625 &key,
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700626 &Some(key_perm_set![KeyPerm::Use])
Janis Danisevskis45760022021-01-19 16:34:10 -0800627 )
628 .is_ok());
629 // But fail if the grant did not cover the requested permission.
630 assert_perm_failed!(check_key_permission(
631 1,
632 &system_server_ctx,
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700633 KeyPerm::Use,
Janis Danisevskis45760022021-01-19 16:34:10 -0800634 &key,
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700635 &Some(key_perm_set![KeyPerm::GetInfo])
Janis Danisevskis45760022021-01-19 16:34:10 -0800636 ));
637
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700638 Ok(())
639 }
640
641 #[test]
642 fn check_key_permission_domain_selinux() -> Result<()> {
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700643 let (sctx, namespace, is_su) = check_context()?;
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700644 let key = KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700645 domain: Domain::SELINUX,
646 nspace: namespace as i64,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700647 alias: None,
648 blob: None,
649 };
650
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700651 assert!(check_key_permission(0, &sctx, KeyPerm::Use, &key, &None).is_ok());
652 assert!(check_key_permission(0, &sctx, KeyPerm::Delete, &key, &None).is_ok());
653 assert!(check_key_permission(0, &sctx, KeyPerm::GetInfo, &key, &None).is_ok());
654 assert!(check_key_permission(0, &sctx, KeyPerm::Rebind, &key, &None).is_ok());
655 assert!(check_key_permission(0, &sctx, KeyPerm::Update, &key, &None).is_ok());
Chris Wailes3877f292021-07-26 19:24:18 -0700656
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700657 if is_su {
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700658 assert!(check_key_permission(0, &sctx, KeyPerm::Grant, &key, &None).is_ok());
659 assert!(check_key_permission(0, &sctx, KeyPerm::ManageBlob, &key, &None).is_ok());
660 assert!(check_key_permission(0, &sctx, KeyPerm::UseDevId, &key, &None).is_ok());
661 assert!(check_key_permission(0, &sctx, KeyPerm::GenUniqueId, &key, &None).is_ok());
662 assert!(check_key_permission(0, &sctx, KeyPerm::ReqForcedOp, &key, &None).is_ok());
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700663 } else {
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700664 assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::Grant, &key, &None));
665 assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::ReqForcedOp, &key, &None));
666 assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::ManageBlob, &key, &None));
667 assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::UseDevId, &key, &None));
668 assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::GenUniqueId, &key, &None));
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700669 }
670 Ok(())
671 }
672
673 #[test]
674 fn check_key_permission_domain_blob() -> Result<()> {
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700675 let (sctx, namespace, is_su) = check_context()?;
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700676 let key = KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700677 domain: Domain::BLOB,
678 nspace: namespace as i64,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700679 alias: None,
680 blob: None,
681 };
682
683 if is_su {
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700684 check_key_permission(0, &sctx, KeyPerm::Use, &key, &None)
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700685 } else {
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700686 assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::Use, &key, &None));
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700687 Ok(())
688 }
689 }
690
691 #[test]
692 fn check_key_permission_domain_key_id() -> Result<()> {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700693 let key = KeyDescriptor { domain: Domain::KEY_ID, nspace: 0, alias: None, blob: None };
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700694
695 assert_eq!(
696 Some(&KsError::sys()),
697 check_key_permission(
Janis Danisevskis45760022021-01-19 16:34:10 -0800698 0,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700699 &selinux::Context::new("ignored").unwrap(),
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700700 KeyPerm::Use,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700701 &key,
702 &None
703 )
704 .err()
705 .unwrap()
706 .root_cause()
707 .downcast_ref::<KsError>()
708 );
709 Ok(())
710 }
711
712 #[test]
713 fn key_perm_set_all_test() {
714 let v = key_perm_set![
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700715 KeyPerm::ManageBlob,
716 KeyPerm::Delete,
717 KeyPerm::UseDevId,
718 KeyPerm::ReqForcedOp,
719 KeyPerm::GenUniqueId,
720 KeyPerm::Grant,
721 KeyPerm::GetInfo,
722 KeyPerm::Rebind,
723 KeyPerm::Update,
724 KeyPerm::Use // Test if the macro accepts missing comma at the end of the list.
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700725 ];
726 let mut i = v.into_iter();
Janis Danisevskis56af0312021-10-18 16:11:41 -0700727 assert_eq!(i.next().unwrap().name(), "delete");
728 assert_eq!(i.next().unwrap().name(), "gen_unique_id");
729 assert_eq!(i.next().unwrap().name(), "get_info");
730 assert_eq!(i.next().unwrap().name(), "grant");
731 assert_eq!(i.next().unwrap().name(), "manage_blob");
732 assert_eq!(i.next().unwrap().name(), "rebind");
733 assert_eq!(i.next().unwrap().name(), "req_forced_op");
734 assert_eq!(i.next().unwrap().name(), "update");
735 assert_eq!(i.next().unwrap().name(), "use");
736 assert_eq!(i.next().unwrap().name(), "use_dev_id");
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700737 assert_eq!(None, i.next());
738 }
739 #[test]
740 fn key_perm_set_sparse_test() {
741 let v = key_perm_set![
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700742 KeyPerm::ManageBlob,
743 KeyPerm::ReqForcedOp,
744 KeyPerm::GenUniqueId,
745 KeyPerm::Update,
746 KeyPerm::Use, // Test if macro accepts the comma at the end of the list.
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700747 ];
748 let mut i = v.into_iter();
Janis Danisevskis56af0312021-10-18 16:11:41 -0700749 assert_eq!(i.next().unwrap().name(), "gen_unique_id");
750 assert_eq!(i.next().unwrap().name(), "manage_blob");
751 assert_eq!(i.next().unwrap().name(), "req_forced_op");
752 assert_eq!(i.next().unwrap().name(), "update");
753 assert_eq!(i.next().unwrap().name(), "use");
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700754 assert_eq!(None, i.next());
755 }
756 #[test]
757 fn key_perm_set_empty_test() {
758 let v = key_perm_set![];
759 let mut i = v.into_iter();
760 assert_eq!(None, i.next());
761 }
762 #[test]
763 fn key_perm_set_include_subset_test() {
764 let v1 = key_perm_set![
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700765 KeyPerm::ManageBlob,
766 KeyPerm::Delete,
767 KeyPerm::UseDevId,
768 KeyPerm::ReqForcedOp,
769 KeyPerm::GenUniqueId,
770 KeyPerm::Grant,
771 KeyPerm::GetInfo,
772 KeyPerm::Rebind,
773 KeyPerm::Update,
774 KeyPerm::Use,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700775 ];
776 let v2 = key_perm_set![
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700777 KeyPerm::ManageBlob,
778 KeyPerm::Delete,
779 KeyPerm::Rebind,
780 KeyPerm::Update,
781 KeyPerm::Use,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700782 ];
783 assert!(v1.includes(v2));
784 assert!(!v2.includes(v1));
785 }
786 #[test]
787 fn key_perm_set_include_equal_test() {
788 let v1 = key_perm_set![
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700789 KeyPerm::ManageBlob,
790 KeyPerm::Delete,
791 KeyPerm::Rebind,
792 KeyPerm::Update,
793 KeyPerm::Use,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700794 ];
795 let v2 = key_perm_set![
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700796 KeyPerm::ManageBlob,
797 KeyPerm::Delete,
798 KeyPerm::Rebind,
799 KeyPerm::Update,
800 KeyPerm::Use,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700801 ];
802 assert!(v1.includes(v2));
803 assert!(v2.includes(v1));
804 }
805 #[test]
806 fn key_perm_set_include_overlap_test() {
807 let v1 = key_perm_set![
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700808 KeyPerm::ManageBlob,
809 KeyPerm::Delete,
810 KeyPerm::Grant, // only in v1
811 KeyPerm::Rebind,
812 KeyPerm::Update,
813 KeyPerm::Use,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700814 ];
815 let v2 = key_perm_set![
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700816 KeyPerm::ManageBlob,
817 KeyPerm::Delete,
818 KeyPerm::ReqForcedOp, // only in v2
819 KeyPerm::Rebind,
820 KeyPerm::Update,
821 KeyPerm::Use,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700822 ];
823 assert!(!v1.includes(v2));
824 assert!(!v2.includes(v1));
825 }
826 #[test]
827 fn key_perm_set_include_no_overlap_test() {
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700828 let v1 = key_perm_set![KeyPerm::ManageBlob, KeyPerm::Delete, KeyPerm::Grant,];
829 let v2 =
830 key_perm_set![KeyPerm::ReqForcedOp, KeyPerm::Rebind, KeyPerm::Update, KeyPerm::Use,];
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700831 assert!(!v1.includes(v2));
832 assert!(!v2.includes(v1));
833 }
834}