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