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