• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }