1 /*
2  * Copyright (C) 2021 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 "iso_client_bind_exchange_task.h"
17 #include "alg_defs.h"
18 #include "das_task_common.h"
19 #include "das_module_defines.h"
20 #include "hc_log.h"
21 #include "hc_types.h"
22 #include "iso_protocol_common.h"
23 #include "iso_task_common.h"
24 #include "securec.h"
25 
26 enum {
27     TASK_TYPE_BEGIN = 1,
28     TASK_TYPE_FINAL,
29 };
30 
GetTaskType(void)31 static CurTaskType GetTaskType(void)
32 {
33     return TASK_TYPE_BIND_LITE_EXCHANGE;
34 }
35 
DestroyCreateClientBindExchangeTask(struct SymBaseCurTaskT * task)36 static void DestroyCreateClientBindExchangeTask(struct SymBaseCurTaskT *task)
37 {
38     HcFree(task);
39 }
40 
DecAndImportInner(IsoClientBindExchangeTask * realTask,const IsoParams * params,const Uint8Buff * nonceBuf,const Uint8Buff * encDataBuf,Uint8Buff * authCodeBuf)41 static int DecAndImportInner(IsoClientBindExchangeTask *realTask, const IsoParams *params,
42     const Uint8Buff *nonceBuf, const Uint8Buff *encDataBuf, Uint8Buff *authCodeBuf)
43 {
44     int res;
45     uint8_t *keyAliasVal = (uint8_t *)HcMalloc(ISO_KEY_ALIAS_LEN, 0);
46     if (keyAliasVal == NULL) {
47         res = HC_ERR_ALLOC_MEMORY;
48         goto ERR;
49     }
50     Uint8Buff keyAlias = { keyAliasVal, ISO_KEY_ALIAS_LEN };
51     GcmParam gcmParam;
52     gcmParam.aad = realTask->challenge;
53     gcmParam.aadLen = sizeof(realTask->challenge);
54     gcmParam.nonce = nonceBuf->val;
55     gcmParam.nonceLen = nonceBuf->length;
56     KeyParams keyParams = {
57         { params->baseParams.sessionKey.val, params->baseParams.sessionKey.length, false },
58         false,
59         params->baseParams.osAccountId
60     };
61     res = params->baseParams.loader->aesGcmDecrypt(&keyParams, encDataBuf, &gcmParam, authCodeBuf);
62     if (res != 0) {
63         LOGE("gcm decrypt failed, res:%d", res);
64         goto ERR;
65     }
66     res = GenerateKeyAliasInIso(params, keyAliasVal, ISO_KEY_ALIAS_LEN, true);
67     if (res != 0) {
68         LOGE("GenerateKeyAliasInIso failed, res:%d", res);
69         goto ERR;
70     }
71 
72     LOGI("AuthCode alias(HEX): %x%x%x%x****.", keyAliasVal[DEV_AUTH_ZERO], keyAliasVal[DEV_AUTH_ONE],
73         keyAliasVal[DEV_AUTH_TWO], keyAliasVal[DEV_AUTH_THREE]);
74     ExtraInfo exInfo = { { params->baseParams.authIdPeer.val, params->baseParams.authIdPeer.length },
75         params->peerUserType, PAIR_TYPE_BIND };
76     KeyParams keyAliasParams = { { keyAlias.val, keyAlias.length, true }, false, params->baseParams.osAccountId };
77     res = params->baseParams.loader->importSymmetricKey(&keyAliasParams, authCodeBuf, KEY_PURPOSE_MAC, &exInfo);
78     if (res != 0) {
79         LOGE("ImportSymmetricKey failed, res: %x.", res);
80         goto ERR;
81     }
82 ERR:
83     HcFree(keyAliasVal);
84     return res;
85 }
86 
DecAndImportAuthCode(IsoClientBindExchangeTask * realTask,const IsoParams * params,const CJson * in)87 static int DecAndImportAuthCode(IsoClientBindExchangeTask *realTask, const IsoParams *params, const CJson *in)
88 {
89     uint8_t *nonce = NULL;
90     uint8_t *encData = NULL;
91     uint8_t *authCode = NULL;
92     int encDataLen = AUTH_CODE_LEN + TAG_LEN;
93     int res;
94     nonce = (uint8_t *)HcMalloc(NONCE_SIZE, 0);
95     if (nonce == NULL) {
96         res = HC_ERR_ALLOC_MEMORY;
97         goto ERR;
98     }
99     encData = (uint8_t *)HcMalloc(encDataLen, 0);
100     if (encData == NULL) {
101         res = HC_ERR_ALLOC_MEMORY;
102         goto ERR;
103     }
104     GOTO_ERR_AND_SET_RET(GetByteFromJson(in, FIELD_NONCE, nonce, NONCE_SIZE), res);
105     GOTO_ERR_AND_SET_RET(GetByteFromJson(in, FIELD_ENC_AUTH_TOKEN, encData, encDataLen), res);
106 
107     Uint8Buff encDataBuf = { encData, encDataLen };
108     authCode = (uint8_t *)HcMalloc(AUTH_CODE_LEN, 0);
109     if (authCode == NULL) {
110         res = HC_ERR_ALLOC_MEMORY;
111         goto ERR;
112     }
113     Uint8Buff authCodeBuf = { authCode, AUTH_CODE_LEN };
114     Uint8Buff nonceBuf = { nonce, NONCE_SIZE };
115 
116     res = DecAndImportInner(realTask, params, &nonceBuf, &encDataBuf, &authCodeBuf);
117     if (res != 0) {
118         LOGE("DecAndImportInner failed, res:%d", res);
119     }
120 ERR:
121     HcFree(nonce);
122     HcFree(encData);
123     if (authCode != NULL) {
124         (void)memset_s(authCode, AUTH_CODE_LEN, 0, AUTH_CODE_LEN);
125     }
126     HcFree(authCode);
127     return res;
128 }
129 
Process(struct SymBaseCurTaskT * task,IsoParams * params,const CJson * in,CJson * out,int32_t * status)130 static int Process(struct SymBaseCurTaskT *task, IsoParams *params, const CJson *in, CJson *out, int32_t *status)
131 {
132     IsoClientBindExchangeTask *realTask = (IsoClientBindExchangeTask *)task;
133     if (realTask->taskBase.taskStatus < TASK_TYPE_BEGIN) {
134         LOGE("Invalid taskStatus: %d", realTask->taskBase.taskStatus);
135         return HC_ERR_BAD_MESSAGE;
136     }
137 
138     if (realTask->taskBase.taskStatus > TASK_TYPE_BEGIN) {
139         LOGI("The message is repeated, ignore it, status: %d", realTask->taskBase.taskStatus);
140         *status = IGNORE_MSG;
141         return HC_SUCCESS;
142     }
143     int res;
144     int32_t message = 0;
145     res = GetIntFromJson(in, FIELD_MESSAGE, &message);
146     if (res != 0 || message != ISO_SERVER_BIND_EXCHANGE_RET) {
147         return HC_ERR_BAD_MESSAGE;
148     }
149     res = DecAndImportAuthCode(realTask, params, in);
150     if (res != 0) {
151         LOGE("dec and import authCode failed, res:%d", res);
152         return res;
153     }
154     res = GenEncResult(params, ISO_CLIENT_BIND_EXCHANGE_CONFIRM, out, RESULT_AAD, false);
155     if (res == HC_SUCCESS) {
156         realTask->taskBase.taskStatus = TASK_TYPE_FINAL;
157         *status = FINISH;
158     }
159     return res;
160 }
161 
ClientBindAesEncrypt(IsoClientBindExchangeTask * task,const IsoParams * params,uint8_t ** encData,uint8_t ** nonce)162 static int ClientBindAesEncrypt(IsoClientBindExchangeTask *task, const IsoParams *params,
163     uint8_t **encData, uint8_t **nonce)
164 {
165     Uint8Buff challengeBuf = { task->challenge, sizeof(task->challenge) };
166     int res = params->baseParams.loader->generateRandom(&challengeBuf);
167     if (res != 0) {
168         LOGE("generate random failed, res:%d", res);
169         return res;
170     }
171     *nonce = (uint8_t *)HcMalloc(NONCE_SIZE, 0);
172     if (*nonce == NULL) {
173         LOGE("malloc nonce failed");
174         return HC_ERR_ALLOC_MEMORY;
175     }
176     Uint8Buff nonceBuf = { *nonce, NONCE_SIZE };
177     res = params->baseParams.loader->generateRandom(&nonceBuf);
178     if (res != 0) {
179         LOGE("generateRandom failed, res:%d", res);
180         return res;
181     }
182     *encData = (uint8_t *)HcMalloc(sizeof(task->challenge) + TAG_LEN, 0);
183     if (*encData == NULL) {
184         return HC_ERR_ALLOC_MEMORY;
185     }
186     GcmParam gcmParams;
187     gcmParams.aad = (uint8_t *)EXCHANGE_AAD;
188     gcmParams.aadLen = (uint32_t)HcStrlen(EXCHANGE_AAD);
189     gcmParams.nonce = *nonce;
190     gcmParams.nonceLen = NONCE_SIZE;
191     Uint8Buff outBuf = { *encData, sizeof(task->challenge) + TAG_LEN };
192     KeyParams keyParams = {
193         { params->baseParams.sessionKey.val, params->baseParams.sessionKey.length, false },
194         false,
195         params->baseParams.osAccountId
196     };
197     res = params->baseParams.loader->aesGcmEncrypt(&keyParams, &challengeBuf, &gcmParams, &outBuf);
198     if (res != 0) {
199         LOGE("encrypt failed, res:%d", res);
200         return res;
201     }
202     return res;
203 }
204 
ClientBindExchangeStart(const IsoParams * params,IsoClientBindExchangeTask * task,CJson * out,int32_t * status)205 static int ClientBindExchangeStart(const IsoParams *params, IsoClientBindExchangeTask *task, CJson *out,
206                                    int32_t *status)
207 {
208     uint8_t *nonce = NULL;
209     uint8_t *encData = NULL;
210     CJson *payload = NULL;
211     CJson *sendToPeer = NULL;
212 
213     // execute
214     int res = ClientBindAesEncrypt(task, params, &encData, &nonce);
215     if (res != 0) {
216         goto ERR;
217     }
218 
219     // package message
220     sendToPeer = CreateJson();
221     if (sendToPeer == NULL) {
222         res = HC_ERR_ALLOC_MEMORY;
223         goto ERR;
224     }
225     payload = CreateJson();
226     if (payload == NULL) {
227         res = HC_ERR_ALLOC_MEMORY;
228         goto ERR;
229     }
230     GOTO_ERR_AND_SET_RET(AddIntToJson(sendToPeer, FIELD_MESSAGE, ISO_CLIENT_BIND_EXCHANGE_CMD), res);
231     GOTO_ERR_AND_SET_RET(AddByteToJson(payload, FIELD_NONCE, nonce, NONCE_SIZE), res);
232     GOTO_ERR_AND_SET_RET(AddByteToJson(payload, FIELD_ENC_DATA, encData, sizeof(task->challenge) + TAG_LEN), res);
233     GOTO_ERR_AND_SET_RET(AddObjToJson(sendToPeer, FIELD_PAYLOAD, payload), res);
234     GOTO_ERR_AND_SET_RET(AddObjToJson(out, FIELD_SEND_TO_PEER, sendToPeer), res);
235 
236     task->taskBase.taskStatus = TASK_TYPE_BEGIN;
237     *status = CONTINUE;
238 ERR:
239     FreeJson(payload);
240     FreeJson(sendToPeer);
241     HcFree(nonce);
242     HcFree(encData);
243     return res;
244 }
245 
CreateClientBindExchangeTask(IsoParams * params,const CJson * in,CJson * out,int32_t * status)246 SymBaseCurTask *CreateClientBindExchangeTask(IsoParams *params, const CJson *in, CJson *out, int32_t *status)
247 {
248     (void)in;
249     IsoClientBindExchangeTask *task = (IsoClientBindExchangeTask *)HcMalloc(sizeof(IsoClientBindExchangeTask), 0);
250     if (task == NULL) {
251         LOGE("Failed to malloc client bind exchange task.");
252         return NULL;
253     }
254     task->taskBase.destroyTask = DestroyCreateClientBindExchangeTask;
255     task->taskBase.process = Process;
256     task->taskBase.getCurTaskType = GetTaskType;
257     int res = ClientBindExchangeStart(params, task, out, status);
258     if (res != 0) {
259         DestroyCreateClientBindExchangeTask((struct SymBaseCurTaskT *)task);
260         return NULL;
261     }
262     return (SymBaseCurTask *)task;
263 }
264