1 /*
2  * Copyright (c) 2021-2022 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 "hks_auth.h"
17 
18 #include <stddef.h>
19 
20 #include "hks_base_check.h"
21 #include "hks_log.h"
22 #include "hks_param.h"
23 #include "hks_template.h"
24 #include "hks_secure_access.h"
25 
26 struct HksAuthPolicy {
27     uint32_t authId;
28     uint32_t policyCnt;
29     uint32_t *policyTag;
30 };
31 
32 #ifndef _CUT_AUTHENTICATE_
33 static uint32_t g_symCipherPolicyTag[] = { HKS_TAG_ALGORITHM, HKS_TAG_BLOCK_MODE, HKS_TAG_PADDING, HKS_TAG_PURPOSE };
34 static uint32_t g_asymCipherPolicyTag[] = { HKS_TAG_ALGORITHM, HKS_TAG_DIGEST, HKS_TAG_PADDING, HKS_TAG_PURPOSE };
35 static uint32_t g_signVerifyRsaPolicyTag[] = { HKS_TAG_ALGORITHM, HKS_TAG_DIGEST, HKS_TAG_PADDING, HKS_TAG_PURPOSE };
36 static uint32_t g_signVerifyEccPolicyTag[] = { HKS_TAG_ALGORITHM, HKS_TAG_DIGEST, HKS_TAG_PURPOSE };
37 static uint32_t g_signVerifyEd25519PolicyTag[] = { HKS_TAG_PURPOSE };
38 static uint32_t g_macPolicyTag[] = { HKS_TAG_DIGEST, HKS_TAG_PURPOSE };
39 static uint32_t g_macSm3PolicyTag[] = { HKS_TAG_ALGORITHM, HKS_TAG_DIGEST, HKS_TAG_PURPOSE };
40 static uint32_t g_derivePolicyTag[] = { HKS_TAG_DIGEST, HKS_TAG_PURPOSE };
41 static uint32_t g_agreePolicyTag[] = { HKS_TAG_PURPOSE };
42 
43 struct HksAuthPolicy g_authPolicyList[] = {
44     { HKS_AUTH_ID_SYM_CIPHER, HKS_ARRAY_SIZE(g_symCipherPolicyTag), g_symCipherPolicyTag },
45     { HKS_AUTH_ID_ASYM_CIPHER, HKS_ARRAY_SIZE(g_asymCipherPolicyTag), g_asymCipherPolicyTag },
46     { HKS_AUTH_ID_SIGN_VERIFY_RSA, HKS_ARRAY_SIZE(g_signVerifyRsaPolicyTag), g_signVerifyRsaPolicyTag },
47     { HKS_AUTH_ID_SIGN_VERIFY_ECC, HKS_ARRAY_SIZE(g_signVerifyEccPolicyTag), g_signVerifyEccPolicyTag },
48     { HKS_AUTH_ID_SIGN_VERIFY_ED25519, HKS_ARRAY_SIZE(g_signVerifyEd25519PolicyTag), g_signVerifyEd25519PolicyTag },
49     { HKS_AUTH_ID_MAC_HMAC, HKS_ARRAY_SIZE(g_macPolicyTag), g_macPolicyTag },
50     { HKS_AUTH_ID_MAC_SM3, HKS_ARRAY_SIZE(g_macSm3PolicyTag), g_macSm3PolicyTag },
51     { HKS_AUTH_ID_DERIVE, HKS_ARRAY_SIZE(g_derivePolicyTag), g_derivePolicyTag },
52     { HKS_AUTH_ID_AGREE, HKS_ARRAY_SIZE(g_agreePolicyTag), g_agreePolicyTag }
53 };
54 
CheckPurpose(const struct HksParam * authParam,const struct HksParam * requestParam)55 static int32_t CheckPurpose(const struct HksParam *authParam, const struct HksParam *requestParam)
56 {
57     if (requestParam->uint32Param == 0) {
58         return HKS_ERROR_INVALID_ARGUMENT;
59     }
60     if ((requestParam->uint32Param & authParam->uint32Param) != requestParam->uint32Param) {
61         return HKS_ERROR_INVALID_ARGUMENT;
62     }
63     return HKS_SUCCESS;
64 }
65 
OptionalParamCheck(uint32_t authTag,uint32_t alg,uint32_t purpose,const struct HksParamSet * paramSet,const struct ParamsValues * paramValues)66 static int32_t OptionalParamCheck(uint32_t authTag, uint32_t alg, uint32_t purpose, const struct HksParamSet *paramSet,
67     const struct ParamsValues* paramValues)
68 {
69     HKS_LOG_I("tag is 0x%" LOG_PUBLIC "x", authTag);
70     struct HksParam *param = NULL;
71     bool isAbsent = false;
72     int32_t ret = HksGetParam(paramSet, authTag, &param);
73     if (ret == HKS_ERROR_INVALID_ARGUMENT) {
74         HKS_LOG_E("get auth param 0x%" LOG_PUBLIC "x failed!", authTag);
75         return ret;
76     }
77     if (ret == HKS_ERROR_PARAM_NOT_EXIST) {
78         HKS_LOG_D("when generates key, the tag is absent. tag is 0x%" LOG_PUBLIC "x", authTag);
79         isAbsent = true;
80     }
81 
82     ret = HksCheckOptionalParam(authTag, alg, purpose, isAbsent, param);
83     if (ret != HKS_SUCCESS) {
84         HKS_LOG_E("check optional param fail");
85         return ret;
86     }
87     if (((purpose & HKS_KEY_PURPOSE_DERIVE) != 0) || ((purpose & HKS_KEY_PURPOSE_MAC) != 0)) {
88         HKS_LOG_E("derive or mac no need to check");
89         return HKS_SUCCESS;
90     }
91     // Parameter check is more strict than above
92     return HksCheckGenKeyMutableParams(alg, paramValues);
93 }
94 
GetAlgAndPurposeParam(const struct HksParamSet * keyBlobParamSet,const struct HksParamSet * paramSet,struct HksParam ** algParam,struct HksParam ** purposeParam,struct ParamsValues * paramValues)95 static int32_t GetAlgAndPurposeParam(const struct HksParamSet *keyBlobParamSet, const struct HksParamSet *paramSet,
96     struct HksParam **algParam, struct HksParam **purposeParam, struct ParamsValues* paramValues)
97 {
98     int32_t ret = HksGetParam(keyBlobParamSet, HKS_TAG_ALGORITHM, algParam);
99     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, HKS_ERROR_CHECK_GET_ALG_FAIL,
100         "get param  0x%" LOG_PUBLIC "x failed!", HKS_TAG_ALGORITHM);
101     ret = HksGetParam(keyBlobParamSet, HKS_TAG_PURPOSE, purposeParam);
102     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, HKS_ERROR_CHECK_GET_PURPOSE_FAIL,
103         "get param  0x%" LOG_PUBLIC "x failed!", HKS_TAG_PURPOSE);
104     return GetInputParams(paramSet, paramValues);
105 }
106 
AuthPolicy(const struct HksAuthPolicy * policy,const struct HksParamSet * keyBlobParamSet,const struct HksParamSet * paramSet)107 static int32_t AuthPolicy(const struct HksAuthPolicy *policy, const struct HksParamSet *keyBlobParamSet,
108     const struct HksParamSet *paramSet)
109 {
110     uint32_t authTag;
111     struct HksParam *authParam = NULL;
112     struct HksParam *requestParam = NULL;
113     struct HksParam *algParam = NULL;
114     struct HksParam *purposeParam = NULL;
115     struct ParamsValues paramValues = { { false, 0, false }, { true, 0, false }, { true, 0, false },
116         { true, 0, false }, { true, 0, false } };
117     int32_t ret = GetAlgAndPurposeParam(keyBlobParamSet, paramSet, &algParam, &purposeParam, &paramValues);
118     if (ret != HKS_SUCCESS) {
119         HKS_LOG_E("GetAlgAndPurposeParam failed");
120         return ret;
121     }
122     for (uint32_t i = 0; i < policy->policyCnt; i++) {
123         authTag = policy->policyTag[i];
124         ret = HksGetParam(keyBlobParamSet, authTag, &authParam);
125         if (ret == HKS_ERROR_INVALID_ARGUMENT) {
126             HKS_LOG_E("get auth param 0x%" LOG_PUBLIC "x failed!", authTag);
127             return ret;
128         }
129         if (ret == HKS_ERROR_PARAM_NOT_EXIST) {
130             ret = OptionalParamCheck(authTag, algParam->uint32Param, purposeParam->uint32Param, paramSet, &paramValues);
131             if (ret != HKS_SUCCESS) {
132                 return ret;
133             }
134             continue;
135         }
136         ret = HksGetParam(paramSet, authTag, &requestParam);
137         if (ret != HKS_SUCCESS) {
138             HKS_LOG_E("get request param 0x%" LOG_PUBLIC "x failed!", authTag);
139             return ret;
140         }
141         if (authTag != HKS_TAG_PURPOSE) {
142             ret = HksCheckParamMatch((const struct HksParam *)authParam, (const struct HksParam *)requestParam);
143         } else {
144             ret = CheckPurpose((const struct HksParam *)authParam, (const struct HksParam *)requestParam);
145         }
146         if (ret != HKS_SUCCESS) {
147             HKS_LOG_E("unmatch policy 0x%" LOG_PUBLIC "x , 0x%" LOG_PUBLIC "x != 0x%" LOG_PUBLIC "x!", authTag,
148                 requestParam->uint32Param, authParam->uint32Param);
149             return ret;
150         }
151     }
152     return HKS_SUCCESS;
153 }
154 
HksAuth(uint32_t authId,const struct HksKeyNode * keyNode,const struct HksParamSet * paramSet)155 int32_t HksAuth(uint32_t authId, const struct HksKeyNode *keyNode, const struct HksParamSet *paramSet)
156 {
157     bool isSupportUserAuth = false;
158     int32_t ret = HksCheckKeybBlobIsSupportUserAuth(keyNode->paramSet, &isSupportUserAuth);
159     if (ret != HKS_SUCCESS) {
160         HKS_LOG_E("HksCheckKeybBlobIsSupportUserAuth failed");
161         return ret;
162     }
163 
164     if (isSupportUserAuth) {
165         HKS_LOG_E("key should do user auth, but one stage api do not support user auth operation");
166         return HKS_ERROR_NOT_SUPPORTED;
167     }
168 
169     for (uint32_t i = 0; i < HKS_ARRAY_SIZE(g_authPolicyList); i++) {
170         if (authId == g_authPolicyList[i].authId) {
171             return AuthPolicy(&g_authPolicyList[i], keyNode->paramSet, paramSet);
172         }
173     }
174     return HKS_ERROR_BAD_STATE;
175 }
176 
HksThreeStageAuth(uint32_t authId,const struct HuksKeyNode * keyNode)177 int32_t HksThreeStageAuth(uint32_t authId, const struct HuksKeyNode *keyNode)
178 {
179     for (uint32_t i = 0; i < HKS_ARRAY_SIZE(g_authPolicyList); i++) {
180         if (authId == g_authPolicyList[i].authId) {
181             return AuthPolicy(&g_authPolicyList[i], keyNode->keyBlobParamSet, keyNode->runtimeParamSet);
182         }
183     }
184     return HKS_ERROR_BAD_STATE;
185 }
186 #endif /* _CUT_AUTHENTICATE_ */
187