• 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 implement cryptographic algorithm operations, including key generation.
17 
18 use asset_common::{transfer_error_code, CallingInfo, SUCCESS};
19 use asset_definition::{Accessibility, AuthType, ErrCode, Result};
20 use asset_log::{loge, logi};
21 use asset_utils::hasher;
22 
23 use crate::{HksBlob, KeyId};
24 
25 /// Struct to store key attributes, excluding key materials.
26 #[derive(Clone)]
27 pub struct SecretKey {
28     auth_type: AuthType,
29     access_type: Accessibility,
30     require_password_set: bool,
31     alias: Vec<u8>,
32     calling_info: CallingInfo,
33 }
34 
35 enum KeyAliasVersion {
36     V1(Vec<u8>), // Old secret key alias
37     V2(Vec<u8>), // New secret key alias
38     V3,          // Prefixed new secret key alias
39     None,
40 }
41 
42 extern "C" {
GenerateKey(keyId: *const KeyId, need_auth: bool, require_password_set: bool) -> i3243     fn GenerateKey(keyId: *const KeyId, need_auth: bool, require_password_set: bool) -> i32;
DeleteKey(keyId: *const KeyId) -> i3244     fn DeleteKey(keyId: *const KeyId) -> i32;
IsKeyExist(keyId: *const KeyId) -> i3245     fn IsKeyExist(keyId: *const KeyId) -> i32;
RenameKeyAlias(keyId: *const KeyId, newKeyAlias: *const HksBlob) -> i3246     fn RenameKeyAlias(keyId: *const KeyId, newKeyAlias: *const HksBlob) -> i32;
47 }
48 
49 const MAX_ALIAS_SIZE: usize = 64;
50 const ALIAS_PREFIX: [u8; 2] = [b'1', b'_'];
51 
append_attr<T>(tag: &str, value: T, vec: &mut Vec<u8>) where T: Default + std::cmp::PartialEq, u32: std::convert::From<T>,52 fn append_attr<T>(tag: &str, value: T, vec: &mut Vec<u8>)
53 where
54     T: Default + std::cmp::PartialEq,
55     u32: std::convert::From<T>,
56 {
57     if value != T::default() {
58         vec.push(b'_');
59         vec.extend_from_slice(tag.as_bytes());
60         vec.push(b':');
61         vec.extend_from_slice(&u32::from(value).to_le_bytes());
62     }
63 }
64 
calculate_key_alias( calling_info: &CallingInfo, auth_type: AuthType, access_type: Accessibility, require_password_set: bool, standard: bool, ) -> Vec<u8>65 fn calculate_key_alias(
66     calling_info: &CallingInfo,
67     auth_type: AuthType,
68     access_type: Accessibility,
69     require_password_set: bool,
70     standard: bool,
71 ) -> Vec<u8> {
72     let mut alias: Vec<u8> = Vec::with_capacity(MAX_ALIAS_SIZE);
73     alias.extend_from_slice(&calling_info.user_id().to_le_bytes());
74     alias.push(b'_');
75     alias.extend_from_slice(&calling_info.owner_type().to_le_bytes());
76     alias.push(b'_');
77     alias.extend(calling_info.owner_info());
78     append_attr::<AuthType>("AuthType", auth_type, &mut alias);
79     append_attr::<Accessibility>("Accessibility", access_type, &mut alias);
80     append_attr::<bool>("RequirePasswordSet", require_password_set, &mut alias);
81     hasher::sha256(standard, &alias)
82 }
83 
get_existing_key_alias( calling_info: &CallingInfo, auth_type: AuthType, access_type: Accessibility, require_password_set: bool, ) -> Result<KeyAliasVersion>84 fn get_existing_key_alias(
85     calling_info: &CallingInfo,
86     auth_type: AuthType,
87     access_type: Accessibility,
88     require_password_set: bool,
89 ) -> Result<KeyAliasVersion> {
90     let new_alias = calculate_key_alias(calling_info, auth_type, access_type, require_password_set, true);
91     let prefixed_new_alias = [ALIAS_PREFIX.to_vec(), new_alias.clone()].concat();
92     let key = SecretKey {
93         auth_type,
94         access_type,
95         require_password_set,
96         alias: prefixed_new_alias.clone(),
97         calling_info: calling_info.clone(),
98     };
99     if key.exists()? {
100         logi!("[INFO][{access_type}]-typed secret key with v3 alias exists.");
101         return Ok(KeyAliasVersion::V3);
102     }
103 
104     let key = SecretKey {
105         auth_type,
106         access_type,
107         require_password_set,
108         alias: new_alias.clone(),
109         calling_info: calling_info.clone(),
110     };
111     if key.exists()? {
112         logi!("[INFO][{access_type}]-typed secret key with v2 alias exists.");
113         return Ok(KeyAliasVersion::V2(new_alias));
114     }
115 
116     let old_alias = calculate_key_alias(calling_info, auth_type, access_type, require_password_set, false);
117     let key = SecretKey {
118         auth_type,
119         access_type,
120         require_password_set,
121         alias: old_alias.clone(),
122         calling_info: calling_info.clone(),
123     };
124     if key.exists()? {
125         logi!("[INFO][{access_type}]-typed secret key with v1 alias exists.");
126         return Ok(KeyAliasVersion::V1(old_alias));
127     }
128 
129     Ok(KeyAliasVersion::None)
130 }
131 
huks_rename_key_alias( calling_info: &CallingInfo, auth_type: AuthType, access_type: Accessibility, require_password_set: bool, alias: Vec<u8>, ) -> i32132 fn huks_rename_key_alias(
133     calling_info: &CallingInfo,
134     auth_type: AuthType,
135     access_type: Accessibility,
136     require_password_set: bool,
137     alias: Vec<u8>,
138 ) -> i32 {
139     // Prepare secret key id with outdated alias.
140     let alias_ref = &alias;
141     let alias_blob = HksBlob { size: alias.len() as u32, data: alias_ref.as_ptr() };
142     let key_id = KeyId::new(calling_info.user_id(), alias_blob, access_type);
143 
144     // Prepare secret key alias to be replaced in.
145     let new_alias = calculate_key_alias(calling_info, auth_type, access_type, require_password_set, true);
146     let prefixed_new_alias = [ALIAS_PREFIX.to_vec(), new_alias].concat();
147     let prefixed_new_alias_ref = &prefixed_new_alias;
148     let prefixed_new_alias_blob =
149         HksBlob { size: prefixed_new_alias.len() as u32, data: prefixed_new_alias_ref.as_ptr() };
150 
151     unsafe { RenameKeyAlias(&key_id as *const KeyId, &prefixed_new_alias_blob as *const HksBlob) }
152 }
153 
154 /// Rename a secret key alias.
rename_key_alias( calling_info: &CallingInfo, auth_type: AuthType, access_type: Accessibility, require_password_set: bool, ) -> bool155 pub fn rename_key_alias(
156     calling_info: &CallingInfo,
157     auth_type: AuthType,
158     access_type: Accessibility,
159     require_password_set: bool,
160 ) -> bool {
161     match get_existing_key_alias(calling_info, auth_type, access_type, require_password_set) {
162         Ok(KeyAliasVersion::V3) => {
163             logi!("[INFO]Alias of [{access_type}]-typed secret key has already been renamed successfully.");
164             true
165         },
166         Ok(KeyAliasVersion::V2(alias)) | Ok(KeyAliasVersion::V1(alias)) => {
167             let ret = huks_rename_key_alias(calling_info, auth_type, access_type, require_password_set, alias);
168             if let SUCCESS = ret {
169                 logi!("[INFO]Rename alias of [{access_type}]-typed secret key success.");
170                 true
171             } else {
172                 loge!("[FATAL]Rename alias of [{access_type}]-typed secret key failed, err is {}.", ret);
173                 false
174             }
175         },
176         Ok(KeyAliasVersion::None) => {
177             loge!("[FATAL][{access_type}]-typed secret key does not exist.");
178             false
179         },
180         Err(e) => {
181             loge!("[FATAL]Can not determine whether [{access_type}]-typed secret key exists, err is {}", e);
182             false
183         },
184     }
185 }
186 
187 impl SecretKey {
188     /// New a secret key.
new( calling_info: &CallingInfo, auth_type: AuthType, access_type: Accessibility, require_password_set: bool, ) -> Result<Self>189     pub fn new(
190         calling_info: &CallingInfo,
191         auth_type: AuthType,
192         access_type: Accessibility,
193         require_password_set: bool,
194     ) -> Result<Self> {
195         let new_alias = calculate_key_alias(calling_info, auth_type, access_type, require_password_set, true);
196         let prefixed_new_alias = [ALIAS_PREFIX.to_vec(), new_alias.clone()].concat();
197         let key = Self {
198             auth_type,
199             access_type,
200             require_password_set,
201             alias: prefixed_new_alias,
202             calling_info: calling_info.clone(),
203         };
204         Ok(key)
205     }
206 
207     /// Check whether the secret key exists.
exists(&self) -> Result<bool>208     pub fn exists(&self) -> Result<bool> {
209         let key_alias = HksBlob { size: self.alias.len() as u32, data: self.alias.as_ptr() };
210         let key_id = KeyId::new(self.calling_info().user_id(), key_alias, self.access_type);
211         let ret = unsafe { IsKeyExist(&key_id as *const KeyId) };
212         match ret {
213             SUCCESS => Ok(true),
214             ret if ret == ErrCode::NotFound as i32 => Ok(false),
215             _ => Err(transfer_error_code(ErrCode::try_from(ret as u32)?)),
216         }
217     }
218 
219     /// Generate the secret key and store in HUKS.
generate(&self) -> Result<()>220     pub fn generate(&self) -> Result<()> {
221         let key_alias = HksBlob { size: self.alias.len() as u32, data: self.alias.as_ptr() };
222         let key_id = KeyId::new(self.calling_info().user_id(), key_alias, self.access_type);
223         let ret = unsafe { GenerateKey(&key_id as *const KeyId, self.need_user_auth(), self.require_password_set) };
224         match ret {
225             SUCCESS => Ok(()),
226             _ => Err(transfer_error_code(ErrCode::try_from(ret as u32)?)),
227         }
228     }
229 
230     /// Delete the secret key.
delete(&self) -> Result<()>231     pub fn delete(&self) -> Result<()> {
232         let key_alias = HksBlob { size: self.alias.len() as u32, data: self.alias.as_ptr() };
233         let key_id = KeyId::new(self.calling_info().user_id(), key_alias, self.access_type);
234         let ret = unsafe { DeleteKey(&key_id as *const KeyId) };
235         match ret {
236             ret if ((ret == ErrCode::NotFound as i32) || ret == SUCCESS) => Ok(()),
237             _ => Err(transfer_error_code(ErrCode::try_from(ret as u32)?)),
238         }
239     }
240 
241     /// Delete secret key by owner.
delete_by_owner(calling_info: &CallingInfo) -> Result<()>242     pub fn delete_by_owner(calling_info: &CallingInfo) -> Result<()> {
243         let mut res = Ok(());
244         let accessibilitys =
245             [Accessibility::DevicePowerOn, Accessibility::DeviceFirstUnlocked, Accessibility::DeviceUnlocked];
246         for accessibility in accessibilitys.into_iter() {
247             let secret_key = SecretKey::new(calling_info, AuthType::None, accessibility, true)?;
248             let tmp = secret_key.delete();
249             res = if tmp.is_err() { tmp } else { res };
250 
251             let secret_key = SecretKey::new(calling_info, AuthType::Any, accessibility, true)?;
252             let tmp = secret_key.delete();
253             res = if tmp.is_err() { tmp } else { res };
254 
255             let secret_key = SecretKey::new(calling_info, AuthType::None, accessibility, false)?;
256             let tmp = secret_key.delete();
257             res = if tmp.is_err() { tmp } else { res };
258 
259             let secret_key = SecretKey::new(calling_info, AuthType::Any, accessibility, false)?;
260             let tmp = secret_key.delete();
261             res = if tmp.is_err() { tmp } else { res };
262         }
263         res
264     }
265 
266     /// Determine whether user auth is required.
need_user_auth(&self) -> bool267     pub(crate) fn need_user_auth(&self) -> bool {
268         self.auth_type == AuthType::Any
269     }
270 
271     /// Determine whether device unlock is required.
need_device_unlock(&self) -> bool272     pub(crate) fn need_device_unlock(&self) -> bool {
273         self.access_type == Accessibility::DeviceUnlocked
274     }
275 
276     /// Get the key alias.
alias(&self) -> &Vec<u8>277     pub(crate) fn alias(&self) -> &Vec<u8> {
278         &self.alias
279     }
280 
281     /// Get the key access type
access_type(&self) -> Accessibility282     pub(crate) fn access_type(&self) -> Accessibility {
283         self.access_type
284     }
285 
286     /// Get the key calling info
calling_info(&self) -> &CallingInfo287     pub(crate) fn calling_info(&self) -> &CallingInfo {
288         &self.calling_info
289     }
290 }
291