blob: 27044dd4bba9368378389e3c1343433af6c98375 [file] [log] [blame]
Janis Danisevskisa75e2082020-10-07 16:44:26 -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 module implements utility functions used by the Keystore 2.0 service
16//! implementation.
17
18use crate::error::Error;
19use crate::permission;
20use crate::permission::{KeyPerm, KeyPermSet, KeystorePerm};
21use android_hardware_keymint::aidl::android::hardware::keymint::{
22 KeyParameter::KeyParameter as KmParam, Tag::Tag,
23};
24use android_system_keystore2::aidl::android::system::keystore2::{
25 KeyDescriptor::KeyDescriptor, KeyParameter::KeyParameter,
26};
27use anyhow::{anyhow, Context};
28use binder::{FromIBinder, SpIBinder, ThreadState};
29use std::sync::Mutex;
30
31/// This function uses its namesake in the permission module and in
32/// combination with with_calling_sid from the binder crate to check
33/// if the caller has the given keystore permission.
34pub fn check_keystore_permission(perm: KeystorePerm) -> anyhow::Result<()> {
35 ThreadState::with_calling_sid(|calling_sid| {
36 permission::check_keystore_permission(
37 &calling_sid.ok_or_else(Error::sys).context(
38 "In check_keystore_permission: Cannot check permission without calling_sid.",
39 )?,
40 perm,
41 )
42 })
43}
44
45/// This function uses its namesake in the permission module and in
46/// combination with with_calling_sid from the binder crate to check
47/// if the caller has the given grant permission.
48pub fn check_grant_permission(access_vec: KeyPermSet, key: &KeyDescriptor) -> anyhow::Result<()> {
49 ThreadState::with_calling_sid(|calling_sid| {
50 permission::check_grant_permission(
51 &calling_sid.ok_or_else(Error::sys).context(
52 "In check_grant_permission: Cannot check permission without calling_sid.",
53 )?,
54 access_vec,
55 key,
56 )
57 })
58}
59
60/// This function uses its namesake in the permission module and in
61/// combination with with_calling_sid from the binder crate to check
62/// if the caller has the given key permission.
63pub fn check_key_permission(
64 perm: KeyPerm,
65 key: &KeyDescriptor,
66 access_vector: &Option<KeyPermSet>,
67) -> anyhow::Result<()> {
68 ThreadState::with_calling_sid(|calling_sid| {
69 permission::check_key_permission(
70 &calling_sid
71 .ok_or_else(Error::sys)
72 .context("In check_key_permission: Cannot check permission without calling_sid.")?,
73 perm,
74 key,
75 access_vector,
76 )
77 })
78}
79
80/// This function converts a `KeyParameter` from the keystore2 AIDL
81/// bindings into a `KeyParameter` from the keymint AIDL bindings.
82/// TODO This is a temporary workaround until the keymint AIDL spec
83/// lands.
84pub fn keyparam_ks_to_km(p: &KeyParameter) -> KmParam {
85 KmParam {
86 tag: Tag(p.tag),
87 boolValue: p.boolValue,
88 integer: p.integer,
89 longInteger: p.longInteger,
90 dateTime: p.dateTime,
91 blob: match &p.blob {
92 Some(b) => b.clone(),
93 None => vec![],
94 },
95 }
96}
97
Janis Danisevskis2c7f9622020-09-30 16:30:31 -070098/// This function converts a `KeyParameter` from the keymint AIDL
99/// bindings into a `KeyParameter` from the keystore2 AIDL bindings.
100/// TODO This is a temporary workaround until the keymint AIDL spec
101/// lands.
102pub fn keyparam_km_to_ks(p: &KmParam) -> KeyParameter {
103 KeyParameter {
104 tag: p.tag.0,
105 boolValue: p.boolValue,
106 integer: p.integer,
107 longInteger: p.longInteger,
108 dateTime: p.dateTime,
109 blob: match p.blob.len() {
110 0 => None,
111 _ => Some(p.blob.clone()),
112 },
113 }
114}
115
Janis Danisevskisa75e2082020-10-07 16:44:26 -0700116/// Thread safe wrapper around SpIBinder. It is safe to have SpIBinder smart pointers to the
117/// same object in multiple threads, but cloning a SpIBinder is not thread safe.
118/// Keystore frequently hands out binder tokens to the security level interface. If this
119/// is to happen from a multi threaded thread pool, the SpIBinder needs to be protected by a
120/// Mutex.
121#[derive(Debug)]
122pub struct Asp(Mutex<SpIBinder>);
123
124impl Asp {
125 /// Creates a new instance owning a SpIBinder wrapped in a Mutex.
126 pub fn new(i: SpIBinder) -> Self {
127 Self(Mutex::new(i))
128 }
129
130 /// Clones the owned SpIBinder and attempts to convert it into the requested interface.
131 pub fn get_interface<T: FromIBinder + ?Sized>(&self) -> anyhow::Result<Box<T>> {
132 // We can use unwrap here because we never panic when locked, so the mutex
133 // can never be poisoned.
134 let lock = self.0.lock().unwrap();
135 (*lock)
136 .clone()
137 .into_interface()
138 .map_err(|e| anyhow!(format!("get_interface failed with error code {:?}", e)))
139 }
140}