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:%" LOG_PUB "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:%" LOG_PUB "d", res);
69 goto ERR;
70 }
71
72 LOGI("AuthCode alias(HEX): %" LOG_PUB "x%" LOG_PUB "x%" LOG_PUB "x%" LOG_PUB "x****.", keyAliasVal[DEV_AUTH_ZERO],
73 keyAliasVal[DEV_AUTH_ONE], 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: %" LOG_PUB "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:%" LOG_PUB "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: %" LOG_PUB "d", realTask->taskBase.taskStatus);
135 return HC_ERR_BAD_MESSAGE;
136 }
137 if (realTask->taskBase.taskStatus > TASK_TYPE_BEGIN) {
138 LOGI("Message is repeated, ignore it, status: %" LOG_PUB "d.", realTask->taskBase.taskStatus);
139 *status = IGNORE_MSG;
140 return HC_SUCCESS;
141 }
142 int32_t message = 0;
143 int res;
144 res = GetIntFromJson(in, FIELD_MESSAGE, &message);
145 if (res != 0 || message != ISO_SERVER_BIND_EXCHANGE_RET) {
146 return HC_ERR_BAD_MESSAGE;
147 }
148 res = DecAndImportAuthCode(realTask, params, in);
149 if (res != 0) {
150 LOGE("dec and import authCode failed, res:%" LOG_PUB "d", res);
151 return res;
152 }
153 res = GenEncResult(params, ISO_CLIENT_BIND_EXCHANGE_CONFIRM, out, RESULT_AAD, false);
154 if (res == HC_SUCCESS) {
155 realTask->taskBase.taskStatus = TASK_TYPE_FINAL;
156 *status = FINISH;
157 }
158 return res;
159 }
160
ClientBindAesEncrypt(IsoClientBindExchangeTask * task,const IsoParams * params,uint8_t ** encData,uint8_t ** nonce)161 static int ClientBindAesEncrypt(IsoClientBindExchangeTask *task, const IsoParams *params,
162 uint8_t **encData, uint8_t **nonce)
163 {
164 Uint8Buff challengeBuf = { task->challenge, sizeof(task->challenge) };
165 int res = params->baseParams.loader->generateRandom(&challengeBuf);
166 if (res != 0) {
167 LOGE("generate random failed, res:%" LOG_PUB "d", res);
168 return res;
169 }
170 *nonce = (uint8_t *)HcMalloc(NONCE_SIZE, 0);
171 if (*nonce == NULL) {
172 LOGE("malloc nonce failed");
173 return HC_ERR_ALLOC_MEMORY;
174 }
175 Uint8Buff nonceBuf = { *nonce, NONCE_SIZE };
176 res = params->baseParams.loader->generateRandom(&nonceBuf);
177 if (res != 0) {
178 LOGE("generateRandom failed, res:%" LOG_PUB "d", res);
179 return res;
180 }
181 *encData = (uint8_t *)HcMalloc(sizeof(task->challenge) + TAG_LEN, 0);
182 if (*encData == NULL) {
183 return HC_ERR_ALLOC_MEMORY;
184 }
185 GcmParam gcmParams;
186 gcmParams.aad = (uint8_t *)EXCHANGE_AAD;
187 gcmParams.aadLen = (uint32_t)HcStrlen(EXCHANGE_AAD);
188 gcmParams.nonce = *nonce;
189 gcmParams.nonceLen = NONCE_SIZE;
190 Uint8Buff outBuf = { *encData, sizeof(task->challenge) + TAG_LEN };
191 KeyParams keyParams = {
192 { params->baseParams.sessionKey.val, params->baseParams.sessionKey.length, false },
193 false,
194 params->baseParams.osAccountId
195 };
196 res = params->baseParams.loader->aesGcmEncrypt(&keyParams, &challengeBuf, &gcmParams, &outBuf);
197 if (res != 0) {
198 LOGE("encrypt failed, res:%" LOG_PUB "d", res);
199 return res;
200 }
201 return res;
202 }
203
ClientBindExchangeStart(const IsoParams * params,IsoClientBindExchangeTask * task,CJson * out,int32_t * status)204 static int ClientBindExchangeStart(const IsoParams *params, IsoClientBindExchangeTask *task, CJson *out,
205 int32_t *status)
206 {
207 uint8_t *nonce = NULL;
208 uint8_t *encData = NULL;
209 CJson *payload = NULL;
210 CJson *sendToPeer = NULL;
211
212 // execute
213 int res = ClientBindAesEncrypt(task, params, &encData, &nonce);
214 if (res != 0) {
215 goto ERR;
216 }
217
218 // package message
219 sendToPeer = CreateJson();
220 if (sendToPeer == NULL) {
221 res = HC_ERR_ALLOC_MEMORY;
222 goto ERR;
223 }
224 payload = CreateJson();
225 if (payload == NULL) {
226 res = HC_ERR_ALLOC_MEMORY;
227 goto ERR;
228 }
229 GOTO_ERR_AND_SET_RET(AddIntToJson(sendToPeer, FIELD_MESSAGE, ISO_CLIENT_BIND_EXCHANGE_CMD), res);
230 GOTO_ERR_AND_SET_RET(AddByteToJson(payload, FIELD_NONCE, nonce, NONCE_SIZE), res);
231 GOTO_ERR_AND_SET_RET(AddByteToJson(payload, FIELD_ENC_DATA, encData, sizeof(task->challenge) + TAG_LEN), res);
232 GOTO_ERR_AND_SET_RET(AddObjToJson(sendToPeer, FIELD_PAYLOAD, payload), res);
233 GOTO_ERR_AND_SET_RET(AddObjToJson(out, FIELD_SEND_TO_PEER, sendToPeer), res);
234
235 task->taskBase.taskStatus = TASK_TYPE_BEGIN;
236 *status = CONTINUE;
237 ERR:
238 FreeJson(payload);
239 FreeJson(sendToPeer);
240 HcFree(nonce);
241 HcFree(encData);
242 return res;
243 }
244
CreateClientBindExchangeTask(IsoParams * params,const CJson * in,CJson * out,int32_t * status)245 SymBaseCurTask *CreateClientBindExchangeTask(IsoParams *params, const CJson *in, CJson *out, int32_t *status)
246 {
247 (void)in;
248 IsoClientBindExchangeTask *task = (IsoClientBindExchangeTask *)HcMalloc(sizeof(IsoClientBindExchangeTask), 0);
249 if (task == NULL) {
250 LOGE("Failed to malloc client bind exchange task.");
251 return NULL;
252 }
253 task->taskBase.destroyTask = DestroyCreateClientBindExchangeTask;
254 task->taskBase.process = Process;
255 task->taskBase.getCurTaskType = GetTaskType;
256 int res = ClientBindExchangeStart(params, task, out, status);
257 if (res != 0) {
258 DestroyCreateClientBindExchangeTask((struct SymBaseCurTaskT *)task);
259 return NULL;
260 }
261 return (SymBaseCurTask *)task;
262 }
263