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