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