• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // 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 
21 use android_system_keystore2::aidl::android::system::keystore2::{
22     Domain::Domain, KeyDescriptor::KeyDescriptor, KeyPermission::KeyPermission,
23 };
24 
25 use std::cmp::PartialEq;
26 use std::convert::From;
27 use std::ffi::CStr;
28 
29 use crate::error::Error as KsError;
30 use keystore2_selinux as selinux;
31 
32 use anyhow::Context as AnyhowContext;
33 
34 use selinux::Backend;
35 
36 use lazy_static::lazy_static;
37 
38 // Replace getcon with a mock in the test situation
39 #[cfg(not(test))]
40 use selinux::getcon;
41 #[cfg(test)]
42 use tests::test_getcon as getcon;
43 
44 lazy_static! {
45     // Panicking here is allowed because keystore cannot function without this backend
46     // and it would happen early and indicate a gross misconfiguration of the device.
47     static ref KEYSTORE2_KEY_LABEL_BACKEND: selinux::KeystoreKeyBackend =
48             selinux::KeystoreKeyBackend::new().unwrap();
49 }
50 
lookup_keystore2_key_context(namespace: i64) -> anyhow::Result<selinux::Context>51 fn lookup_keystore2_key_context(namespace: i64) -> anyhow::Result<selinux::Context> {
52     KEYSTORE2_KEY_LABEL_BACKEND.lookup(&namespace.to_string())
53 }
54 
55 /// ## Background
56 ///
57 /// AIDL enums are represented as constants of the form:
58 /// ```
59 /// mod EnumName {
60 ///     pub type EnumName = i32;
61 ///     pub const Variant1: EnumName = <value1>;
62 ///     pub const Variant2: EnumName = <value2>;
63 ///     ...
64 /// }
65 ///```
66 /// This macro wraps the enum in a new type, e.g., `MyPerm` and maps each variant to an SELinux
67 /// permission while providing the following interface:
68 ///  * From<EnumName> and Into<EnumName> are implemented. Where the implementation of From maps
69 ///    any variant not specified to the default.
70 ///  * Every variant has a constructor with a name corresponding to its lower case SELinux string
71 ///    representation.
72 ///  * `MyPerm.to_selinux(&self)` returns the SELinux string representation of the
73 ///    represented permission.
74 ///
75 /// ## Special behavior
76 /// If the keyword `use` appears as an selinux name `use_` is used as identifier for the
77 /// constructor function (e.g. `MePerm::use_()`) but the string returned by `to_selinux` will
78 /// still be `"use"`.
79 ///
80 /// ## Example
81 /// ```
82 ///
83 /// implement_permission!(
84 ///     /// MyPerm documentation.
85 ///     #[derive(Clone, Copy, Debug, PartialEq)]
86 ///     MyPerm from EnumName with default (None, none) {}
87 ///         Variant1,    selinux name: variant1;
88 ///         Variant2,    selinux name: variant1;
89 ///     }
90 /// );
91 /// ```
92 macro_rules! implement_permission_aidl {
93     // This rule provides the public interface of the macro. And starts the preprocessing
94     // recursion (see below).
95     ($(#[$m:meta])* $name:ident from $aidl_name:ident with default ($($def:tt)*)
96         { $($element:tt)* })
97     => {
98         implement_permission_aidl!(@replace_use $($m)*, $name, $aidl_name, ($($def)*), [],
99             $($element)*);
100     };
101 
102     // The following three rules recurse through the elements of the form
103     // `<enum variant>, selinux name: <selinux_name>;`
104     // preprocessing the input.
105 
106     // The first rule terminates the recursion and passes the processed arguments to the final
107     // rule that spills out the implementation.
108     (@replace_use $($m:meta)*, $name:ident, $aidl_name:ident, ($($def:tt)*), [$($out:tt)*], ) => {
109         implement_permission_aidl!(@end $($m)*, $name, $aidl_name, ($($def)*) { $($out)* } );
110     };
111 
112     // The second rule is triggered if the selinux name of an element is literally `use`.
113     // It produces the tuple `<enum variant>, use_, use;`
114     // and appends it to the out list.
115     (@replace_use $($m:meta)*, $name:ident, $aidl_name:ident, ($($def:tt)*), [$($out:tt)*],
116         $e_name:ident, selinux name: use; $($element:tt)*)
117     => {
118         implement_permission_aidl!(@replace_use $($m)*, $name, $aidl_name, ($($def)*),
119                               [$($out)* $e_name, use_, use;], $($element)*);
120     };
121 
122     // The third rule is the default rule which replaces every input tuple with
123     // `<enum variant>, <selinux_name>, <selinux_name>;`
124     // and appends the result to the out list.
125     (@replace_use $($m:meta)*, $name:ident, $aidl_name:ident, ($($def:tt)*), [$($out:tt)*],
126         $e_name:ident, selinux name: $e_str:ident; $($element:tt)*)
127     => {
128         implement_permission_aidl!(@replace_use $($m)*, $name, $aidl_name, ($($def)*),
129                               [$($out)* $e_name, $e_str, $e_str;], $($element)*);
130     };
131 
132     (@end $($m:meta)*, $name:ident, $aidl_name:ident,
133         ($def_name:ident, $def_selinux_name:ident) {
134             $($element_name:ident, $element_identifier:ident,
135                 $selinux_name:ident;)*
136         })
137     =>
138     {
139         $(#[$m])*
140         pub struct $name(pub $aidl_name);
141 
142         impl From<$aidl_name> for $name {
143             fn from (p: $aidl_name) -> Self {
144                 match p {
145                     $aidl_name::$def_name => Self($aidl_name::$def_name),
146                     $($aidl_name::$element_name => Self($aidl_name::$element_name),)*
147                     _ => Self($aidl_name::$def_name),
148                 }
149             }
150         }
151 
152         impl From<$name> for $aidl_name {
153             fn from(p: $name) -> $aidl_name {
154                 p.0
155             }
156         }
157 
158         impl $name {
159             /// Returns a string representation of the permission as required by
160             /// `selinux::check_access`.
161             pub fn to_selinux(&self) -> &'static str {
162                 match self {
163                     Self($aidl_name::$def_name) => stringify!($def_selinux_name),
164                     $(Self($aidl_name::$element_name) => stringify!($selinux_name),)*
165                     _ => stringify!($def_selinux_name),
166                 }
167             }
168 
169             /// Creates an instance representing a permission with the same name.
170             pub const fn $def_selinux_name() -> Self { Self($aidl_name::$def_name) }
171             $(
172                 /// Creates an instance representing a permission with the same name.
173                 pub const fn $element_identifier() -> Self { Self($aidl_name::$element_name) }
174             )*
175         }
176     };
177 }
178 
179 implement_permission_aidl!(
180     /// KeyPerm provides a convenient abstraction from the SELinux class `keystore2_key`.
181     /// At the same time it maps `KeyPermissions` from the Keystore 2.0 AIDL Grant interface to
182     /// the SELinux permissions. With the implement_permission macro, we conveniently
183     /// provide mappings between the wire type bit field values, the rust enum and the SELinux
184     /// string representation.
185     ///
186     /// ## Example
187     ///
188     /// In this access check `KeyPerm::get_info().to_selinux()` would return the SELinux representation
189     /// "info".
190     /// ```
191     /// selinux::check_access(source_context, target_context, "keystore2_key",
192     ///                       KeyPerm::get_info().to_selinux());
193     /// ```
194     #[derive(Clone, Copy, Debug, Eq, PartialEq)]
195     KeyPerm from KeyPermission with default (NONE, none) {
196         CONVERT_STORAGE_KEY_TO_EPHEMERAL,   selinux name: convert_storage_key_to_ephemeral;
197         DELETE,         selinux name: delete;
198         GEN_UNIQUE_ID,  selinux name: gen_unique_id;
199         GET_INFO,       selinux name: get_info;
200         GRANT,          selinux name: grant;
201         MANAGE_BLOB,    selinux name: manage_blob;
202         REBIND,         selinux name: rebind;
203         REQ_FORCED_OP,  selinux name: req_forced_op;
204         UPDATE,         selinux name: update;
205         USE,            selinux name: use;
206         USE_DEV_ID,     selinux name: use_dev_id;
207     }
208 );
209 
210 /// This macro implements an enum with values mapped to SELinux permission names.
211 /// The below example wraps the enum MyPermission in the tuple struct `MyPerm` and implements
212 ///  * From<i32> and Into<i32> are implemented. Where the implementation of From maps
213 ///    any variant not specified to the default.
214 ///  * Every variant has a constructor with a name corresponding to its lower case SELinux string
215 ///    representation.
216 ///  * `MyPerm.to_selinux(&self)` returns the SELinux string representation of the
217 ///    represented permission.
218 ///
219 /// ## Example
220 /// ```
221 /// implement_permission!(
222 ///     /// MyPerm documentation.
223 ///     #[derive(Clone, Copy, Debug, Eq, PartialEq)]
224 ///     MyPerm with default (None = 0, none) {
225 ///         Foo = 1,           selinux name: foo;
226 ///         Bar = 2,           selinux name: bar;
227 ///     }
228 /// );
229 /// ```
230 macro_rules! implement_permission {
231     // This rule provides the public interface of the macro. And starts the preprocessing
232     // recursion (see below).
233     ($(#[$m:meta])* $name:ident with default
234         ($def_name:ident = $def_val:expr, $def_selinux_name:ident)
235         {
236             $($(#[$element_meta:meta])*
237             $element_name:ident = $element_val:expr, selinux name: $selinux_name:ident;)*
238         })
239     => {
240         $(#[$m])*
241         pub enum $name {
242             /// The default variant of an enum.
243             $def_name = $def_val,
244             $(
245                 $(#[$element_meta])*
246                 $element_name = $element_val,
247             )*
248         }
249 
250         impl From<i32> for $name {
251             fn from (p: i32) -> Self {
252                 match p {
253                     $def_val => Self::$def_name,
254                     $($element_val => Self::$element_name,)*
255                     _ => Self::$def_name,
256                 }
257             }
258         }
259 
260         impl From<$name> for i32 {
261             fn from(p: $name) -> i32 {
262                 p as i32
263             }
264         }
265 
266         impl $name {
267             /// Returns a string representation of the permission as required by
268             /// `selinux::check_access`.
269             pub fn to_selinux(&self) -> &'static str {
270                 match self {
271                     Self::$def_name => stringify!($def_selinux_name),
272                     $(Self::$element_name => stringify!($selinux_name),)*
273                 }
274             }
275 
276             /// Creates an instance representing a permission with the same name.
277             pub const fn $def_selinux_name() -> Self { Self::$def_name }
278             $(
279                 /// Creates an instance representing a permission with the same name.
280                 pub const fn $selinux_name() -> Self { Self::$element_name }
281             )*
282         }
283     };
284 }
285 
286 implement_permission!(
287     /// KeystorePerm provides a convenient abstraction from the SELinux class `keystore2`.
288     /// Using the implement_permission macro we get the same features as `KeyPerm`.
289     #[derive(Clone, Copy, Debug, PartialEq)]
290     KeystorePerm with default (None = 0, none) {
291         /// Checked when a new auth token is installed.
292         AddAuth = 1,    selinux name: add_auth;
293         /// Checked when an app is uninstalled or wiped.
294         ClearNs = 2,    selinux name: clear_ns;
295         /// Checked when the user state is queried from Keystore 2.0.
296         GetState = 4,   selinux name: get_state;
297         /// Checked when Keystore 2.0 is asked to list a namespace that the caller
298         /// does not have the get_info permission for.
299         List = 8,       selinux name: list;
300         /// Checked when Keystore 2.0 gets locked.
301         Lock = 0x10,       selinux name: lock;
302         /// Checked when Keystore 2.0 shall be reset.
303         Reset = 0x20,    selinux name: reset;
304         /// Checked when Keystore 2.0 shall be unlocked.
305         Unlock = 0x40,    selinux name: unlock;
306         /// Checked when user is added or removed.
307         ChangeUser = 0x80,    selinux name: change_user;
308         /// Checked when password of the user is changed.
309         ChangePassword = 0x100,    selinux name: change_password;
310         /// Checked when a UID is cleared.
311         ClearUID = 0x200,    selinux name: clear_uid;
312         /// Checked when Credstore calls IKeystoreAuthorization to obtain auth tokens.
313         GetAuthToken = 0x400,  selinux name: get_auth_token;
314         /// Checked when earlyBootEnded() is called.
315         EarlyBootEnded = 0x800,   selinux name: early_boot_ended;
316         /// Checked when IKeystoreMaintenance::onDeviceOffBody is called.
317         ReportOffBody = 0x1000, selinux name: report_off_body;
318         /// Checked when IkeystoreMetrics::pullMetris is called.
319         PullMetrics = 0x2000, selinux name: pull_metrics;
320         /// Checked when IKeystoreMaintenance::deleteAllKeys is called.
321         DeleteAllKeys = 0x4000, selinux name: delete_all_keys;
322     }
323 );
324 
325 /// Represents a set of `KeyPerm` permissions.
326 /// `IntoIterator` is implemented for this struct allowing the iteration through all the
327 /// permissions in the set.
328 /// It also implements a function `includes(self, other)` that checks if the permissions
329 /// in `other` are included in `self`.
330 ///
331 /// KeyPermSet can be created with the macro `key_perm_set![]`.
332 ///
333 /// ## Example
334 /// ```
335 /// let perms1 = key_perm_set![KeyPerm::use_(), KeyPerm::manage_blob(), KeyPerm::grant()];
336 /// let perms2 = key_perm_set![KeyPerm::use_(), KeyPerm::manage_blob()];
337 ///
338 /// assert!(perms1.includes(perms2))
339 /// assert!(!perms2.includes(perms1))
340 ///
341 /// let i = perms1.into_iter();
342 /// // iteration in ascending order of the permission's numeric representation.
343 /// assert_eq(Some(KeyPerm::manage_blob()), i.next());
344 /// assert_eq(Some(KeyPerm::grant()), i.next());
345 /// assert_eq(Some(KeyPerm::use_()), i.next());
346 /// assert_eq(None, i.next());
347 /// ```
348 #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
349 pub struct KeyPermSet(pub i32);
350 
351 mod perm {
352     use super::*;
353 
354     pub struct IntoIter {
355         vec: KeyPermSet,
356         pos: u8,
357     }
358 
359     impl IntoIter {
new(v: KeyPermSet) -> Self360         pub fn new(v: KeyPermSet) -> Self {
361             Self { vec: v, pos: 0 }
362         }
363     }
364 
365     impl std::iter::Iterator for IntoIter {
366         type Item = KeyPerm;
367 
next(&mut self) -> Option<Self::Item>368         fn next(&mut self) -> Option<Self::Item> {
369             loop {
370                 if self.pos == 32 {
371                     return None;
372                 }
373                 let p = self.vec.0 & (1 << self.pos);
374                 self.pos += 1;
375                 if p != 0 {
376                     return Some(KeyPerm::from(KeyPermission(p)));
377                 }
378             }
379         }
380     }
381 }
382 
383 impl From<KeyPerm> for KeyPermSet {
from(p: KeyPerm) -> Self384     fn from(p: KeyPerm) -> Self {
385         Self((p.0).0 as i32)
386     }
387 }
388 
389 /// allow conversion from the AIDL wire type i32 to a permission set.
390 impl From<i32> for KeyPermSet {
from(p: i32) -> Self391     fn from(p: i32) -> Self {
392         Self(p)
393     }
394 }
395 
396 impl From<KeyPermSet> for i32 {
from(p: KeyPermSet) -> i32397     fn from(p: KeyPermSet) -> i32 {
398         p.0
399     }
400 }
401 
402 impl KeyPermSet {
403     /// Returns true iff this permission set has all of the permissions that are in `other`.
includes<T: Into<KeyPermSet>>(&self, other: T) -> bool404     pub fn includes<T: Into<KeyPermSet>>(&self, other: T) -> bool {
405         let o: KeyPermSet = other.into();
406         (self.0 & o.0) == o.0
407     }
408 }
409 
410 /// This macro can be used to create a `KeyPermSet` from a list of `KeyPerm` values.
411 ///
412 /// ## Example
413 /// ```
414 /// let v = key_perm_set![Perm::delete(), Perm::manage_blob()];
415 /// ```
416 #[macro_export]
417 macro_rules! key_perm_set {
418     () => { KeyPermSet(0) };
419     ($head:expr $(, $tail:expr)* $(,)?) => {
420         KeyPermSet(($head.0).0 $(| ($tail.0).0)*)
421     };
422 }
423 
424 impl IntoIterator for KeyPermSet {
425     type Item = KeyPerm;
426     type IntoIter = perm::IntoIter;
427 
into_iter(self) -> Self::IntoIter428     fn into_iter(self) -> Self::IntoIter {
429         Self::IntoIter::new(self)
430     }
431 }
432 
433 /// Uses `selinux::check_access` to check if the given caller context `caller_cxt` may access
434 /// the given permision `perm` of the `keystore2` security class.
check_keystore_permission(caller_ctx: &CStr, perm: KeystorePerm) -> anyhow::Result<()>435 pub fn check_keystore_permission(caller_ctx: &CStr, perm: KeystorePerm) -> anyhow::Result<()> {
436     let target_context = getcon().context("check_keystore_permission: getcon failed.")?;
437     selinux::check_access(caller_ctx, &target_context, "keystore2", perm.to_selinux())
438 }
439 
440 /// Uses `selinux::check_access` to check if the given caller context `caller_cxt` has
441 /// all the permissions indicated in `access_vec` for the target domain indicated by the key
442 /// descriptor `key` in the security class `keystore2_key`.
443 ///
444 /// Also checks if the caller has the grant permission for the given target domain.
445 ///
446 /// Attempts to grant the grant permission are always denied.
447 ///
448 /// The only viable target domains are
449 ///  * `Domain::APP` in which case u:r:keystore:s0 is used as target context and
450 ///  * `Domain::SELINUX` in which case the `key.nspace` parameter is looked up in
451 ///                      SELinux keystore key backend, and the result is used
452 ///                      as target context.
check_grant_permission( caller_ctx: &CStr, access_vec: KeyPermSet, key: &KeyDescriptor, ) -> anyhow::Result<()>453 pub fn check_grant_permission(
454     caller_ctx: &CStr,
455     access_vec: KeyPermSet,
456     key: &KeyDescriptor,
457 ) -> anyhow::Result<()> {
458     let target_context = match key.domain {
459         Domain::APP => getcon().context("check_grant_permission: getcon failed.")?,
460         Domain::SELINUX => lookup_keystore2_key_context(key.nspace)
461             .context("check_grant_permission: Domain::SELINUX: Failed to lookup namespace.")?,
462         _ => return Err(KsError::sys()).context(format!("Cannot grant {:?}.", key.domain)),
463     };
464 
465     selinux::check_access(caller_ctx, &target_context, "keystore2_key", "grant")
466         .context("Grant permission is required when granting.")?;
467 
468     if access_vec.includes(KeyPerm::grant()) {
469         return Err(selinux::Error::perm()).context("Grant permission cannot be granted.");
470     }
471 
472     for p in access_vec.into_iter() {
473         selinux::check_access(caller_ctx, &target_context, "keystore2_key", p.to_selinux())
474             .context(format!(
475                 concat!(
476                     "check_grant_permission: check_access failed. ",
477                     "The caller may have tried to grant a permission that they don't possess. {:?}"
478                 ),
479                 p
480             ))?
481     }
482     Ok(())
483 }
484 
485 /// Uses `selinux::check_access` to check if the given caller context `caller_cxt`
486 /// has the permissions indicated by `perm` for the target domain indicated by the key
487 /// descriptor `key` in the security class `keystore2_key`.
488 ///
489 /// The behavior differs slightly depending on the selected target domain:
490 ///  * `Domain::APP` u:r:keystore:s0 is used as target context.
491 ///  * `Domain::SELINUX` `key.nspace` parameter is looked up in the SELinux keystore key
492 ///                      backend, and the result is used as target context.
493 ///  * `Domain::BLOB` Same as SELinux but the "manage_blob" permission is always checked additionally
494 ///                   to the one supplied in `perm`.
495 ///  * `Domain::GRANT` Does not use selinux::check_access. Instead the `access_vector`
496 ///                    parameter is queried for permission, which must be supplied in this case.
497 ///
498 /// ## Return values.
499 ///  * Ok(()) If the requested permissions were granted.
500 ///  * Err(selinux::Error::perm()) If the requested permissions were denied.
501 ///  * Err(KsError::sys()) This error is produced if `Domain::GRANT` is selected but no `access_vec`
502 ///                      was supplied. It is also produced if `Domain::KEY_ID` was selected, and
503 ///                      on various unexpected backend failures.
check_key_permission( caller_uid: u32, caller_ctx: &CStr, perm: KeyPerm, key: &KeyDescriptor, access_vector: &Option<KeyPermSet>, ) -> anyhow::Result<()>504 pub fn check_key_permission(
505     caller_uid: u32,
506     caller_ctx: &CStr,
507     perm: KeyPerm,
508     key: &KeyDescriptor,
509     access_vector: &Option<KeyPermSet>,
510 ) -> anyhow::Result<()> {
511     // If an access vector was supplied, the key is either accessed by GRANT or by KEY_ID.
512     // In the former case, key.domain was set to GRANT and we check the failure cases
513     // further below. If the access is requested by KEY_ID, key.domain would have been
514     // resolved to APP or SELINUX depending on where the key actually resides.
515     // Either way we can return here immediately if the access vector covers the requested
516     // permission. If it does not, we can still check if the caller has access by means of
517     // ownership.
518     if let Some(access_vector) = access_vector {
519         if access_vector.includes(perm) {
520             return Ok(());
521         }
522     }
523 
524     let target_context = match key.domain {
525         // apps get the default keystore context
526         Domain::APP => {
527             if caller_uid as i64 != key.nspace {
528                 return Err(selinux::Error::perm())
529                     .context("Trying to access key without ownership.");
530             }
531             getcon().context("check_key_permission: getcon failed.")?
532         }
533         Domain::SELINUX => lookup_keystore2_key_context(key.nspace)
534             .context("check_key_permission: Domain::SELINUX: Failed to lookup namespace.")?,
535         Domain::GRANT => {
536             match access_vector {
537                 Some(_) => {
538                     return Err(selinux::Error::perm())
539                         .context(format!("\"{}\" not granted", perm.to_selinux()));
540                 }
541                 None => {
542                     // If DOMAIN_GRANT was selected an access vector must be supplied.
543                     return Err(KsError::sys()).context(
544                         "Cannot check permission for Domain::GRANT without access vector.",
545                     );
546                 }
547             }
548         }
549         Domain::KEY_ID => {
550             // We should never be called with `Domain::KEY_ID. The database
551             // lookup should have converted this into one of `Domain::APP`
552             // or `Domain::SELINUX`.
553             return Err(KsError::sys()).context("Cannot check permission for Domain::KEY_ID.");
554         }
555         Domain::BLOB => {
556             let tctx = lookup_keystore2_key_context(key.nspace)
557                 .context("Domain::BLOB: Failed to lookup namespace.")?;
558             // If DOMAIN_KEY_BLOB was specified, we check for the "manage_blob"
559             // permission in addition to the requested permission.
560             selinux::check_access(
561                 caller_ctx,
562                 &tctx,
563                 "keystore2_key",
564                 KeyPerm::manage_blob().to_selinux(),
565             )?;
566 
567             tctx
568         }
569         _ => {
570             return Err(KsError::sys())
571                 .context(format!("Unknown domain value: \"{:?}\".", key.domain))
572         }
573     };
574 
575     selinux::check_access(caller_ctx, &target_context, "keystore2_key", perm.to_selinux())
576 }
577 
578 #[cfg(test)]
579 mod tests {
580     use super::*;
581     use anyhow::anyhow;
582     use anyhow::Result;
583     use keystore2_selinux::*;
584 
585     const ALL_PERMS: KeyPermSet = key_perm_set![
586         KeyPerm::manage_blob(),
587         KeyPerm::delete(),
588         KeyPerm::use_dev_id(),
589         KeyPerm::req_forced_op(),
590         KeyPerm::gen_unique_id(),
591         KeyPerm::grant(),
592         KeyPerm::get_info(),
593         KeyPerm::rebind(),
594         KeyPerm::update(),
595         KeyPerm::use_(),
596         KeyPerm::convert_storage_key_to_ephemeral(),
597     ];
598 
599     const SYSTEM_SERVER_PERMISSIONS_NO_GRANT: KeyPermSet = key_perm_set![
600         KeyPerm::delete(),
601         KeyPerm::use_dev_id(),
602         // No KeyPerm::grant()
603         KeyPerm::get_info(),
604         KeyPerm::rebind(),
605         KeyPerm::update(),
606         KeyPerm::use_(),
607     ];
608 
609     const NOT_GRANT_PERMS: KeyPermSet = key_perm_set![
610         KeyPerm::manage_blob(),
611         KeyPerm::delete(),
612         KeyPerm::use_dev_id(),
613         KeyPerm::req_forced_op(),
614         KeyPerm::gen_unique_id(),
615         // No KeyPerm::grant()
616         KeyPerm::get_info(),
617         KeyPerm::rebind(),
618         KeyPerm::update(),
619         KeyPerm::use_(),
620         KeyPerm::convert_storage_key_to_ephemeral(),
621     ];
622 
623     const UNPRIV_PERMS: KeyPermSet = key_perm_set![
624         KeyPerm::delete(),
625         KeyPerm::get_info(),
626         KeyPerm::rebind(),
627         KeyPerm::update(),
628         KeyPerm::use_(),
629     ];
630 
631     /// The su_key namespace as defined in su.te and keystore_key_contexts of the
632     /// SePolicy (system/sepolicy).
633     const SU_KEY_NAMESPACE: i32 = 0;
634     /// The shell_key namespace as defined in shell.te and keystore_key_contexts of the
635     /// SePolicy (system/sepolicy).
636     const SHELL_KEY_NAMESPACE: i32 = 1;
637 
test_getcon() -> Result<Context>638     pub fn test_getcon() -> Result<Context> {
639         Context::new("u:object_r:keystore:s0")
640     }
641 
642     // This macro evaluates the given expression and checks that
643     // a) evaluated to Result::Err() and that
644     // b) the wrapped error is selinux::Error::perm() (permission denied).
645     // We use a macro here because a function would mask which invocation caused the failure.
646     //
647     // TODO b/164121720 Replace this macro with a function when `track_caller` is available.
648     macro_rules! assert_perm_failed {
649         ($test_function:expr) => {
650             let result = $test_function;
651             assert!(result.is_err(), "Permission check should have failed.");
652             assert_eq!(
653                 Some(&selinux::Error::perm()),
654                 result.err().unwrap().root_cause().downcast_ref::<selinux::Error>()
655             );
656         };
657     }
658 
check_context() -> Result<(selinux::Context, i32, bool)>659     fn check_context() -> Result<(selinux::Context, i32, bool)> {
660         // Calling the non mocked selinux::getcon here intended.
661         let context = selinux::getcon()?;
662         match context.to_str().unwrap() {
663             "u:r:su:s0" => Ok((context, SU_KEY_NAMESPACE, true)),
664             "u:r:shell:s0" => Ok((context, SHELL_KEY_NAMESPACE, false)),
665             c => Err(anyhow!(format!(
666                 "This test must be run as \"su\" or \"shell\". Current context: \"{}\"",
667                 c
668             ))),
669         }
670     }
671 
672     #[test]
check_keystore_permission_test() -> Result<()>673     fn check_keystore_permission_test() -> Result<()> {
674         let system_server_ctx = Context::new("u:r:system_server:s0")?;
675         assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::add_auth()).is_ok());
676         assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::clear_ns()).is_ok());
677         assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::get_state()).is_ok());
678         assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::lock()).is_ok());
679         assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::reset()).is_ok());
680         assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::unlock()).is_ok());
681         assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::change_user()).is_ok());
682         assert!(
683             check_keystore_permission(&system_server_ctx, KeystorePerm::change_password()).is_ok()
684         );
685         assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::clear_uid()).is_ok());
686         let shell_ctx = Context::new("u:r:shell:s0")?;
687         assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::add_auth()));
688         assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::clear_ns()));
689         assert!(check_keystore_permission(&shell_ctx, KeystorePerm::get_state()).is_ok());
690         assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::list()));
691         assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::lock()));
692         assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::reset()));
693         assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::unlock()));
694         assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::change_user()));
695         assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::change_password()));
696         assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::clear_uid()));
697         Ok(())
698     }
699 
700     #[test]
check_grant_permission_app() -> Result<()>701     fn check_grant_permission_app() -> Result<()> {
702         let system_server_ctx = Context::new("u:r:system_server:s0")?;
703         let shell_ctx = Context::new("u:r:shell:s0")?;
704         let key = KeyDescriptor { domain: Domain::APP, nspace: 0, alias: None, blob: None };
705         check_grant_permission(&system_server_ctx, SYSTEM_SERVER_PERMISSIONS_NO_GRANT, &key)
706             .expect("Grant permission check failed.");
707 
708         // attempts to grant the grant permission must always fail even when privileged.
709         assert_perm_failed!(check_grant_permission(
710             &system_server_ctx,
711             KeyPerm::grant().into(),
712             &key
713         ));
714         // unprivileged grant attempts always fail. shell does not have the grant permission.
715         assert_perm_failed!(check_grant_permission(&shell_ctx, UNPRIV_PERMS, &key));
716         Ok(())
717     }
718 
719     #[test]
check_grant_permission_selinux() -> Result<()>720     fn check_grant_permission_selinux() -> Result<()> {
721         let (sctx, namespace, is_su) = check_context()?;
722         let key = KeyDescriptor {
723             domain: Domain::SELINUX,
724             nspace: namespace as i64,
725             alias: None,
726             blob: None,
727         };
728         if is_su {
729             assert!(check_grant_permission(&sctx, NOT_GRANT_PERMS, &key).is_ok());
730             // attempts to grant the grant permission must always fail even when privileged.
731             assert_perm_failed!(check_grant_permission(&sctx, KeyPerm::grant().into(), &key));
732         } else {
733             // unprivileged grant attempts always fail. shell does not have the grant permission.
734             assert_perm_failed!(check_grant_permission(&sctx, UNPRIV_PERMS, &key));
735         }
736         Ok(())
737     }
738 
739     #[test]
check_key_permission_domain_grant() -> Result<()>740     fn check_key_permission_domain_grant() -> Result<()> {
741         let key = KeyDescriptor { domain: Domain::GRANT, nspace: 0, alias: None, blob: None };
742 
743         assert_perm_failed!(check_key_permission(
744             0,
745             &selinux::Context::new("ignored").unwrap(),
746             KeyPerm::grant(),
747             &key,
748             &Some(UNPRIV_PERMS)
749         ));
750 
751         check_key_permission(
752             0,
753             &selinux::Context::new("ignored").unwrap(),
754             KeyPerm::use_(),
755             &key,
756             &Some(ALL_PERMS),
757         )
758     }
759 
760     #[test]
check_key_permission_domain_app() -> Result<()>761     fn check_key_permission_domain_app() -> Result<()> {
762         let system_server_ctx = Context::new("u:r:system_server:s0")?;
763         let shell_ctx = Context::new("u:r:shell:s0")?;
764         let gmscore_app = Context::new("u:r:gmscore_app:s0")?;
765 
766         let key = KeyDescriptor { domain: Domain::APP, nspace: 0, alias: None, blob: None };
767 
768         assert!(check_key_permission(0, &system_server_ctx, KeyPerm::use_(), &key, &None).is_ok());
769         assert!(check_key_permission(0, &system_server_ctx, KeyPerm::delete(), &key, &None).is_ok());
770         assert!(
771             check_key_permission(0, &system_server_ctx, KeyPerm::get_info(), &key, &None).is_ok()
772         );
773         assert!(check_key_permission(0, &system_server_ctx, KeyPerm::rebind(), &key, &None).is_ok());
774         assert!(check_key_permission(0, &system_server_ctx, KeyPerm::update(), &key, &None).is_ok());
775         assert!(check_key_permission(0, &system_server_ctx, KeyPerm::grant(), &key, &None).is_ok());
776         assert!(
777             check_key_permission(0, &system_server_ctx, KeyPerm::use_dev_id(), &key, &None).is_ok()
778         );
779         assert!(
780             check_key_permission(0, &gmscore_app, KeyPerm::gen_unique_id(), &key, &None).is_ok()
781         );
782 
783         assert!(check_key_permission(0, &shell_ctx, KeyPerm::use_(), &key, &None).is_ok());
784         assert!(check_key_permission(0, &shell_ctx, KeyPerm::delete(), &key, &None).is_ok());
785         assert!(check_key_permission(0, &shell_ctx, KeyPerm::get_info(), &key, &None).is_ok());
786         assert!(check_key_permission(0, &shell_ctx, KeyPerm::rebind(), &key, &None).is_ok());
787         assert!(check_key_permission(0, &shell_ctx, KeyPerm::update(), &key, &None).is_ok());
788         assert_perm_failed!(check_key_permission(0, &shell_ctx, KeyPerm::grant(), &key, &None));
789         assert_perm_failed!(check_key_permission(
790             0,
791             &shell_ctx,
792             KeyPerm::req_forced_op(),
793             &key,
794             &None
795         ));
796         assert_perm_failed!(check_key_permission(
797             0,
798             &shell_ctx,
799             KeyPerm::manage_blob(),
800             &key,
801             &None
802         ));
803         assert_perm_failed!(check_key_permission(
804             0,
805             &shell_ctx,
806             KeyPerm::use_dev_id(),
807             &key,
808             &None
809         ));
810         assert_perm_failed!(check_key_permission(
811             0,
812             &shell_ctx,
813             KeyPerm::gen_unique_id(),
814             &key,
815             &None
816         ));
817 
818         // Also make sure that the permission fails if the caller is not the owner.
819         assert_perm_failed!(check_key_permission(
820             1, // the owner is 0
821             &system_server_ctx,
822             KeyPerm::use_(),
823             &key,
824             &None
825         ));
826         // Unless there was a grant.
827         assert!(check_key_permission(
828             1,
829             &system_server_ctx,
830             KeyPerm::use_(),
831             &key,
832             &Some(key_perm_set![KeyPerm::use_()])
833         )
834         .is_ok());
835         // But fail if the grant did not cover the requested permission.
836         assert_perm_failed!(check_key_permission(
837             1,
838             &system_server_ctx,
839             KeyPerm::use_(),
840             &key,
841             &Some(key_perm_set![KeyPerm::get_info()])
842         ));
843 
844         Ok(())
845     }
846 
847     #[test]
check_key_permission_domain_selinux() -> Result<()>848     fn check_key_permission_domain_selinux() -> Result<()> {
849         let (sctx, namespace, is_su) = check_context()?;
850         let key = KeyDescriptor {
851             domain: Domain::SELINUX,
852             nspace: namespace as i64,
853             alias: None,
854             blob: None,
855         };
856 
857         if is_su {
858             assert!(check_key_permission(0, &sctx, KeyPerm::use_(), &key, &None).is_ok());
859             assert!(check_key_permission(0, &sctx, KeyPerm::delete(), &key, &None).is_ok());
860             assert!(check_key_permission(0, &sctx, KeyPerm::get_info(), &key, &None).is_ok());
861             assert!(check_key_permission(0, &sctx, KeyPerm::rebind(), &key, &None).is_ok());
862             assert!(check_key_permission(0, &sctx, KeyPerm::update(), &key, &None).is_ok());
863             assert!(check_key_permission(0, &sctx, KeyPerm::grant(), &key, &None).is_ok());
864             assert!(check_key_permission(0, &sctx, KeyPerm::manage_blob(), &key, &None).is_ok());
865             assert!(check_key_permission(0, &sctx, KeyPerm::use_dev_id(), &key, &None).is_ok());
866             assert!(check_key_permission(0, &sctx, KeyPerm::gen_unique_id(), &key, &None).is_ok());
867             assert!(check_key_permission(0, &sctx, KeyPerm::req_forced_op(), &key, &None).is_ok());
868         } else {
869             assert!(check_key_permission(0, &sctx, KeyPerm::use_(), &key, &None).is_ok());
870             assert!(check_key_permission(0, &sctx, KeyPerm::delete(), &key, &None).is_ok());
871             assert!(check_key_permission(0, &sctx, KeyPerm::get_info(), &key, &None).is_ok());
872             assert!(check_key_permission(0, &sctx, KeyPerm::rebind(), &key, &None).is_ok());
873             assert!(check_key_permission(0, &sctx, KeyPerm::update(), &key, &None).is_ok());
874             assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::grant(), &key, &None));
875             assert_perm_failed!(check_key_permission(
876                 0,
877                 &sctx,
878                 KeyPerm::req_forced_op(),
879                 &key,
880                 &None
881             ));
882             assert_perm_failed!(check_key_permission(
883                 0,
884                 &sctx,
885                 KeyPerm::manage_blob(),
886                 &key,
887                 &None
888             ));
889             assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::use_dev_id(), &key, &None));
890             assert_perm_failed!(check_key_permission(
891                 0,
892                 &sctx,
893                 KeyPerm::gen_unique_id(),
894                 &key,
895                 &None
896             ));
897         }
898         Ok(())
899     }
900 
901     #[test]
check_key_permission_domain_blob() -> Result<()>902     fn check_key_permission_domain_blob() -> Result<()> {
903         let (sctx, namespace, is_su) = check_context()?;
904         let key = KeyDescriptor {
905             domain: Domain::BLOB,
906             nspace: namespace as i64,
907             alias: None,
908             blob: None,
909         };
910 
911         if is_su {
912             check_key_permission(0, &sctx, KeyPerm::use_(), &key, &None)
913         } else {
914             assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::use_(), &key, &None));
915             Ok(())
916         }
917     }
918 
919     #[test]
check_key_permission_domain_key_id() -> Result<()>920     fn check_key_permission_domain_key_id() -> Result<()> {
921         let key = KeyDescriptor { domain: Domain::KEY_ID, nspace: 0, alias: None, blob: None };
922 
923         assert_eq!(
924             Some(&KsError::sys()),
925             check_key_permission(
926                 0,
927                 &selinux::Context::new("ignored").unwrap(),
928                 KeyPerm::use_(),
929                 &key,
930                 &None
931             )
932             .err()
933             .unwrap()
934             .root_cause()
935             .downcast_ref::<KsError>()
936         );
937         Ok(())
938     }
939 
940     #[test]
key_perm_set_all_test()941     fn key_perm_set_all_test() {
942         let v = key_perm_set![
943             KeyPerm::manage_blob(),
944             KeyPerm::delete(),
945             KeyPerm::use_dev_id(),
946             KeyPerm::req_forced_op(),
947             KeyPerm::gen_unique_id(),
948             KeyPerm::grant(),
949             KeyPerm::get_info(),
950             KeyPerm::rebind(),
951             KeyPerm::update(),
952             KeyPerm::use_() // Test if the macro accepts missing comma at the end of the list.
953         ];
954         let mut i = v.into_iter();
955         assert_eq!(i.next().unwrap().to_selinux(), "delete");
956         assert_eq!(i.next().unwrap().to_selinux(), "gen_unique_id");
957         assert_eq!(i.next().unwrap().to_selinux(), "get_info");
958         assert_eq!(i.next().unwrap().to_selinux(), "grant");
959         assert_eq!(i.next().unwrap().to_selinux(), "manage_blob");
960         assert_eq!(i.next().unwrap().to_selinux(), "rebind");
961         assert_eq!(i.next().unwrap().to_selinux(), "req_forced_op");
962         assert_eq!(i.next().unwrap().to_selinux(), "update");
963         assert_eq!(i.next().unwrap().to_selinux(), "use");
964         assert_eq!(i.next().unwrap().to_selinux(), "use_dev_id");
965         assert_eq!(None, i.next());
966     }
967     #[test]
key_perm_set_sparse_test()968     fn key_perm_set_sparse_test() {
969         let v = key_perm_set![
970             KeyPerm::manage_blob(),
971             KeyPerm::req_forced_op(),
972             KeyPerm::gen_unique_id(),
973             KeyPerm::update(),
974             KeyPerm::use_(), // Test if macro accepts the comma at the end of the list.
975         ];
976         let mut i = v.into_iter();
977         assert_eq!(i.next().unwrap().to_selinux(), "gen_unique_id");
978         assert_eq!(i.next().unwrap().to_selinux(), "manage_blob");
979         assert_eq!(i.next().unwrap().to_selinux(), "req_forced_op");
980         assert_eq!(i.next().unwrap().to_selinux(), "update");
981         assert_eq!(i.next().unwrap().to_selinux(), "use");
982         assert_eq!(None, i.next());
983     }
984     #[test]
key_perm_set_empty_test()985     fn key_perm_set_empty_test() {
986         let v = key_perm_set![];
987         let mut i = v.into_iter();
988         assert_eq!(None, i.next());
989     }
990     #[test]
key_perm_set_include_subset_test()991     fn key_perm_set_include_subset_test() {
992         let v1 = key_perm_set![
993             KeyPerm::manage_blob(),
994             KeyPerm::delete(),
995             KeyPerm::use_dev_id(),
996             KeyPerm::req_forced_op(),
997             KeyPerm::gen_unique_id(),
998             KeyPerm::grant(),
999             KeyPerm::get_info(),
1000             KeyPerm::rebind(),
1001             KeyPerm::update(),
1002             KeyPerm::use_(),
1003         ];
1004         let v2 = key_perm_set![
1005             KeyPerm::manage_blob(),
1006             KeyPerm::delete(),
1007             KeyPerm::rebind(),
1008             KeyPerm::update(),
1009             KeyPerm::use_(),
1010         ];
1011         assert!(v1.includes(v2));
1012         assert!(!v2.includes(v1));
1013     }
1014     #[test]
key_perm_set_include_equal_test()1015     fn key_perm_set_include_equal_test() {
1016         let v1 = key_perm_set![
1017             KeyPerm::manage_blob(),
1018             KeyPerm::delete(),
1019             KeyPerm::rebind(),
1020             KeyPerm::update(),
1021             KeyPerm::use_(),
1022         ];
1023         let v2 = key_perm_set![
1024             KeyPerm::manage_blob(),
1025             KeyPerm::delete(),
1026             KeyPerm::rebind(),
1027             KeyPerm::update(),
1028             KeyPerm::use_(),
1029         ];
1030         assert!(v1.includes(v2));
1031         assert!(v2.includes(v1));
1032     }
1033     #[test]
key_perm_set_include_overlap_test()1034     fn key_perm_set_include_overlap_test() {
1035         let v1 = key_perm_set![
1036             KeyPerm::manage_blob(),
1037             KeyPerm::delete(),
1038             KeyPerm::grant(), // only in v1
1039             KeyPerm::rebind(),
1040             KeyPerm::update(),
1041             KeyPerm::use_(),
1042         ];
1043         let v2 = key_perm_set![
1044             KeyPerm::manage_blob(),
1045             KeyPerm::delete(),
1046             KeyPerm::req_forced_op(), // only in v2
1047             KeyPerm::rebind(),
1048             KeyPerm::update(),
1049             KeyPerm::use_(),
1050         ];
1051         assert!(!v1.includes(v2));
1052         assert!(!v2.includes(v1));
1053     }
1054     #[test]
key_perm_set_include_no_overlap_test()1055     fn key_perm_set_include_no_overlap_test() {
1056         let v1 = key_perm_set![KeyPerm::manage_blob(), KeyPerm::delete(), KeyPerm::grant(),];
1057         let v2 = key_perm_set![
1058             KeyPerm::req_forced_op(),
1059             KeyPerm::rebind(),
1060             KeyPerm::update(),
1061             KeyPerm::use_(),
1062         ];
1063         assert!(!v1.includes(v2));
1064         assert!(!v2.includes(v1));
1065     }
1066 }
1067