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