• 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     user_id: i32,
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     match calling_info.group() {
76         Some(group) => alias.extend(group),
77         None => {
78             alias.extend_from_slice(&calling_info.owner_type().to_le_bytes());
79             alias.push(b'_');
80             alias.extend(calling_info.owner_info());
81         },
82     }
83     append_attr::<AuthType>("AuthType", auth_type, &mut alias);
84     append_attr::<Accessibility>("Accessibility", access_type, &mut alias);
85     append_attr::<bool>("RequirePasswordSet", require_password_set, &mut alias);
86     hasher::sha256(standard, &alias)
87 }
88 
get_existing_key_alias( calling_info: &CallingInfo, auth_type: AuthType, access_type: Accessibility, require_password_set: bool, ) -> Result<KeyAliasVersion>89 fn get_existing_key_alias(
90     calling_info: &CallingInfo,
91     auth_type: AuthType,
92     access_type: Accessibility,
93     require_password_set: bool,
94 ) -> Result<KeyAliasVersion> {
95     let new_alias = calculate_key_alias(calling_info, auth_type, access_type, require_password_set, true);
96     let prefixed_new_alias = [ALIAS_PREFIX.to_vec(), new_alias.clone()].concat();
97     let key = SecretKey {
98         user_id: calling_info.user_id(),
99         auth_type,
100         access_type,
101         require_password_set,
102         alias: prefixed_new_alias.clone(),
103     };
104     if key.exists()? {
105         logi!("[INFO][{access_type}]-typed secret key with v3 alias exists.");
106         return Ok(KeyAliasVersion::V3);
107     }
108 
109     let key = SecretKey {
110         user_id: calling_info.user_id(),
111         auth_type,
112         access_type,
113         require_password_set,
114         alias: new_alias.clone(),
115     };
116     if key.exists()? {
117         logi!("[INFO][{access_type}]-typed secret key with v2 alias exists.");
118         return Ok(KeyAliasVersion::V2(new_alias));
119     }
120 
121     let old_alias = calculate_key_alias(calling_info, auth_type, access_type, require_password_set, false);
122     let key = SecretKey {
123         user_id: calling_info.user_id(),
124         auth_type,
125         access_type,
126         require_password_set,
127         alias: old_alias.clone(),
128     };
129     if key.exists()? {
130         logi!("[INFO][{access_type}]-typed secret key with v1 alias exists.");
131         return Ok(KeyAliasVersion::V1(old_alias));
132     }
133 
134     Ok(KeyAliasVersion::None)
135 }
136 
huks_rename_key_alias( calling_info: &CallingInfo, auth_type: AuthType, access_type: Accessibility, require_password_set: bool, alias: Vec<u8>, ) -> i32137 fn huks_rename_key_alias(
138     calling_info: &CallingInfo,
139     auth_type: AuthType,
140     access_type: Accessibility,
141     require_password_set: bool,
142     alias: Vec<u8>,
143 ) -> i32 {
144     // Prepare secret key id with outdated alias.
145     let alias_ref = &alias;
146     let alias_blob = HksBlob { size: alias.len() as u32, data: alias_ref.as_ptr() };
147     let key_id = KeyId::new(calling_info.user_id(), alias_blob, access_type);
148 
149     // Prepare secret key alias to be replaced in.
150     let new_alias = calculate_key_alias(calling_info, auth_type, access_type, require_password_set, true);
151     let prefixed_new_alias = [ALIAS_PREFIX.to_vec(), new_alias].concat();
152     let prefixed_new_alias_ref = &prefixed_new_alias;
153     let prefixed_new_alias_blob =
154         HksBlob { size: prefixed_new_alias.len() as u32, data: prefixed_new_alias_ref.as_ptr() };
155 
156     unsafe { RenameKeyAlias(&key_id as *const KeyId, &prefixed_new_alias_blob as *const HksBlob) }
157 }
158 
159 /// Rename a secret key alias.
rename_key_alias( calling_info: &CallingInfo, auth_type: AuthType, access_type: Accessibility, require_password_set: bool, ) -> bool160 pub fn rename_key_alias(
161     calling_info: &CallingInfo,
162     auth_type: AuthType,
163     access_type: Accessibility,
164     require_password_set: bool,
165 ) -> bool {
166     match get_existing_key_alias(calling_info, auth_type, access_type, require_password_set) {
167         Ok(KeyAliasVersion::V3) => {
168             logi!("[INFO]Alias of [{access_type}]-typed secret key has already been renamed successfully.");
169             true
170         },
171         Ok(KeyAliasVersion::V2(alias)) | Ok(KeyAliasVersion::V1(alias)) => {
172             let ret = huks_rename_key_alias(calling_info, auth_type, access_type, require_password_set, alias);
173             if let SUCCESS = ret {
174                 logi!("[INFO]Rename alias of [{access_type}]-typed secret key success.");
175                 true
176             } else {
177                 loge!("[FATAL]Rename alias of [{access_type}]-typed secret key failed, err is {}.", ret);
178                 false
179             }
180         },
181         Ok(KeyAliasVersion::None) => {
182             loge!("[FATAL][{access_type}]-typed secret key does not exist.");
183             false
184         },
185         Err(e) => {
186             loge!("[FATAL]Can not determine whether [{access_type}]-typed secret key exists, err is {}", e);
187             false
188         },
189     }
190 }
191 
192 impl SecretKey {
193     /// New a secret key with the input key alias argument.
new_with_alias( user_id: i32, auth_type: AuthType, access_type: Accessibility, require_password_set: bool, alias: Vec<u8>, ) -> Result<Self>194     pub fn new_with_alias(
195         user_id: i32,
196         auth_type: AuthType,
197         access_type: Accessibility,
198         require_password_set: bool,
199         alias: Vec<u8>,
200     ) -> Result<Self> {
201         Ok(Self { user_id, auth_type, access_type, require_password_set, alias })
202     }
203 
204     /// Calculate key alias and then new a secret key.
new_without_alias( calling_info: &CallingInfo, auth_type: AuthType, access_type: Accessibility, require_password_set: bool, ) -> Result<Self>205     pub fn new_without_alias(
206         calling_info: &CallingInfo,
207         auth_type: AuthType,
208         access_type: Accessibility,
209         require_password_set: bool,
210     ) -> Result<Self> {
211         let new_alias = calculate_key_alias(calling_info, auth_type, access_type, require_password_set, true);
212         let prefixed_new_alias = [ALIAS_PREFIX.to_vec(), new_alias.clone()].concat();
213         let key = Self {
214             user_id: calling_info.user_id(),
215             auth_type,
216             access_type,
217             require_password_set,
218             alias: prefixed_new_alias,
219         };
220         Ok(key)
221     }
222 
223     /// Check whether the secret key exists.
exists(&self) -> Result<bool>224     pub fn exists(&self) -> Result<bool> {
225         let key_alias = HksBlob { size: self.alias.len() as u32, data: self.alias.as_ptr() };
226         let key_id = KeyId::new(self.user_id, key_alias, self.access_type);
227         let ret = unsafe { IsKeyExist(&key_id as *const KeyId) };
228         match ret {
229             SUCCESS => Ok(true),
230             ret if ret == ErrCode::NotFound as i32 => Ok(false),
231             _ => Err(transfer_error_code(ErrCode::try_from(ret as u32)?)),
232         }
233     }
234 
235     /// Generate the secret key and store in HUKS.
generate(&self) -> Result<()>236     pub fn generate(&self) -> Result<()> {
237         let key_alias = HksBlob { size: self.alias.len() as u32, data: self.alias.as_ptr() };
238         let key_id = KeyId::new(self.user_id, key_alias, self.access_type);
239         let ret = unsafe { GenerateKey(&key_id as *const KeyId, self.need_user_auth(), self.require_password_set) };
240         match ret {
241             SUCCESS => Ok(()),
242             _ => Err(transfer_error_code(ErrCode::try_from(ret as u32)?)),
243         }
244     }
245 
246     /// Delete the secret key.
delete(&self) -> Result<()>247     pub fn delete(&self) -> Result<()> {
248         let key_alias = HksBlob { size: self.alias.len() as u32, data: self.alias.as_ptr() };
249         let key_id = KeyId::new(self.user_id, key_alias, self.access_type);
250         let ret = unsafe { DeleteKey(&key_id as *const KeyId) };
251         match ret {
252             ret if ((ret == ErrCode::NotFound as i32) || ret == SUCCESS) => Ok(()),
253             _ => Err(transfer_error_code(ErrCode::try_from(ret as u32)?)),
254         }
255     }
256 
257     /// Delete secret key by owner.
delete_by_owner(calling_info: &CallingInfo) -> Result<()>258     pub fn delete_by_owner(calling_info: &CallingInfo) -> Result<()> {
259         let mut res = Ok(());
260         let accessibilitys =
261             [Accessibility::DevicePowerOn, Accessibility::DeviceFirstUnlocked, Accessibility::DeviceUnlocked];
262         for accessibility in accessibilitys.into_iter() {
263             let secret_key = SecretKey::new_without_alias(calling_info, AuthType::None, accessibility, true)?;
264             let tmp = secret_key.delete();
265             res = if tmp.is_err() { tmp } else { res };
266 
267             let secret_key = SecretKey::new_without_alias(calling_info, AuthType::Any, accessibility, true)?;
268             let tmp = secret_key.delete();
269             res = if tmp.is_err() { tmp } else { res };
270 
271             let secret_key = SecretKey::new_without_alias(calling_info, AuthType::None, accessibility, false)?;
272             let tmp = secret_key.delete();
273             res = if tmp.is_err() { tmp } else { res };
274 
275             let secret_key = SecretKey::new_without_alias(calling_info, AuthType::Any, accessibility, false)?;
276             let tmp = secret_key.delete();
277             res = if tmp.is_err() { tmp } else { res };
278         }
279 
280         res
281     }
282 
283     /// Determine whether user auth is required.
need_user_auth(&self) -> bool284     pub(crate) fn need_user_auth(&self) -> bool {
285         self.auth_type == AuthType::Any
286     }
287 
288     /// Determine whether device unlock is required.
need_device_unlock(&self) -> bool289     pub(crate) fn need_device_unlock(&self) -> bool {
290         self.access_type == Accessibility::DeviceUnlocked
291     }
292 
293     /// Get the key alias.
alias(&self) -> &Vec<u8>294     pub fn alias(&self) -> &Vec<u8> {
295         &self.alias
296     }
297 
298     /// Get the key access type
access_type(&self) -> Accessibility299     pub(crate) fn access_type(&self) -> Accessibility {
300         self.access_type
301     }
302 
303     /// Get the key user id.
user_id(&self) -> i32304     pub(crate) fn user_id(&self) -> i32 {
305         self.user_id
306     }
307 }
308