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