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