• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
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 
16 //! This module is used to manage crypto in cache.
17 
18 use std::sync::{Arc, Mutex};
19 
20 use asset_constants::CallingInfo;
21 use asset_definition::{log_throw_error, ErrCode, Result};
22 
23 use crate::crypto::Crypto;
24 
25 const CRYPTO_CAPACITY: usize = 16;
26 
27 /// Manages the crypto that required user authentication.
28 pub struct CryptoManager {
29     cryptos: Vec<Crypto>,
30 }
31 
32 impl CryptoManager {
new() -> Self33     fn new() -> Self {
34         Self { cryptos: vec![] }
35     }
36 
37     /// Get the single instance of CryptoManager.
get_instance() -> Arc<Mutex<CryptoManager>>38     pub fn get_instance() -> Arc<Mutex<CryptoManager>> {
39         static mut INSTANCE: Option<Arc<Mutex<CryptoManager>>> = None;
40         unsafe { INSTANCE.get_or_insert_with(|| Arc::new(Mutex::new(CryptoManager::new()))).clone() }
41     }
42 
43     /// Add the crypto to manager.
add(&mut self, crypto: Crypto) -> Result<()>44     pub fn add(&mut self, crypto: Crypto) -> Result<()> {
45         self.remove_expired_crypto()?;
46         if self.cryptos.len() >= CRYPTO_CAPACITY {
47             log_throw_error!(ErrCode::LimitExceeded, "The number of cryptos exceeds the upper limit.")
48         } else {
49             self.cryptos.push(crypto);
50             Ok(())
51         }
52     }
53 
54     /// Find the crypto with the specified alias and challenge slice from manager.
find(&mut self, calling_info: &CallingInfo, challenge: &Vec<u8>) -> Result<&Crypto>55     pub fn find(&mut self, calling_info: &CallingInfo, challenge: &Vec<u8>) -> Result<&Crypto> {
56         self.remove_expired_crypto()?;
57         for crypto in self.cryptos.iter() {
58             if crypto.challenge().eq(challenge) && crypto.key().calling_info().eq(calling_info) {
59                 return Ok(crypto);
60             }
61         }
62         log_throw_error!(ErrCode::NotFound, "The crypto expires or does not exist. Call the preQuery first.")
63     }
64 
65     /// Remove the crypto from manager.
remove(&mut self, calling_info: &CallingInfo, challenge: &Vec<u8>)66     pub fn remove(&mut self, calling_info: &CallingInfo, challenge: &Vec<u8>) {
67         self.cryptos.retain(|crypto|
68             crypto.key().calling_info() != calling_info || !crypto.challenge().eq(challenge)
69         );
70     }
71 
72     /// Remove the crypto by calling info.
remove_by_calling_info(&mut self, calling_info: &CallingInfo)73     pub fn remove_by_calling_info(&mut self, calling_info: &CallingInfo) {
74         self.cryptos.retain(|crypto| crypto.key().calling_info() != calling_info );
75     }
76 
77     /// Remove cryptos that required device to be unlocked.
remove_need_device_unlocked(&mut self)78     pub fn remove_need_device_unlocked(&mut self) {
79         self.cryptos.retain(|crypto| !crypto.key().need_device_unlock());
80     }
81 
remove_expired_crypto(&mut self) -> Result<()>82     fn remove_expired_crypto(&mut self) -> Result<()> {
83         self.cryptos.retain(|crypto| crypto.start_time().elapsed().as_secs() <= crypto.valid_time() as u64);
84         Ok(())
85     }
86 }
87