1 /*
2 * Copyright (C) 2022-2024 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 "user_sign_centre.h"
17
18 #include "securec.h"
19
20 #include "adaptor_algorithm.h"
21 #include "adaptor_log.h"
22 #include "adaptor_time.h"
23 #include "token_key.h"
24
25 #define AES_GCM_TOKEN_AAD "OH_authToken"
26 #define AES_GCM_TOKEN_AAD_SIZE 12
27
28 #ifdef IAM_TEST_ENABLE
29 #define IAM_STATIC
30 #else
31 #define IAM_STATIC static
32 #endif
33
IsTimeValid(const UserAuthTokenHal * userAuthToken,uint64_t allowableDuration)34 IAM_STATIC bool IsTimeValid(const UserAuthTokenHal *userAuthToken, uint64_t allowableDuration)
35 {
36 uint64_t currentTime = GetSystemTime();
37 if (currentTime < userAuthToken->tokenDataPlain.time) {
38 return false;
39 }
40 if (currentTime - userAuthToken->tokenDataPlain.time > allowableDuration) {
41 return false;
42 }
43 return true;
44 }
45
UserAuthTokenHmac(UserAuthTokenHal * userAuthToken,HksAuthTokenKey * tokenKey)46 IAM_STATIC ResultCode UserAuthTokenHmac(UserAuthTokenHal *userAuthToken, HksAuthTokenKey *tokenKey)
47 {
48 Buffer *sign = NULL;
49
50 const Buffer data = GetTmpBuffer((uint8_t *)userAuthToken, AUTH_TOKEN_DATA_LEN, AUTH_TOKEN_DATA_LEN);
51 const Buffer key = GetTmpBuffer(tokenKey->macKey, sizeof(tokenKey->macKey), sizeof(tokenKey->macKey));
52 ResultCode ret = HmacSha256(&key, &data, &sign);
53 if (ret != RESULT_SUCCESS) {
54 LOG_ERROR("HmacSha256 failed");
55 goto EXIT;
56 }
57 if (!CheckBufferWithSize(sign, SHA256_DIGEST_SIZE)) {
58 LOG_ERROR("CheckBufferWithSize failed");
59 ret = RESULT_GENERAL_ERROR;
60 goto EXIT;
61 }
62 if (memcpy_s(userAuthToken->sign, SHA256_DIGEST_SIZE, sign->buf, sign->contentSize) != EOK) {
63 LOG_ERROR("sign copy failed");
64 ret = RESULT_BAD_COPY;
65 goto EXIT;
66 }
67
68 EXIT:
69 DestoryBuffer(sign);
70 return ret;
71 }
72
DeinitAesGcmParam(AesGcmParam * aesGcmParam)73 IAM_STATIC void DeinitAesGcmParam(AesGcmParam *aesGcmParam)
74 {
75 DestoryBuffer(aesGcmParam->aad);
76 DestoryBuffer(aesGcmParam->iv);
77 DestoryBuffer(aesGcmParam->key);
78 (void)memset_s(aesGcmParam, sizeof(AesGcmParam), 0, sizeof(AesGcmParam));
79 }
80
DecryptTokenCipher(const UserAuthTokenHal * userAuthToken,UserAuthTokenPlainHal * tokenPlain,HksAuthTokenKey * tokenKey)81 IAM_STATIC ResultCode DecryptTokenCipher(const UserAuthTokenHal *userAuthToken, UserAuthTokenPlainHal *tokenPlain,
82 HksAuthTokenKey *tokenKey)
83 {
84 AesGcmParam aesGcmParam = {
85 .key = CreateBufferByData(tokenKey->cipherKey, sizeof(tokenKey->cipherKey)),
86 .iv = CreateBufferByData(userAuthToken->iv, sizeof(userAuthToken->iv)),
87 .aad = CreateBufferByData((uint8_t *)AES_GCM_TOKEN_AAD, AES_GCM_TOKEN_AAD_SIZE),
88 };
89 Buffer *plaintext = NULL;
90 int ret = RESULT_GENERAL_ERROR;
91 if (!IsBufferValid(aesGcmParam.key) || !IsBufferValid(aesGcmParam.iv) || !IsBufferValid(aesGcmParam.aad)) {
92 LOG_ERROR("get buffer failed");
93 goto EXIT;
94 }
95 const Buffer tag = GetTmpBuffer((uint8_t *)userAuthToken->tag, sizeof(userAuthToken->tag),
96 sizeof(userAuthToken->tag));
97 const Buffer ciphertext = GetTmpBuffer((uint8_t *)userAuthToken->tokenDataCipher,
98 sizeof(userAuthToken->tokenDataCipher), sizeof(userAuthToken->tokenDataCipher));
99 ret = AesGcmDecrypt(&ciphertext, &aesGcmParam, &tag, &plaintext);
100 if (ret != RESULT_SUCCESS) {
101 LOG_ERROR("AesGcmDecrypt failed");
102 goto EXIT;
103 }
104 if (!CheckBufferWithSize(plaintext, sizeof(tokenPlain->tokenDataToEncrypt))) {
105 LOG_ERROR("CheckBufferWithSize failed");
106 ret = RESULT_GENERAL_ERROR;
107 goto EXIT;
108 }
109 if (memcpy_s(&(tokenPlain->tokenDataToEncrypt), sizeof(tokenPlain->tokenDataToEncrypt),
110 plaintext->buf, plaintext->contentSize) != EOK) {
111 LOG_ERROR("copy TokenDataToEncrypt failed");
112 ret = RESULT_GENERAL_ERROR;
113 goto EXIT;
114 }
115
116 EXIT:
117 DestoryBuffer(plaintext);
118 DeinitAesGcmParam(&aesGcmParam);
119 return ret;
120 }
121
CheckUserAuthTokenHmac(const UserAuthTokenHal * userAuthToken,HksAuthTokenKey * tokenKey)122 IAM_STATIC ResultCode CheckUserAuthTokenHmac(const UserAuthTokenHal *userAuthToken, HksAuthTokenKey *tokenKey)
123 {
124 Buffer *rightSign = NULL;
125 const Buffer data = GetTmpBuffer((uint8_t *)userAuthToken, AUTH_TOKEN_DATA_LEN, AUTH_TOKEN_DATA_LEN);
126 const Buffer key = GetTmpBuffer(tokenKey->macKey, sizeof(tokenKey->macKey), sizeof(tokenKey->macKey));
127 ResultCode ret = HmacSha256(&key, &data, &rightSign);
128 if (ret != RESULT_SUCCESS) {
129 LOG_ERROR("HmacSha256 failed");
130 goto EXIT;
131 }
132 const Buffer sign = GetTmpBuffer((uint8_t *)userAuthToken->sign, SHA256_DIGEST_SIZE, SHA256_DIGEST_SIZE);
133 if (!CompareBuffer(rightSign, &sign)) {
134 LOG_ERROR("sign compare failed");
135 ret = RESULT_BAD_SIGN;
136 }
137
138 EXIT:
139 DestoryBuffer(rightSign);
140 return ret;
141 }
142
UserAuthTokenVerifyInner(const UserAuthTokenHal * userAuthToken,UserAuthTokenPlainHal * tokenPlain)143 IAM_STATIC ResultCode UserAuthTokenVerifyInner(const UserAuthTokenHal *userAuthToken, UserAuthTokenPlainHal *tokenPlain)
144 {
145 HksAuthTokenKey tokenKey = {};
146 ResultCode ret = GetTokenKey(&tokenKey);
147 if (ret != RESULT_SUCCESS) {
148 LOG_ERROR("GetTokenKey fail");
149 (void)memset_s(&tokenKey, sizeof(HksAuthTokenKey), 0, sizeof(HksAuthTokenKey));
150 return ret;
151 }
152 ret = CheckUserAuthTokenHmac(userAuthToken, &tokenKey);
153 if (ret != RESULT_SUCCESS) {
154 LOG_ERROR("UserAuthTokenVerify fail");
155 (void)memset_s(&tokenKey, sizeof(HksAuthTokenKey), 0, sizeof(HksAuthTokenKey));
156 return ret;
157 }
158 tokenPlain->tokenDataPlain = userAuthToken->tokenDataPlain;
159 ret = DecryptTokenCipher(userAuthToken, tokenPlain, &tokenKey);
160 if (ret != RESULT_SUCCESS) {
161 LOG_ERROR("DecryptTokenCipher fail");
162 }
163 (void)memset_s(&tokenKey, sizeof(HksAuthTokenKey), 0, sizeof(HksAuthTokenKey));
164 return ret;
165 }
166
UserAuthTokenVerify(const UserAuthTokenHal * userAuthToken,uint64_t allowableDuration,UserAuthTokenPlainHal * tokenPlain)167 ResultCode UserAuthTokenVerify(const UserAuthTokenHal *userAuthToken, uint64_t allowableDuration,
168 UserAuthTokenPlainHal *tokenPlain)
169 {
170 if (userAuthToken == NULL || tokenPlain == NULL) {
171 LOG_ERROR("userAuthToken is null");
172 return RESULT_BAD_PARAM;
173 }
174 if (!IsTimeValid(userAuthToken, allowableDuration)) {
175 LOG_ERROR("token timeout");
176 return RESULT_TOKEN_TIMEOUT;
177 }
178 if (UserAuthTokenVerifyInner(userAuthToken, tokenPlain) != RESULT_SUCCESS) {
179 LOG_ERROR("UserAuthTokenVerifyInner failed");
180 return RESULT_VERIFY_TOKEN_FAIL;
181 }
182 return RESULT_SUCCESS;
183 }
184
InitAesGcmParam(AesGcmParam * aesGcmParam,const HksAuthTokenKey * tokenKey)185 IAM_STATIC ResultCode InitAesGcmParam(AesGcmParam *aesGcmParam, const HksAuthTokenKey *tokenKey)
186 {
187 int32_t ret = RESULT_GENERAL_ERROR;
188 aesGcmParam->key = CreateBufferByData(tokenKey->cipherKey, sizeof(tokenKey->cipherKey));
189 aesGcmParam->iv = CreateBufferBySize(AES_GCM_IV_SIZE);
190 aesGcmParam->aad = CreateBufferByData((uint8_t *)AES_GCM_TOKEN_AAD, AES_GCM_TOKEN_AAD_SIZE);
191 if (!IsBufferValid(aesGcmParam->key) || !IsBufferValid(aesGcmParam->iv) || !IsBufferValid(aesGcmParam->aad)) {
192 LOG_ERROR("get secure uid failed");
193 goto EXIT;
194 }
195 ret = SecureRandom(aesGcmParam->iv->buf, aesGcmParam->iv->maxSize);
196 if (ret != RESULT_SUCCESS) {
197 LOG_ERROR("SecureRandom failed");
198 goto EXIT;
199 }
200 aesGcmParam->iv->contentSize = aesGcmParam->iv->maxSize;
201 return ret;
202 EXIT:
203 DeinitAesGcmParam(aesGcmParam);
204 return ret;
205 }
206
CopyTokenCipherParam(const Buffer * ciphertext,const Buffer * tag,const Buffer * iv,UserAuthTokenHal * authToken)207 IAM_STATIC ResultCode CopyTokenCipherParam(const Buffer *ciphertext, const Buffer *tag, const Buffer *iv,
208 UserAuthTokenHal *authToken)
209 {
210 if (!CheckBufferWithSize(ciphertext, sizeof(authToken->tokenDataCipher))) {
211 LOG_ERROR("bad ciphertext size");
212 return RESULT_GENERAL_ERROR;
213 }
214 if (memcpy_s(authToken->tokenDataCipher, sizeof(authToken->tokenDataCipher),
215 ciphertext->buf, ciphertext->contentSize) != EOK) {
216 LOG_ERROR("copy ciphertext failed");
217 return RESULT_GENERAL_ERROR;
218 }
219 if (!CheckBufferWithSize(tag, sizeof(authToken->tag))) {
220 LOG_ERROR("bad tag size");
221 return RESULT_GENERAL_ERROR;
222 }
223 if (memcpy_s(authToken->tag, sizeof(authToken->tag), tag->buf, tag->contentSize) != EOK) {
224 LOG_ERROR("copy tag failed");
225 return RESULT_GENERAL_ERROR;
226 }
227 if (!CheckBufferWithSize(iv, sizeof(authToken->iv))) {
228 LOG_ERROR("bad iv size");
229 return RESULT_GENERAL_ERROR;
230 }
231 if (memcpy_s(authToken->iv, sizeof(authToken->iv), iv->buf, iv->contentSize) != EOK) {
232 LOG_ERROR("copy iv failed");
233 return RESULT_GENERAL_ERROR;
234 }
235 return RESULT_SUCCESS;
236 }
237
GetTokenDataCipherResult(const TokenDataToEncrypt * data,UserAuthTokenHal * authToken,const HksAuthTokenKey * tokenKey)238 IAM_STATIC ResultCode GetTokenDataCipherResult(const TokenDataToEncrypt *data, UserAuthTokenHal *authToken,
239 const HksAuthTokenKey *tokenKey)
240 {
241 AesGcmParam aesGcmParam = {0};
242 Buffer *ciphertext = NULL;
243 Buffer *tag = NULL;
244 ResultCode ret = InitAesGcmParam(&aesGcmParam, tokenKey);
245 if (ret != RESULT_SUCCESS) {
246 LOG_ERROR("InitAesGcmParam failed");
247 goto EXIT;
248 }
249 const Buffer plaintext = GetTmpBuffer((uint8_t *)data, sizeof(TokenDataToEncrypt), sizeof(TokenDataToEncrypt));
250 ret = AesGcmEncrypt(&plaintext, &aesGcmParam, &ciphertext, &tag);
251 if (ret != RESULT_SUCCESS) {
252 LOG_ERROR("AesGcmEncrypt failed");
253 goto EXIT;
254 }
255 ret = CopyTokenCipherParam(ciphertext, tag, aesGcmParam.iv, authToken);
256 if (ret != RESULT_SUCCESS) {
257 LOG_ERROR("CopyTokenCipherParam failed");
258 goto EXIT;
259 }
260
261 EXIT:
262 DestoryBuffer(tag);
263 DestoryBuffer(ciphertext);
264 DeinitAesGcmParam(&aesGcmParam);
265 return ret;
266 }
267
UserAuthTokenSign(UserAuthTokenPlainHal * tokenPlain,UserAuthTokenHal * authToken)268 ResultCode UserAuthTokenSign(UserAuthTokenPlainHal *tokenPlain, UserAuthTokenHal *authToken)
269 {
270 if (tokenPlain == NULL || authToken == NULL) {
271 LOG_ERROR("bad param");
272 return RESULT_BAD_PARAM;
273 }
274
275 (void)memset_s(authToken, sizeof(UserAuthTokenHal), 0, sizeof(UserAuthTokenHal));
276 HksAuthTokenKey tokenKey = {};
277 ResultCode ret = GetTokenKey(&tokenKey);
278 if (ret != RESULT_SUCCESS) {
279 LOG_ERROR("GetTokenKey fail");
280 goto FAIL;
281 }
282
283 authToken->version = TOKEN_VERSION;
284 authToken->tokenDataPlain = tokenPlain->tokenDataPlain;
285 authToken->tokenDataPlain.time = GetSystemTime();
286 LOG_INFO("signed token type %{public}u", authToken->tokenDataPlain.tokenType);
287
288 ret = GetTokenDataCipherResult(&(tokenPlain->tokenDataToEncrypt), authToken, &tokenKey);
289 if (ret != RESULT_SUCCESS) {
290 LOG_ERROR("GetTokenDataCipherResult failed");
291 goto FAIL;
292 }
293
294 ret = UserAuthTokenHmac(authToken, &tokenKey);
295 if (ret != RESULT_SUCCESS) {
296 LOG_ERROR("UserAuthTokenHmac fail");
297 goto FAIL;
298 }
299 (void)memset_s(&tokenKey, sizeof(HksAuthTokenKey), 0, sizeof(HksAuthTokenKey));
300 return RESULT_SUCCESS;
301
302 FAIL:
303 (void)memset_s(&tokenKey, sizeof(HksAuthTokenKey), 0, sizeof(HksAuthTokenKey));
304 (void)memset_s(authToken, sizeof(UserAuthTokenHal), 0, sizeof(UserAuthTokenHal));
305 return ret;
306 }
307
ReuseUnlockTokenSign(UserAuthTokenHal * reuseToken)308 ResultCode ReuseUnlockTokenSign(UserAuthTokenHal *reuseToken)
309 {
310 if (reuseToken == NULL) {
311 LOG_ERROR("reuseToken is null");
312 return RESULT_BAD_PARAM;
313 }
314 HksAuthTokenKey tokenKey = {};
315 ResultCode ret = GetTokenKey(&tokenKey);
316 if (ret != RESULT_SUCCESS) {
317 LOG_ERROR("GetTokenKey fail");
318 goto FAIL;
319 }
320 ret = UserAuthTokenHmac(reuseToken, &tokenKey);
321 if (ret != RESULT_SUCCESS) {
322 LOG_ERROR("ReuseUnlockTokenSign fail");
323 goto FAIL;
324 }
325 (void)memset_s(&tokenKey, sizeof(HksAuthTokenKey), 0, sizeof(HksAuthTokenKey));
326 return RESULT_SUCCESS;
327
328 FAIL:
329 (void)memset_s(&tokenKey, sizeof(HksAuthTokenKey), 0, sizeof(HksAuthTokenKey));
330 (void)memset_s(reuseToken, sizeof(UserAuthTokenHal), 0, sizeof(UserAuthTokenHal));
331 return ret;
332 }