blob: b039506846f97a8cf29239f724ff475daee5d7ef [file] [log] [blame]
Hasini Gunasinghef04d07a2020-11-25 22:41:35 +00001// 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 the handling of background tasks such as obtaining timestamp tokens from
16//! the timestamp service (or TEE KeyMint in legacy devices), via a separate thread.
17
18use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
Janis Danisevskisc3a496b2021-01-05 10:37:22 -080019 HardwareAuthToken::HardwareAuthToken,
20};
21use android_hardware_security_secureclock::aidl::android::hardware::security::secureclock::{
22 ISecureClock::ISecureClock, TimeStampToken::TimeStampToken,
Hasini Gunasinghef04d07a2020-11-25 22:41:35 +000023};
24use android_system_keystore2::aidl::android::system::keystore2::OperationChallenge::OperationChallenge;
25use anyhow::Result;
26use log::error;
27use std::sync::mpsc::{Receiver, Sender};
28use std::sync::Mutex;
29use std::thread::{spawn, JoinHandle};
Janis Danisevskisc3a496b2021-01-05 10:37:22 -080030
31use crate::globals::get_timestamp_service;
32
Hasini Gunasinghef04d07a2020-11-25 22:41:35 +000033/// This is the struct encapsulating the thread which handles background tasks such as
Janis Danisevskisc3a496b2021-01-05 10:37:22 -080034/// obtaining timestamp tokens.
Hasini Gunasinghef04d07a2020-11-25 22:41:35 +000035pub struct BackgroundTaskHandler {
36 task_handler: Mutex<Option<JoinHandle<()>>>,
37}
Janis Danisevskisc3a496b2021-01-05 10:37:22 -080038
Hasini Gunasinghef04d07a2020-11-25 22:41:35 +000039/// This enum defines the two variants of a message that can be passed down to the
40/// BackgroundTaskHandler via the channel.
41pub enum Message {
42 ///This variant represents a message sent down the channel when requesting a timestamp token.
Janis Danisevskisc3a496b2021-01-05 10:37:22 -080043 Inputs((HardwareAuthToken, OperationChallenge, Sender<(HardwareAuthToken, TimeStampToken)>)),
Hasini Gunasinghef04d07a2020-11-25 22:41:35 +000044 ///This variant represents a message sent down the channel when signalling the thread to stop.
45 Shutdown,
46}
47
48impl BackgroundTaskHandler {
49 /// Initialize the BackgroundTaskHandler with the task_handler field set to None.
50 /// The thread is not started during initialization, as it needs the receiver end of a channel
51 /// to function.
52 pub fn new() -> Self {
53 BackgroundTaskHandler { task_handler: Mutex::new(None) }
54 }
55
56 /// Start the background task handler (bth) by passing in the receiver end of a channel, through
57 /// which the enforcement module can send messages to the bth thread.
58 pub fn start_bth(&self, receiver: Receiver<Message>) -> Result<()> {
59 let task_handler = Self::start_thread(receiver)?;
60 // it is ok to unwrap here because there is no way that this lock can get poisoned.
61 let mut thread_guard = self.task_handler.lock().unwrap();
62 *thread_guard = Some(task_handler);
63 Ok(())
64 }
65
66 fn start_thread(receiver: Receiver<Message>) -> Result<JoinHandle<()>> {
67 // TODO: initialize timestamp service/keymint instances.
68 // First lookup timestamp token service, if this is not a legacy device.
69 // Otherwise, lookup keymaster 4.1 or 4.0 (previous ones are not relevant, because strongbox
70 // was introduced with keymaster 4.0).
71 // If either a timestamp service or a keymint instance is expected to be found and neither
72 // is found, an error is returned.
73 // If neither is expected to be found, make timestamp_service field None, and in the thread,
Janis Danisevskisc3a496b2021-01-05 10:37:22 -080074 // send a default timestamp token down the channel to the operation.
Hasini Gunasinghef04d07a2020-11-25 22:41:35 +000075 // Until timestamp service is available and proper probing of legacy keymaster devices are
76 // done, the keymint service is initialized here as it is done in security_level module.
77 Ok(spawn(move || {
Janis Danisevskisc3a496b2021-01-05 10:37:22 -080078 while let Message::Inputs((auth_token, op_challenge, op_sender)) =
79 receiver.recv().expect(
80 "In background task handler thread. Failed to
81 receive message over the channel.",
82 )
83 {
84 let dev: Box<dyn ISecureClock> = get_timestamp_service()
85 .expect(concat!(
86 "Secure Clock service must be present ",
87 "if TimeStampTokens are required."
88 ))
89 .get_interface()
90 .expect("Fatal: Timestamp service does not implement ISecureClock.");
91 let result = dev.generateTimeStamp(op_challenge.challenge);
Hasini Gunasinghef04d07a2020-11-25 22:41:35 +000092 match result {
Janis Danisevskisc3a496b2021-01-05 10:37:22 -080093 Ok(timestamp_token) => {
Hasini Gunasinghef04d07a2020-11-25 22:41:35 +000094 // this can fail if the operation is dropped and hence the channel
95 // is hung up.
Janis Danisevskisc3a496b2021-01-05 10:37:22 -080096 op_sender.send((auth_token, timestamp_token)).unwrap_or_else(|e| {
Hasini Gunasinghef04d07a2020-11-25 22:41:35 +000097 error!(
98 "In background task handler thread. Failed to send
Janis Danisevskisc3a496b2021-01-05 10:37:22 -080099 timestamp token to operation {} due to error {:?}.",
Hasini Gunasinghef04d07a2020-11-25 22:41:35 +0000100 op_challenge.challenge, e
101 )
102 });
103 }
104 Err(e) => {
105 // log error
106 error!(
107 "In background task handler thread. Failed to receive
Janis Danisevskisc3a496b2021-01-05 10:37:22 -0800108 timestamp token for operation {} due to error {:?}.",
Hasini Gunasinghef04d07a2020-11-25 22:41:35 +0000109 op_challenge.challenge, e
110 );
Janis Danisevskisc3a496b2021-01-05 10:37:22 -0800111 // send default timestamp token
Hasini Gunasinghef04d07a2020-11-25 22:41:35 +0000112 // this can fail if the operation is dropped and the channel is
113 // hung up.
Janis Danisevskisc3a496b2021-01-05 10:37:22 -0800114 op_sender.send((auth_token, TimeStampToken::default())).unwrap_or_else(
Hasini Gunasinghef04d07a2020-11-25 22:41:35 +0000115 |e| {
116 error!(
117 "In background task handler thread. Failed to send default
Janis Danisevskisc3a496b2021-01-05 10:37:22 -0800118 timestamp token to operation {} due to error {:?}.",
Hasini Gunasinghef04d07a2020-11-25 22:41:35 +0000119 op_challenge.challenge, e
120 )
121 },
122 );
123 }
124 }
125 }
126 }))
127 }
128}
129
130impl Default for BackgroundTaskHandler {
131 fn default() -> Self {
132 Self::new()
133 }
134}
135
136// TODO: Verify if we want the thread to finish the requests they are working on, during drop.
137impl Drop for BackgroundTaskHandler {
138 fn drop(&mut self) {
139 // it is ok to unwrap here as there is no way this lock can get poisoned.
140 let mut thread_guard = self.task_handler.lock().unwrap();
141 if let Some(thread) = (*thread_guard).take() {
142 // TODO: Verify how best to handle the error in this case.
143 thread.join().unwrap_or_else(|e| {
144 panic!("Failed to join the background task handling thread because of {:?}.", e);
145 });
146 }
147 }
148}