• 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 #include <stdint.h>
17 
18 #include "hks_api.h"
19 #include "hks_param.h"
20 
21 #include "asset_log.h"
22 #include "asset_type.h"
23 #include "huks_wrapper.h"
24 
AccessibilityToHksAuthStorageLevel(enum Accessibility accessibility)25 static enum HksAuthStorageLevel AccessibilityToHksAuthStorageLevel(enum Accessibility accessibility)
26 {
27     switch (accessibility) {
28         case DEVICE_POWERED_ON:
29             return HKS_AUTH_STORAGE_LEVEL_DE;
30         case DEVICE_FIRST_UNLOCKED:
31             return HKS_AUTH_STORAGE_LEVEL_CE;
32         default:
33             return HKS_AUTH_STORAGE_LEVEL_ECE;
34     }
35 }
36 
HuksErrorTransfer(int32_t ret)37 static int32_t HuksErrorTransfer(int32_t ret)
38 {
39     switch (ret) {
40         case HKS_SUCCESS:
41             return ASSET_SUCCESS;
42         case HKS_ERROR_NO_PERMISSION:
43         case HKS_ERROR_DEVICE_PASSWORD_UNSET:
44             return ASSET_STATUS_MISMATCH;
45         case HKS_ERROR_NOT_EXIST:
46             return ASSET_NOT_FOUND;
47         case HKS_ERROR_KEY_AUTH_FAILED:
48         case HKS_ERROR_KEY_AUTH_VERIFY_FAILED:
49             return ASSET_ACCESS_DENIED;
50         default:
51             return ASSET_CRYPTO_ERROR;
52     }
53 }
54 
BuildParamSet(struct HksParamSet ** paramSet,const struct HksParam * params,uint32_t paramCount)55 static int32_t BuildParamSet(struct HksParamSet **paramSet, const struct HksParam *params, uint32_t paramCount)
56 {
57     int32_t ret = HksInitParamSet(paramSet);
58     if (ret != HKS_SUCCESS) {
59         LOGE("[FATAL]HUKS init param set failed. error=%{public}d", ret);
60         return ret;
61     }
62 
63     if (paramCount != 0) {
64         ret = HksAddParams(*paramSet, params, paramCount);
65         if (ret != HKS_SUCCESS) {
66             LOGE("[FATAL]HUKS add params failed. error=%{public}d", ret);
67             HksFreeParamSet(paramSet);
68             return ret;
69         }
70     }
71 
72     ret = HksBuildParamSet(paramSet);
73     if (ret != HKS_SUCCESS) {
74         LOGE("[FATAL]HUKS build param set failed. error=%{public}d", ret);
75         HksFreeParamSet(paramSet);
76     }
77     return ret;
78 }
79 
AddCommonGenParams(struct HksParamSet * paramSet,const struct KeyId * keyId)80 static int32_t AddCommonGenParams(struct HksParamSet *paramSet, const struct KeyId *keyId)
81 {
82     struct HksParam commonParams[] = {
83         { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES },
84         { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT },
85         { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 },
86         { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE },
87         { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM },
88         { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = AccessibilityToHksAuthStorageLevel(keyId->accessibility) },
89         { .tag = HKS_TAG_SPECIFIC_USER_ID, .int32Param = keyId->userId },
90     };
91     return HksAddParams(paramSet, commonParams, ARRAY_SIZE(commonParams));
92 }
93 
AddAuthGenParams(struct HksParamSet * paramSet)94 static int32_t AddAuthGenParams(struct HksParamSet *paramSet)
95 {
96     struct HksParam authParams[] = {
97         { .tag = HKS_TAG_KEY_AUTH_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_DECRYPT },
98         { .tag = HKS_TAG_KEY_AUTH_ACCESS_TYPE, .uint32Param = HKS_AUTH_ACCESS_ALWAYS_VALID },
99         { .tag = HKS_TAG_BATCH_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_DECRYPT },
100         { .tag = HKS_TAG_CHALLENGE_TYPE, .uint32Param = HKS_CHALLENGE_TYPE_NORMAL },
101         { .tag = HKS_TAG_USER_AUTH_TYPE, .uint32Param =
102             HKS_USER_AUTH_TYPE_FINGERPRINT | HKS_USER_AUTH_TYPE_FACE | HKS_USER_AUTH_TYPE_PIN }
103     };
104     return HksAddParams(paramSet, authParams, ARRAY_SIZE(authParams));
105 }
106 
GenerateKey(const struct KeyId * keyId,bool needAuth,bool requirePasswordSet)107 int32_t GenerateKey(const struct KeyId *keyId, bool needAuth, bool requirePasswordSet)
108 {
109     struct HksParamSet *paramSet = NULL;
110     int32_t ret = HKS_SUCCESS;
111     do {
112         ret = HksInitParamSet(&paramSet);
113         if (ret != HKS_SUCCESS) {
114             LOGE("[FATAL]HUKS init param set failed. error=%{public}d", ret);
115             break;
116         }
117 
118         ret = AddCommonGenParams(paramSet, keyId);
119         if (ret != HKS_SUCCESS) {
120             LOGE("[FATAL]HUKS add common params failed. error=%{public}d", ret);
121             break;
122         }
123 
124         if (needAuth) {
125             ret = AddAuthGenParams(paramSet);
126             if (ret != HKS_SUCCESS) {
127                 LOGE("[FATAL]HUKS add auth params failed. error=%{public}d", ret);
128                 break;
129             }
130         }
131 
132         if (requirePasswordSet) {
133             struct HksParam tempParam = { .tag = HKS_TAG_IS_DEVICE_PASSWORD_SET, .boolParam = true };
134             ret = HksAddParams(paramSet, &tempParam, 1); // 1: add one param to paramSet
135             if (ret != HKS_SUCCESS) {
136                 LOGE("[FATAL]HUKS add requirePasswordSet param failed. error=%{public}d", ret);
137                 break;
138             }
139         }
140 
141         ret = HksBuildParamSet(&paramSet);
142         if (ret != HKS_SUCCESS) {
143             LOGE("[FATAL]HUKS build param set failed. error=%{public}d", ret);
144             break;
145         }
146 
147         ret = HksGenerateKey(&keyId->alias, paramSet, NULL);
148         if (ret != HKS_SUCCESS) {
149             LOGE("[FATAL]HUKS generate key failed. error=%{public}d", ret);
150         }
151     } while (0);
152 
153     HksFreeParamSet(&paramSet);
154     return HuksErrorTransfer(ret);
155 }
156 
DeleteKey(const struct KeyId * keyId)157 int32_t DeleteKey(const struct KeyId *keyId)
158 {
159     struct HksParam params[] = {
160         { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = AccessibilityToHksAuthStorageLevel(keyId->accessibility) },
161         { .tag = HKS_TAG_SPECIFIC_USER_ID, .int32Param = keyId->userId },
162     };
163     struct HksParamSet *paramSet = NULL;
164     int32_t ret = BuildParamSet(&paramSet, params, ARRAY_SIZE(params));
165     if (ret != HKS_SUCCESS) {
166         return HuksErrorTransfer(ret);
167     }
168 
169     ret = HksDeleteKey(&keyId->alias, paramSet);
170     HksFreeParamSet(&paramSet);
171     return HuksErrorTransfer(ret);
172 }
173 
IsKeyExist(const struct KeyId * keyId)174 int32_t IsKeyExist(const struct KeyId *keyId)
175 {
176     struct HksParam params[] = {
177         { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = AccessibilityToHksAuthStorageLevel(keyId->accessibility) },
178         { .tag = HKS_TAG_SPECIFIC_USER_ID, .int32Param = keyId->userId },
179     };
180     struct HksParamSet *paramSet = NULL;
181     int32_t ret = BuildParamSet(&paramSet, params, ARRAY_SIZE(params));
182     if (ret != HKS_SUCCESS) {
183         return HuksErrorTransfer(ret);
184     }
185 
186     ret = HksKeyExist(&keyId->alias, paramSet);
187     HksFreeParamSet(&paramSet);
188     return HuksErrorTransfer(ret);
189 }
190 
EncryptData(const struct KeyId * keyId,const struct HksBlob * aad,const struct HksBlob * inData,struct HksBlob * outData)191 int32_t EncryptData(const struct KeyId *keyId, const struct HksBlob *aad, const struct HksBlob *inData,
192     struct HksBlob *outData)
193 {
194     struct HksParam encryptParams[] = {
195         { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES },
196         { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT },
197         { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 },
198         { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE },
199         { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM },
200         { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = *aad },
201         { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = AccessibilityToHksAuthStorageLevel(keyId->accessibility) },
202         { .tag = HKS_TAG_SPECIFIC_USER_ID, .int32Param = keyId->userId },
203     };
204     struct HksParamSet *encryptParamSet = NULL;
205     int32_t ret = BuildParamSet(&encryptParamSet, encryptParams, ARRAY_SIZE(encryptParams));
206     if (ret != HKS_SUCCESS) {
207         return HuksErrorTransfer(ret);
208     }
209 
210     uint8_t handle[sizeof(uint64_t)] = { 0 };
211     struct HksBlob handleBlob = { sizeof(uint64_t), handle };
212     ret = HksInit(&keyId->alias, encryptParamSet, &handleBlob, NULL);
213     if (ret != HKS_SUCCESS) {
214         LOGE("[FATAL]HUKS encrypt init failed. error=%{public}d", ret);
215         HksFreeParamSet(&encryptParamSet);
216         return HuksErrorTransfer(ret);
217     }
218 
219     ret = HksFinish(&handleBlob, encryptParamSet, inData, outData);
220     HksFreeParamSet(&encryptParamSet);
221     if (ret != HKS_SUCCESS) {
222         LOGE("[FATAL]HUKS encrypt finish failed. error=%{public}d", ret);
223     }
224     return HuksErrorTransfer(ret);
225 }
226 
DecryptData(const struct KeyId * keyId,const struct HksBlob * aad,const struct HksBlob * inData,struct HksBlob * outData)227 int32_t DecryptData(const struct KeyId *keyId, const struct HksBlob *aad, const struct HksBlob *inData,
228     struct HksBlob *outData)
229 {
230     struct HksBlob cipher = { inData->size - NONCE_SIZE - TAG_SIZE, inData->data };
231     struct HksBlob tag = { TAG_SIZE, inData->data + (inData->size - NONCE_SIZE - TAG_SIZE) };
232     struct HksBlob nonce = { NONCE_SIZE, inData->data + (inData->size - NONCE_SIZE) };
233 
234     struct HksParamSet *decryptParamSet = NULL;
235     struct HksParam decryptParams[] = {
236         { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES },
237         { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_DECRYPT },
238         { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 },
239         { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE },
240         { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM },
241         { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = *aad },
242         { .tag = HKS_TAG_NONCE, .blob = nonce },
243         { .tag = HKS_TAG_AE_TAG, .blob = tag },
244         { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = AccessibilityToHksAuthStorageLevel(keyId->accessibility) },
245         { .tag = HKS_TAG_SPECIFIC_USER_ID, .int32Param = keyId->userId },
246     };
247 
248     int32_t ret = BuildParamSet(&decryptParamSet, decryptParams, ARRAY_SIZE(decryptParams));
249     if (ret != HKS_SUCCESS) {
250         return HuksErrorTransfer(ret);
251     }
252 
253     uint8_t handle[sizeof(uint64_t)] = { 0 };
254     struct HksBlob handleBlob = { sizeof(uint64_t), handle };
255     ret = HksInit(&keyId->alias, decryptParamSet, &handleBlob, NULL);
256     if (ret != HKS_SUCCESS) {
257         LOGE("[FATAL]HUKS decrypt init failed. error=%{public}d", ret);
258         HksFreeParamSet(&decryptParamSet);
259         return HuksErrorTransfer(ret);
260     }
261 
262     ret = HksFinish(&handleBlob, decryptParamSet, &cipher, outData);
263     HksFreeParamSet(&decryptParamSet);
264     if (ret != HKS_SUCCESS) {
265         LOGE("[FATAL]HUKS decrypt finish failed. error=%{public}d", ret);
266     }
267     return HuksErrorTransfer(ret);
268 }
269 
InitKey(const struct KeyId * keyId,uint32_t validTime,struct HksBlob * challenge,struct HksBlob * handle)270 int32_t InitKey(const struct KeyId *keyId, uint32_t validTime, struct HksBlob *challenge, struct HksBlob *handle)
271 {
272     struct HksParam initParams[] = {
273         { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES},
274         { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_DECRYPT },
275         { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 },
276         { .tag = HKS_TAG_IS_BATCH_OPERATION, .boolParam = true },
277         { .tag = HKS_TAG_BATCH_OPERATION_TIMEOUT, .uint32Param = validTime },
278         { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = AccessibilityToHksAuthStorageLevel(keyId->accessibility) },
279         { .tag = HKS_TAG_SPECIFIC_USER_ID, .int32Param = keyId->userId },
280     };
281     struct HksParamSet *paramSet = NULL;
282     int32_t ret = BuildParamSet(&paramSet, initParams, ARRAY_SIZE(initParams));
283     if (ret != HKS_SUCCESS) {
284         return HuksErrorTransfer(ret);
285     }
286 
287     ret = HksInit(&keyId->alias, paramSet, handle, challenge);
288     HksFreeParamSet(&paramSet);
289     if (ret != HKS_SUCCESS) {
290         LOGE("[FATAL]HUKS batch decrypt init failed. error=%{public}d", ret);
291     }
292     return HuksErrorTransfer(ret);
293 }
294 
ExecCrypt(const struct HksBlob * handle,const struct HksBlob * aad,const struct HksBlob * authToken,const struct HksBlob * inData,struct HksBlob * outData)295 int32_t ExecCrypt(const struct HksBlob *handle, const struct HksBlob *aad, const struct HksBlob *authToken,
296     const struct HksBlob *inData, struct HksBlob *outData)
297 {
298     struct HksBlob tag = { TAG_SIZE, inData->data + (inData->size - NONCE_SIZE - TAG_SIZE) };
299     struct HksBlob nonce = { NONCE_SIZE, inData->data + (inData->size - NONCE_SIZE) };
300 
301     struct HksParam updateParams[] = {
302         { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES },
303         { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_DECRYPT },
304         { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 },
305         { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE },
306         { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM },
307         { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = { .size = aad->size, .data = aad->data } },
308         { .tag = HKS_TAG_NONCE, .blob = nonce },
309         { .tag = HKS_TAG_AE_TAG, .blob = tag },
310         { .tag = HKS_TAG_AUTH_TOKEN, .blob = *authToken },
311     };
312 
313     struct HksParamSet *paramSet = NULL;
314     int32_t ret = BuildParamSet(&paramSet, updateParams, ARRAY_SIZE(updateParams));
315     if (ret != HKS_SUCCESS) {
316         return HuksErrorTransfer(ret);
317     }
318 
319     struct HksBlob cipher = { inData->size - NONCE_SIZE - TAG_SIZE, inData->data };
320     ret = HksUpdate(handle, paramSet, &cipher, outData);
321     HksFreeParamSet(&paramSet);
322     if (ret != HKS_SUCCESS) {
323         LOGE("[FATAL]HUKS batch decrypt update failed. error=%{public}d", ret);
324     }
325     return HuksErrorTransfer(ret);
326 }
327 
Drop(const struct HksBlob * handle)328 int32_t Drop(const struct HksBlob *handle)
329 {
330     struct HksBlob inData = { 0, NULL };
331     struct HksBlob outData = { 0, NULL };
332 
333     struct HksParamSet *paramSet = NULL;
334     int32_t ret = BuildParamSet(&paramSet, NULL, 0);
335     if (ret != HKS_SUCCESS) {
336         return HuksErrorTransfer(ret);
337     }
338 
339     ret = HksFinish(handle, paramSet, &inData, &outData);
340     HksFreeParamSet(&paramSet);
341     if (ret != HKS_SUCCESS) {
342         LOGE("[FATAL]HUKS batch decrypt finish failed. error=%{public}d", ret);
343     }
344     return HuksErrorTransfer(ret);
345 }