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)strlen(EXCHANGE_AAD);
99 gcmParam.nonce = nonce;
100 gcmParam.nonceLen = NONCE_SIZE;
101 Uint8Buff challengeBuf = { challenge, CHALLENGE_SIZE };
102 res = params->baseParams.loader->aesGcmDecrypt(¶ms->baseParams.sessionKey, &encDataBuf, &gcmParam, false,
103 &challengeBuf);
104 if (res != 0) {
105 LOGE("decrypt challenge failed, res:%d", res);
106 goto ERR;
107 }
108 ERR:
109 HcFree(encData);
110 HcFree(nonce);
111 return res;
112 }
113
GenAndEncAuthCode(const IsoParams * params,Uint8Buff * nonceBuf,const Uint8Buff * challengeBuf,Uint8Buff * encAuthCodeBuf)114 static int GenAndEncAuthCode(const IsoParams *params, Uint8Buff *nonceBuf, const Uint8Buff *challengeBuf,
115 Uint8Buff *encAuthCodeBuf)
116 {
117 int res;
118 uint8_t *keyAlias = NULL;
119 uint8_t *authCode = (uint8_t *)HcMalloc(AUTH_CODE_LEN, 0);
120 if (authCode == NULL) {
121 res = HC_ERR_ALLOC_MEMORY;
122 goto ERR;
123 }
124 Uint8Buff authCodeBuf = { authCode, AUTH_CODE_LEN };
125 res = params->baseParams.loader->generateRandom(&authCodeBuf);
126 if (res != 0) {
127 LOGE("generate auth code failed, res:%d", res);
128 goto ERR;
129 }
130
131 res = params->baseParams.loader->generateRandom(nonceBuf);
132 if (res != 0) {
133 LOGE("generate nonce failed, res:%d", res);
134 goto ERR;
135 }
136 GcmParam gcmParam = { nonceBuf->val, nonceBuf->length, challengeBuf->val, challengeBuf->length };
137 res = params->baseParams.loader->aesGcmEncrypt(¶ms->baseParams.sessionKey, &authCodeBuf, &gcmParam, false,
138 encAuthCodeBuf);
139 if (res != 0) {
140 LOGE("encrypt auth code failed, res:%d", res);
141 goto ERR;
142 }
143
144 keyAlias = (uint8_t *)HcMalloc(ISO_KEY_ALIAS_LEN, 0);
145 if (keyAlias == NULL) {
146 res = HC_ERR_ALLOC_MEMORY;
147 goto ERR;
148 }
149 res = GenerateKeyAliasInIso(params, keyAlias, ISO_KEY_ALIAS_LEN, true);
150 if (res != 0) {
151 LOGE("GenerateKeyAliasInIso failed, res:%d", res);
152 goto ERR;
153 }
154
155 LOGI("AuthCode alias: %x%x%x%x****.", keyAlias[0], keyAlias[1], keyAlias[2], keyAlias[3]);
156 Uint8Buff keyAliasBuf = { keyAlias, ISO_KEY_ALIAS_LEN };
157 ExtraInfo exInfo = { { params->baseParams.authIdPeer.val, params->baseParams.authIdPeer.length },
158 params->peerUserType, PAIR_TYPE_BIND };
159 res = params->baseParams.loader->importSymmetricKey(&keyAliasBuf, &authCodeBuf, KEY_PURPOSE_MAC, &exInfo);
160 if (res != 0) {
161 LOGE("ImportSymmetricKey failed, res: %x.", res);
162 goto ERR;
163 }
164 ERR:
165 HcFree(keyAlias);
166 FreeAndCleanKey(&authCodeBuf);
167 return res;
168 }
169
GenerateAuthCodeAndImport(const IsoParams * params,CJson * out,uint8_t * challenge,uint32_t challengeLen)170 static int GenerateAuthCodeAndImport(const IsoParams *params, CJson *out, uint8_t *challenge, uint32_t challengeLen)
171 {
172 int res;
173 uint8_t *nonce = NULL;
174 uint8_t *encAuthCode = NULL;
175 CJson *payload = NULL;
176 CJson *sendToPeer = NULL;
177
178 nonce = (uint8_t *)HcMalloc(NONCE_SIZE, 0);
179 if (nonce == NULL) {
180 res = HC_ERR_ALLOC_MEMORY;
181 goto ERR;
182 }
183 encAuthCode = (uint8_t *)HcMalloc(AUTH_CODE_LEN + TAG_LEN, 0);
184 if (encAuthCode == NULL) {
185 res = HC_ERR_ALLOC_MEMORY;
186 goto ERR;
187 }
188 Uint8Buff encAuthCodeBuf = { encAuthCode, AUTH_CODE_LEN + TAG_LEN };
189 Uint8Buff nonceBuf = { nonce, NONCE_SIZE };
190 Uint8Buff challengeBuf = { challenge, challengeLen };
191
192 res = GenAndEncAuthCode(params, &nonceBuf, &challengeBuf, &encAuthCodeBuf);
193 if (res != 0) {
194 LOGE("GenAndEncAuthCode failed, res:%d", res);
195 goto ERR;
196 }
197 payload = CreateJson();
198 if (payload == NULL) {
199 res = HC_ERR_ALLOC_MEMORY;
200 goto ERR;
201 }
202 sendToPeer = CreateJson();
203 if (sendToPeer == NULL) {
204 res = HC_ERR_ALLOC_MEMORY;
205 goto ERR;
206 }
207 GOTO_ERR_AND_SET_RET(AddIntToJson(sendToPeer, FIELD_MESSAGE, ISO_SERVER_BIND_EXCHANGE_RET), res);
208 GOTO_ERR_AND_SET_RET(AddByteToJson(payload, FIELD_ENC_AUTH_TOKEN, encAuthCodeBuf.val, encAuthCodeBuf.length), res);
209 GOTO_ERR_AND_SET_RET(AddByteToJson(payload, FIELD_NONCE, nonceBuf.val, nonceBuf.length), res);
210 GOTO_ERR_AND_SET_RET(AddObjToJson(sendToPeer, FIELD_PAYLOAD, payload), res);
211 GOTO_ERR_AND_SET_RET(AddObjToJson(out, FIELD_SEND_TO_PEER, sendToPeer), res);
212
213 ERR:
214 HcFree(nonce);
215 HcFree(encAuthCode);
216 FreeJson(payload);
217 FreeJson(sendToPeer);
218 return res;
219 }
220
ServerBindExchangeStart(const IsoParams * params,IsoServerBindExchangeTask * task,const CJson * in,CJson * out,int32_t * status)221 static int ServerBindExchangeStart(const IsoParams *params, IsoServerBindExchangeTask *task,
222 const CJson *in, CJson *out, int32_t *status)
223 {
224 int res;
225 uint8_t *challenge = (uint8_t *)HcMalloc(CHALLENGE_SIZE, 0);
226 if (challenge == NULL) {
227 res = HC_ERR_ALLOC_MEMORY;
228 goto ERR;
229 }
230 res = DecryptChallenge(params, in, challenge, CHALLENGE_SIZE);
231 if (res != 0) {
232 LOGE("decrypt challenge failed, res:%d", res);
233 goto ERR;
234 }
235 res = GenerateAuthCodeAndImport(params, out, challenge, CHALLENGE_SIZE);
236 if (res != 0) {
237 LOGE("GenerateAuthCodeAndImport failed, res:%d", res);
238 goto ERR;
239 }
240 task->taskBase.taskStatus = TASK_TYPE_BEGIN;
241 *status = CONTINUE;
242 ERR:
243 HcFree(challenge);
244 return res;
245 }
246
CreateServerBindExchangeTask(IsoParams * params,const CJson * in,CJson * out,int32_t * status)247 SymBaseCurTask *CreateServerBindExchangeTask(IsoParams *params, const CJson *in, CJson *out, int32_t *status)
248 {
249 IsoServerBindExchangeTask *task = (IsoServerBindExchangeTask *)HcMalloc(sizeof(IsoServerBindExchangeTask), 0);
250 if (task == NULL) {
251 return NULL;
252 }
253 task->taskBase.destroyTask = DestroyServerBindExchangeTask;
254 task->taskBase.process = Process;
255 task->taskBase.getCurTaskType = GetTaskType;
256 int res = ServerBindExchangeStart(params, task, in, out, status);
257 if (res != 0) {
258 DestroyServerBindExchangeTask((struct SymBaseCurTaskT *)task);
259 return NULL;
260 }
261 return (SymBaseCurTask *)task;
262 }
263