1 /*
2 * Copyright (C) 2022 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_auth_task_common.h"
17 #include "clib_error.h"
18 #include "common_defs.h"
19 #include "device_auth.h"
20 #include "device_auth_defines.h"
21 #include "hc_log.h"
22 #include "hc_types.h"
23 #include "iso_auth_client_task.h"
24 #include "iso_auth_server_task.h"
25 #include "protocol_common.h"
26 #include "sym_token_manager.h"
27
28 #define KEY_INFO_PERSISTENT_TOKEN "persistent_token"
29 #define AUTH_TOKEN_SIZE_BYTE 32
30
IsIsoAuthTaskSupported(void)31 bool IsIsoAuthTaskSupported(void)
32 {
33 return true;
34 }
35
CreateIsoAuthTask(const CJson * in,CJson * out,const AccountVersionInfo * verInfo)36 TaskBase *CreateIsoAuthTask(const CJson *in, CJson *out, const AccountVersionInfo *verInfo)
37 {
38 bool isClient = false;
39 if (GetBoolFromJson(in, FIELD_IS_CLIENT, &isClient) != CLIB_SUCCESS) {
40 LOGD("Get isClient from json failed."); /* default: server. */
41 }
42 return isClient ? CreateIsoAuthClientTask(in, out, verInfo) :
43 CreateIsoAuthServerTask(in, out, verInfo);
44 }
45
FillUserId(const CJson * in,IsoAuthParams * params)46 static int32_t FillUserId(const CJson *in, IsoAuthParams *params)
47 {
48 params->userIdSelf = (char *)HcMalloc(DEV_AUTH_USER_ID_SIZE, 0);
49 if (params->userIdSelf == NULL) {
50 LOGE("Failed to malloc for userIdSelf.");
51 return HC_ERR_ALLOC_MEMORY;
52 }
53 params->userIdPeer = (char *)HcMalloc(DEV_AUTH_USER_ID_SIZE, 0);
54 if (params->userIdPeer == NULL) {
55 LOGE("Failed to malloc for userIdPeer.");
56 return HC_ERR_ALLOC_MEMORY;
57 }
58 const char *userIdSelf = GetStringFromJson(in, FIELD_SELF_USER_ID);
59 if (userIdSelf == NULL) {
60 LOGE("Failed to get self userId from input data in sym auth.");
61 return HC_ERR_JSON_GET;
62 }
63
64 if (strcpy_s(params->userIdSelf, DEV_AUTH_USER_ID_SIZE, userIdSelf) != EOK) {
65 LOGE("Copy for userIdSelf failed in sym auth.");
66 return HC_ERR_MEMORY_COPY;
67 }
68 return HC_SUCCESS;
69 }
70
FillPayload(const CJson * in,IsoAuthParams * params)71 static int32_t FillPayload(const CJson *in, IsoAuthParams *params)
72 {
73 int32_t res = InitSingleParam(¶ms->devIdSelf, DEV_AUTH_DEVICE_ID_SIZE);
74 if (res != HC_SUCCESS) {
75 LOGE("InitSingleParam for devIdSelf failed, res: %d.", res);
76 return res;
77 }
78 const char *devIdSelf = GetStringFromJson(in, FIELD_SELF_DEV_ID);
79 if (devIdSelf == NULL) {
80 LOGE("Failed to get devIdSelf in sym auth.");
81 return HC_ERR_JSON_GET;
82 }
83 uint32_t devIdLen = HcStrlen(devIdSelf);
84 if (memcpy_s(params->devIdSelf.val, params->devIdSelf.length, devIdSelf, devIdLen + 1) != EOK) {
85 LOGE("Copy for self devId failed in sym auth.");
86 return HC_ERR_MEMORY_COPY;
87 }
88 params->devIdSelf.length = devIdLen;
89 const char *selfDeviceId = GetStringFromJson(in, FIELD_SELF_DEVICE_ID);
90 if (selfDeviceId == NULL) {
91 LOGE("Failed to get self deviceId from input data in sym auth.");
92 return HC_ERR_JSON_GET;
93 }
94 uint32_t selfDeviceIdLen = HcStrlen(selfDeviceId);
95 params->deviceIdSelf = (char *)HcMalloc(selfDeviceIdLen + 1, 0);
96 if (params->deviceIdSelf == NULL) {
97 LOGE("Failed to malloc for selfDeviceId.");
98 return HC_ERR_ALLOC_MEMORY;
99 }
100 if (memcpy_s(params->deviceIdSelf, selfDeviceIdLen + 1, selfDeviceId, selfDeviceIdLen) != EOK) {
101 LOGE("Copy for deviceIdSelf failed in sym auth.");
102 return HC_ERR_MEMORY_COPY;
103 }
104 params->isoBaseParams.authIdSelf.length = params->devIdSelf.length + HcStrlen(params->deviceIdSelf);
105 res = InitSingleParam(¶ms->isoBaseParams.authIdSelf, params->isoBaseParams.authIdSelf.length);
106 if (res != HC_SUCCESS) {
107 LOGE("InitSingleParam for authIdSelf failed, res: %d.", res);
108 return res;
109 }
110 if (memcpy_s(params->isoBaseParams.authIdSelf.val, params->isoBaseParams.authIdSelf.length,
111 params->devIdSelf.val, params->devIdSelf.length) != EOK) {
112 LOGE("Failed to memcpy devIdSelf for authId in sym auth.");
113 return HC_ERR_MEMORY_COPY;
114 }
115 if (memcpy_s(params->isoBaseParams.authIdSelf.val + params->devIdSelf.length,
116 params->isoBaseParams.authIdSelf.length - params->devIdSelf.length,
117 params->deviceIdSelf, selfDeviceIdLen) != EOK) {
118 LOGE("Failed to memcpy deviceIdSelf for authId in sym auth.");
119 return HC_ERR_MEMORY_COPY;
120 }
121 return HC_SUCCESS;
122 }
123
SetChallenge(IsoAuthParams * params,const CJson * in)124 static int32_t SetChallenge(IsoAuthParams *params, const CJson *in)
125 {
126 if (((uint32_t)params->credentialType & SYMMETRIC_CRED) == SYMMETRIC_CRED) {
127 params->challenge.length = HcStrlen(KEY_INFO_PERSISTENT_TOKEN);
128 params->challenge.val = (uint8_t *)HcMalloc(params->challenge.length, 0);
129 if (params->challenge.val == NULL) {
130 LOGE("Failed to malloc for challenge.");
131 return HC_ERR_ALLOC_MEMORY;
132 }
133 if (memcpy_s(params->challenge.val, params->challenge.length, KEY_INFO_PERSISTENT_TOKEN,
134 HcStrlen(KEY_INFO_PERSISTENT_TOKEN)) != EOK) {
135 LOGE("Copy for challenge failed in sym auth.");
136 return HC_ERR_MEMORY_COPY;
137 }
138 return HC_SUCCESS;
139 }
140 LOGE("Invalid credentialType: %d", params->credentialType);
141 return HC_ERR_INVALID_PARAMS;
142 }
143
GenerateAuthTokenForAccessory(const IsoAuthParams * params,Uint8Buff * outKey)144 static int32_t GenerateAuthTokenForAccessory(const IsoAuthParams *params, Uint8Buff *outKey)
145 {
146 uint8_t keyAliasVal[SHA256_LEN] = { 0 };
147 Uint8Buff keyAlias = { keyAliasVal, SHA256_LEN };
148 int32_t res = GetSymTokenManager()->generateKeyAlias(params->userIdSelf, (const char *)(params->devIdSelf.val),
149 &keyAlias);
150 if (res != HC_SUCCESS) {
151 LOGE("Failed to generate key alias for authCode!");
152 return res;
153 }
154 res = InitSingleParam(outKey, AUTH_TOKEN_SIZE_BYTE);
155 if (res != HC_SUCCESS) {
156 LOGE("Malloc for authToken failed, res: %d.", res);
157 return res;
158 }
159 Uint8Buff userIdSelfBuff = {
160 .val = (uint8_t *)(params->userIdSelf),
161 .length = HcStrlen(params->userIdSelf)
162 };
163 res = params->isoBaseParams.loader->computeHkdf(&keyAlias, &userIdSelfBuff, ¶ms->challenge, outKey, true);
164 if (res != HC_SUCCESS) {
165 LOGE("Failed to computeHkdf from authCode to authToken.");
166 FreeAndCleanKey(outKey);
167 }
168 return res;
169 }
170
GenerateTokenAliasForController(const IsoAuthParams * params,Uint8Buff * authTokenAlias)171 static int32_t GenerateTokenAliasForController(const IsoAuthParams *params, Uint8Buff *authTokenAlias)
172 {
173 int32_t res = InitSingleParam(authTokenAlias, SHA256_LEN);
174 if (res != HC_SUCCESS) {
175 LOGE("Malloc for authToken alias failed, res: %d.", res);
176 return res;
177 }
178 res = GetSymTokenManager()->generateKeyAlias(params->userIdPeer, (const char *)(params->devIdPeer.val),
179 authTokenAlias);
180 if (res != HC_SUCCESS) {
181 LOGE("Failed to generate key alias for authToken.");
182 HcFree(authTokenAlias->val);
183 authTokenAlias->val = NULL;
184 }
185 return res;
186 }
187
AccountAuthGeneratePsk(IsoAuthParams * params)188 int32_t AccountAuthGeneratePsk(IsoAuthParams *params)
189 {
190 bool isTokenStored = true;
191 Uint8Buff authToken = { NULL, 0 };
192 int32_t res;
193 if (params->localDevType == DEVICE_TYPE_ACCESSORY) {
194 LOGI("Account sym auth for accessory.");
195 isTokenStored = false;
196 res = GenerateAuthTokenForAccessory(params, &authToken);
197 } else {
198 LOGI("Account sym auth for controller.");
199 res = GenerateTokenAliasForController(params, &authToken);
200 }
201 if (res != HC_SUCCESS) {
202 LOGE("Failed to generate token-related info, res = %d.", res);
203 return res;
204 }
205 Uint8Buff pskBuf = { params->isoBaseParams.psk, PSK_SIZE };
206 Uint8Buff seedBuf = { params->seed, sizeof(params->seed) };
207 res = params->isoBaseParams.loader->computeHmac(&authToken, &seedBuf, &pskBuf, isTokenStored);
208 FreeAndCleanKey(&authToken);
209 if (res != HC_SUCCESS) {
210 LOGE("ComputeHmac for psk failed, res: %d.", res);
211 }
212 return res;
213 }
214
InitIsoAuthParams(const CJson * in,IsoAuthParams * params,const AccountVersionInfo * verInfo)215 int32_t InitIsoAuthParams(const CJson *in, IsoAuthParams *params, const AccountVersionInfo *verInfo)
216 {
217 params->versionNo = verInfo->versionNo;
218 int32_t res = HC_ERR_JSON_GET;
219 if (GetIntFromJson(in, FIELD_AUTH_FORM, ¶ms->authForm) != CLIB_SUCCESS) {
220 LOGE("Failed to get authForm from json in sym auth.");
221 goto CLEAN_UP;
222 }
223 if (GetIntFromJson(in, FIELD_CREDENTIAL_TYPE, ¶ms->credentialType) != CLIB_SUCCESS) {
224 LOGE("Failed to get credentialType from json in sym auth.");
225 goto CLEAN_UP;
226 }
227 if (GetIntFromJson(in, FIELD_LOCAL_DEVICE_TYPE, ¶ms->localDevType) != CLIB_SUCCESS) {
228 LOGE("Failed to get localDevType from json in sym auth.");
229 goto CLEAN_UP;
230 }
231 res = InitIsoBaseParams(¶ms->isoBaseParams);
232 if (res != HC_SUCCESS) {
233 LOGE("InitIsoBaseParams failed, res: %x.", res);
234 goto CLEAN_UP;
235 }
236 res = FillUserId(in, params);
237 if (res != HC_SUCCESS) {
238 LOGE("Failed to fill userId info, res = %d.", res);
239 goto CLEAN_UP;
240 }
241 res = FillPayload(in, params);
242 if (res != HC_SUCCESS) {
243 LOGE("Failed to fill payload info, res = %d.", res);
244 goto CLEAN_UP;
245 }
246 if (params->localDevType == DEVICE_TYPE_ACCESSORY) {
247 res = SetChallenge(params, in);
248 if (res != HC_SUCCESS) {
249 LOGE("SetChallenge failed, res = %d.", res);
250 goto CLEAN_UP;
251 }
252 }
253 return HC_SUCCESS;
254 CLEAN_UP:
255 DestroyIsoAuthParams(params);
256 return res;
257 }
258
DestroyIsoAuthParams(IsoAuthParams * params)259 void DestroyIsoAuthParams(IsoAuthParams *params)
260 {
261 LOGI("Destroy iso auth params begin.");
262 if (params == NULL) {
263 return;
264 }
265 DestroyIsoBaseParams(¶ms->isoBaseParams);
266
267 HcFree(params->challenge.val);
268 params->challenge.val = NULL;
269
270 HcFree(params->userIdSelf);
271 params->userIdSelf = NULL;
272
273 HcFree(params->userIdPeer);
274 params->userIdPeer = NULL;
275
276 HcFree(params->devIdSelf.val);
277 params->devIdSelf.val = NULL;
278
279 HcFree(params->devIdPeer.val);
280 params->devIdPeer.val = NULL;
281
282 HcFree(params->deviceIdSelf);
283 params->deviceIdSelf = NULL;
284
285 HcFree(params->deviceIdPeer);
286 params->deviceIdPeer = NULL;
287 }
288
GetPayloadValue(IsoAuthParams * params,const CJson * in)289 static int32_t GetPayloadValue(IsoAuthParams *params, const CJson *in)
290 {
291 const char *devIdPeerHex = GetStringFromJson(in, FIELD_DEV_ID);
292 if (devIdPeerHex == NULL) {
293 LOGE("Get peer devId hex failed.");
294 return HC_ERR_JSON_GET;
295 }
296 uint32_t devIdPeerHexLen = HcStrlen(devIdPeerHex);
297 // DevId is string, the id from phone is byte. For both cases, apply one more bit for '\0'.
298 params->devIdPeer.val = (uint8_t *)HcMalloc(devIdPeerHexLen / BYTE_TO_HEX_OPER_LENGTH + 1, 0);
299 if (params->devIdPeer.val == NULL) {
300 LOGE("Failed to malloc for peer devId.");
301 return HC_ERR_ALLOC_MEMORY;
302 }
303 params->devIdPeer.length = devIdPeerHexLen / BYTE_TO_HEX_OPER_LENGTH;
304 if (HexStringToByte(devIdPeerHex, params->devIdPeer.val, params->devIdPeer.length) != CLIB_SUCCESS) {
305 LOGE("Failed to convert peer devId.");
306 return HC_ERR_CONVERT_FAILED;
307 }
308 const char *deviceIdPeer = GetStringFromJson(in, FIELD_DEVICE_ID);
309 if (deviceIdPeer == NULL) {
310 LOGE("Get peer deviceId failed.");
311 return HC_ERR_JSON_GET;
312 }
313 uint32_t deviceIdPeerLen = HcStrlen(deviceIdPeer);
314 params->deviceIdPeer = (char *)HcMalloc(deviceIdPeerLen + 1, 0);
315 if (params->deviceIdPeer == NULL) {
316 LOGE("Failed to malloc for peer deviceId.");
317 return HC_ERR_ALLOC_MEMORY;
318 }
319 if (memcpy_s(params->deviceIdPeer, deviceIdPeerLen + 1, deviceIdPeer, deviceIdPeerLen) != EOK) {
320 LOGE("Failed to copy peer deviceId.");
321 return HC_ERR_MEMORY_COPY;
322 }
323 return HC_SUCCESS;
324 }
325
ExtractPeerAuthId(IsoAuthParams * params,const CJson * in)326 static int32_t ExtractPeerAuthId(IsoAuthParams *params, const CJson *in)
327 {
328 const char *payloadHex = GetStringFromJson(in, FIELD_PAYLOAD);
329 if (payloadHex == NULL) {
330 LOGE("Get payloadHex peer from json failed.");
331 return HC_ERR_JSON_GET;
332 }
333 int32_t res = InitSingleParam(&(params->isoBaseParams.authIdPeer), HcStrlen(payloadHex) / BYTE_TO_HEX_OPER_LENGTH);
334 if (res != HC_SUCCESS) {
335 LOGE("InitSingleParam for payload peer failed, res: %d.", res);
336 return res;
337 }
338 if (HexStringToByte(payloadHex, params->isoBaseParams.authIdPeer.val,
339 params->isoBaseParams.authIdPeer.length) != CLIB_SUCCESS) {
340 LOGE("Convert payloadPeer from hex string to byte failed.");
341 return HC_ERR_CONVERT_FAILED;
342 }
343 return HC_SUCCESS;
344 }
345
ExtractAndVerifyPayload(IsoAuthParams * params,const CJson * in)346 int32_t ExtractAndVerifyPayload(IsoAuthParams *params, const CJson *in)
347 {
348 int32_t res = ExtractPeerAuthId(params, in);
349 if (res != HC_SUCCESS) {
350 LOGE("ExtractPeerAuthId failed, res: %d.", res);
351 return res;
352 }
353 res = GetPayloadValue(params, in);
354 if (res != HC_SUCCESS) {
355 LOGE("GetPayloadValue failed, res: %d.", res);
356 return res;
357 }
358 uint32_t deviceIdPeerLen = HcStrlen(params->deviceIdPeer);
359 uint32_t len = params->devIdPeer.length + deviceIdPeerLen;
360 char *combineString = (char *)HcMalloc(len, 0);
361 if (combineString == NULL) {
362 LOGE("Failed to malloc for combineString.");
363 return HC_ERR_ALLOC_MEMORY;
364 }
365 if (memcpy_s(combineString, len, params->devIdPeer.val, params->devIdPeer.length) != EOK) {
366 LOGE("Failed to copy peer devId.");
367 HcFree(combineString);
368 return HC_ERR_MEMORY_COPY;
369 }
370 if (memcpy_s(combineString + params->devIdPeer.length, len - params->devIdPeer.length, params->deviceIdPeer,
371 deviceIdPeerLen) != EOK) {
372 LOGE("Failed to copy peer deviceId.");
373 HcFree(combineString);
374 return HC_ERR_MEMORY_COPY;
375 }
376 if (memcmp(combineString, params->isoBaseParams.authIdPeer.val, len) != 0) {
377 LOGE("Payload is not equal.");
378 HcFree(combineString);
379 return HC_ERR_MEMORY_COMPARE;
380 }
381 HcFree(combineString);
382 return HC_SUCCESS;
383 }
384
AuthIsoSendFinalToOut(IsoAuthParams * params,CJson * out)385 int32_t AuthIsoSendFinalToOut(IsoAuthParams *params, CJson *out)
386 {
387 CJson *sendToSelf = CreateJson();
388 if (sendToSelf == NULL) {
389 LOGE("Create sendToSelf json failed.");
390 return HC_ERR_JSON_CREATE;
391 }
392 if (AddByteToJson(sendToSelf, FIELD_SESSION_KEY,
393 params->isoBaseParams.sessionKey.val, params->isoBaseParams.sessionKey.length) != CLIB_SUCCESS) {
394 LOGE("Add sessionKey to json failed.");
395 goto CLEAN_UP;
396 }
397 if (AddStringToJson(sendToSelf, FIELD_USER_ID, params->userIdPeer) != CLIB_SUCCESS) {
398 LOGE("Add userIdPeer to json failed.");
399 goto CLEAN_UP;
400 }
401 if (AddStringToJson(sendToSelf, FIELD_DEVICE_ID, params->deviceIdPeer) != CLIB_SUCCESS) {
402 LOGE("Add deviceIdPeer to json failed.");
403 goto CLEAN_UP;
404 }
405 if (AddIntToJson(sendToSelf, FIELD_CREDENTIAL_TYPE, params->credentialType) != CLIB_SUCCESS) {
406 LOGE("Add credentialType to json failed.");
407 goto CLEAN_UP;
408 }
409 if (AddStringToJson(sendToSelf, FIELD_DEV_ID, (char *)params->devIdPeer.val) != CLIB_SUCCESS) {
410 LOGE("Add devIdPeer to json failed.");
411 goto CLEAN_UP;
412 }
413 if (AddObjToJson(out, FIELD_SEND_TO_SELF, sendToSelf) != CLIB_SUCCESS) {
414 LOGE("Add sendToSelf to json failed.");
415 goto CLEAN_UP;
416 }
417 FreeJson(sendToSelf);
418 FreeAndCleanKey(&(params->isoBaseParams.sessionKey));
419 return HC_SUCCESS;
420 CLEAN_UP:
421 FreeJson(sendToSelf);
422 FreeAndCleanKey(&(params->isoBaseParams.sessionKey));
423 return HC_ERR_JSON_ADD;
424 }
425