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