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::{ 19 cmp::max, 20 sync::{Arc, Mutex}, 21 }; 22 23 use asset_common::CallingInfo; 24 use asset_definition::{log_throw_error, ErrCode, Result}; 25 26 use crate::crypto::Crypto; 27 28 const CRYPTO_CAPACITY: usize = 16; 29 30 /// Manages the crypto that required user authentication. 31 pub struct CryptoManager { 32 cryptos: Vec<Crypto>, 33 } 34 35 impl CryptoManager { new() -> Self36 fn new() -> Self { 37 Self { cryptos: vec![] } 38 } 39 40 /// Get the single instance of CryptoManager. get_instance() -> Arc<Mutex<CryptoManager>>41 pub fn get_instance() -> Arc<Mutex<CryptoManager>> { 42 static mut INSTANCE: Option<Arc<Mutex<CryptoManager>>> = None; 43 unsafe { INSTANCE.get_or_insert_with(|| Arc::new(Mutex::new(CryptoManager::new()))).clone() } 44 } 45 46 /// Add the crypto to manager. add(&mut self, crypto: Crypto) -> Result<()>47 pub fn add(&mut self, crypto: Crypto) -> Result<()> { 48 self.remove_expired_crypto()?; 49 if self.cryptos.len() >= CRYPTO_CAPACITY { 50 log_throw_error!(ErrCode::LimitExceeded, "The number of cryptos exceeds the upper limit.") 51 } else { 52 self.cryptos.push(crypto); 53 Ok(()) 54 } 55 } 56 57 /// Find the crypto with the specified alias and challenge slice from manager. find(&mut self, calling_info: &CallingInfo, challenge: &Vec<u8>) -> Result<&Crypto>58 pub fn find(&mut self, calling_info: &CallingInfo, challenge: &Vec<u8>) -> Result<&Crypto> { 59 self.remove_expired_crypto()?; 60 for crypto in self.cryptos.iter() { 61 if crypto.challenge().eq(challenge) && crypto.calling_info().eq(calling_info) { 62 return Ok(crypto); 63 } 64 } 65 log_throw_error!(ErrCode::NotFound, "The crypto expires or does not exist. Call the preQuery first.") 66 } 67 68 /// Remove the crypto from manager. remove(&mut self, calling_info: &CallingInfo, challenge: &Vec<u8>)69 pub fn remove(&mut self, calling_info: &CallingInfo, challenge: &Vec<u8>) { 70 self.cryptos.retain(|crypto| crypto.calling_info() != calling_info || !crypto.challenge().eq(challenge)); 71 } 72 73 /// Remove the crypto by calling info. remove_by_calling_info(&mut self, calling_info: &CallingInfo)74 pub fn remove_by_calling_info(&mut self, calling_info: &CallingInfo) { 75 self.cryptos.retain(|crypto| crypto.calling_info() != calling_info); 76 } 77 78 /// Remove cryptos that required device to be unlocked. remove_need_device_unlocked(&mut self)79 pub fn remove_need_device_unlocked(&mut self) { 80 self.cryptos.retain(|crypto| !crypto.key().need_device_unlock()); 81 } 82 83 /// Get last crypto expire time. max_crypto_expire_duration(&mut self) -> u6484 pub fn max_crypto_expire_duration(&mut self) -> u64 { 85 self.remove_expired_crypto().unwrap(); 86 let mut max_time = 0; 87 for crypto in &self.cryptos { 88 max_time = max(crypto.valid_time() as u64 - crypto.start_time().elapsed().as_secs(), max_time) 89 } 90 max_time 91 } 92 remove_expired_crypto(&mut self) -> Result<()>93 fn remove_expired_crypto(&mut self) -> Result<()> { 94 self.cryptos.retain(|crypto| crypto.start_time().elapsed().as_secs() <= crypto.valid_time() as u64); 95 Ok(()) 96 } 97 } 98