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