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