• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(&params->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(&params->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,const CJson * in)122 static int32_t SetChallenge(IsoAuthParams *params, const CJson *in)
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     res = params->isoBaseParams.loader->computeHkdf(&keyAlias, &userIdSelfBuff, &params->challenge, outKey, true);
162     if (res != HC_SUCCESS) {
163         LOGE("Failed to computeHkdf from authCode to authToken.");
164         FreeAndCleanKey(outKey);
165     }
166     return res;
167 }
168 
GenerateTokenAliasForController(const IsoAuthParams * params,Uint8Buff * authTokenAlias)169 static int32_t GenerateTokenAliasForController(const IsoAuthParams *params, Uint8Buff *authTokenAlias)
170 {
171     int32_t res = InitSingleParam(authTokenAlias, SHA256_LEN);
172     if (res != HC_SUCCESS) {
173         LOGE("Malloc for authToken alias failed, res: %d.", res);
174         return res;
175     }
176     res = GetSymTokenManager()->generateKeyAlias(params->userIdPeer, (const char *)(params->devIdPeer.val),
177         authTokenAlias);
178     if (res != HC_SUCCESS) {
179         LOGE("Failed to generate key alias for authToken.");
180         HcFree(authTokenAlias->val);
181         authTokenAlias->val = NULL;
182     }
183     return res;
184 }
185 
AccountAuthGeneratePsk(IsoAuthParams * params)186 int32_t AccountAuthGeneratePsk(IsoAuthParams *params)
187 {
188     bool isTokenStored = true;
189     Uint8Buff authToken = { NULL, 0 };
190     int32_t res;
191     if (params->localDevType == DEVICE_TYPE_ACCESSORY) {
192         LOGI("Account sym auth for accessory.");
193         isTokenStored = false;
194         res = GenerateAuthTokenForAccessory(params, &authToken);
195     } else {
196         LOGI("Account sym auth for controller.");
197         res = GenerateTokenAliasForController(params, &authToken);
198     }
199     if (res != HC_SUCCESS) {
200         LOGE("Failed to generate token-related info, res = %d.", res);
201         return res;
202     }
203     Uint8Buff pskBuf = { params->isoBaseParams.psk, PSK_SIZE };
204     Uint8Buff seedBuf = { params->seed, sizeof(params->seed) };
205     res = params->isoBaseParams.loader->computeHmac(&authToken, &seedBuf, &pskBuf, isTokenStored);
206     FreeAndCleanKey(&authToken);
207     if (res != HC_SUCCESS) {
208         LOGE("ComputeHmac for psk failed, res: %d.", res);
209     }
210     return res;
211 }
212 
InitIsoAuthParams(const CJson * in,IsoAuthParams * params,const AccountVersionInfo * verInfo)213 int32_t InitIsoAuthParams(const CJson *in, IsoAuthParams *params, const AccountVersionInfo *verInfo)
214 {
215     params->versionNo = verInfo->versionNo;
216     int32_t res = HC_ERR_JSON_GET;
217     if (GetIntFromJson(in, FIELD_AUTH_FORM, &params->authForm) != CLIB_SUCCESS) {
218         LOGE("Failed to get authForm from json in sym auth.");
219         goto CLEAN_UP;
220     }
221     if (GetIntFromJson(in, FIELD_CREDENTIAL_TYPE, &params->credentialType) != CLIB_SUCCESS) {
222         LOGE("Failed to get credentialType from json in sym auth.");
223         goto CLEAN_UP;
224     }
225     if (GetIntFromJson(in, FIELD_LOCAL_DEVICE_TYPE, &params->localDevType) != CLIB_SUCCESS) {
226         LOGE("Failed to get localDevType from json in sym auth.");
227         goto CLEAN_UP;
228     }
229     res = InitIsoBaseParams(&params->isoBaseParams);
230     if (res != HC_SUCCESS) {
231         LOGE("InitIsoBaseParams failed, res: %x.", res);
232         goto CLEAN_UP;
233     }
234     res = FillUserId(in, params);
235     if (res != HC_SUCCESS) {
236         LOGE("Failed to fill userId info, res = %d.", res);
237         goto CLEAN_UP;
238     }
239     res = FillPayload(in, params);
240     if (res != HC_SUCCESS) {
241         LOGE("Failed to fill payload info, res = %d.", res);
242         goto CLEAN_UP;
243     }
244     if (params->localDevType == DEVICE_TYPE_ACCESSORY) {
245         res = SetChallenge(params, in);
246         if (res != HC_SUCCESS) {
247             LOGE("SetChallenge failed, res = %d.", res);
248             goto CLEAN_UP;
249         }
250     }
251     return HC_SUCCESS;
252 CLEAN_UP:
253     DestroyIsoAuthParams(params);
254     return res;
255 }
256 
DestroyIsoAuthParams(IsoAuthParams * params)257 void DestroyIsoAuthParams(IsoAuthParams *params)
258 {
259     LOGI("Destroy iso auth params begin.");
260     if (params == NULL) {
261         return;
262     }
263     DestroyIsoBaseParams(&params->isoBaseParams);
264 
265     HcFree(params->challenge.val);
266     params->challenge.val = NULL;
267 
268     HcFree(params->userIdSelf);
269     params->userIdSelf = NULL;
270 
271     HcFree(params->userIdPeer);
272     params->userIdPeer = NULL;
273 
274     HcFree(params->devIdSelf.val);
275     params->devIdSelf.val = NULL;
276 
277     HcFree(params->devIdPeer.val);
278     params->devIdPeer.val = NULL;
279 
280     HcFree(params->deviceIdSelf);
281     params->deviceIdSelf = NULL;
282 
283     HcFree(params->deviceIdPeer);
284     params->deviceIdPeer = NULL;
285 }
286 
GetPayloadValue(IsoAuthParams * params,const CJson * in)287 static int32_t GetPayloadValue(IsoAuthParams *params, const CJson *in)
288 {
289     const char *devIdPeerHex = GetStringFromJson(in, FIELD_DEV_ID);
290     if (devIdPeerHex == NULL) {
291         LOGE("Get peer devId hex failed.");
292         return HC_ERR_JSON_GET;
293     }
294     uint32_t devIdPeerHexLen = HcStrlen(devIdPeerHex);
295     // DevId is string, the id from phone is byte. For both cases, apply one more bit for '\0'.
296     params->devIdPeer.val = (uint8_t *)HcMalloc(devIdPeerHexLen / BYTE_TO_HEX_OPER_LENGTH + 1, 0);
297     if (params->devIdPeer.val == NULL) {
298         LOGE("Failed to malloc for peer devId.");
299         return HC_ERR_ALLOC_MEMORY;
300     }
301     params->devIdPeer.length = devIdPeerHexLen / BYTE_TO_HEX_OPER_LENGTH;
302     if (HexStringToByte(devIdPeerHex, params->devIdPeer.val, params->devIdPeer.length) != CLIB_SUCCESS) {
303         LOGE("Failed to convert peer devId.");
304         return HC_ERR_CONVERT_FAILED;
305     }
306     const char *deviceIdPeer = GetStringFromJson(in, FIELD_DEVICE_ID);
307     if (deviceIdPeer == NULL) {
308         LOGE("Get peer deviceId failed.");
309         return HC_ERR_JSON_GET;
310     }
311     uint32_t deviceIdPeerLen = HcStrlen(deviceIdPeer);
312     params->deviceIdPeer = (char *)HcMalloc(deviceIdPeerLen + 1, 0);
313     if (params->deviceIdPeer == NULL) {
314         LOGE("Failed to malloc for peer deviceId.");
315         return HC_ERR_ALLOC_MEMORY;
316     }
317     if (memcpy_s(params->deviceIdPeer, deviceIdPeerLen + 1, deviceIdPeer, deviceIdPeerLen) != EOK) {
318         LOGE("Failed to copy peer deviceId.");
319         return HC_ERR_MEMORY_COPY;
320     }
321     return HC_SUCCESS;
322 }
323 
ExtractPeerAuthId(IsoAuthParams * params,const CJson * in)324 static int32_t ExtractPeerAuthId(IsoAuthParams *params, const CJson *in)
325 {
326     const char *payloadHex = GetStringFromJson(in, FIELD_PAYLOAD);
327     if (payloadHex == NULL) {
328         LOGE("Get payloadHex peer from json failed.");
329         return HC_ERR_JSON_GET;
330     }
331     int32_t res = InitSingleParam(&(params->isoBaseParams.authIdPeer), HcStrlen(payloadHex) / BYTE_TO_HEX_OPER_LENGTH);
332     if (res != HC_SUCCESS) {
333         LOGE("InitSingleParam for payload peer failed, res: %d.", res);
334         return res;
335     }
336     if (HexStringToByte(payloadHex, params->isoBaseParams.authIdPeer.val,
337         params->isoBaseParams.authIdPeer.length) != CLIB_SUCCESS) {
338         LOGE("Convert payloadPeer from hex string to byte failed.");
339         return HC_ERR_CONVERT_FAILED;
340     }
341     return HC_SUCCESS;
342 }
343 
ExtractAndVerifyPayload(IsoAuthParams * params,const CJson * in)344 int32_t ExtractAndVerifyPayload(IsoAuthParams *params, const CJson *in)
345 {
346     int32_t res = ExtractPeerAuthId(params, in);
347     if (res != HC_SUCCESS) {
348         LOGE("ExtractPeerAuthId failed, res: %d.", res);
349         return res;
350     }
351     res = GetPayloadValue(params, in);
352     if (res != HC_SUCCESS) {
353         LOGE("GetPayloadValue failed, res: %d.", res);
354         return res;
355     }
356     uint32_t deviceIdPeerLen = HcStrlen(params->deviceIdPeer);
357     uint32_t len = params->devIdPeer.length + deviceIdPeerLen;
358     char *combineString = (char *)HcMalloc(len, 0);
359     if (combineString == NULL) {
360         LOGE("Failed to malloc for combineString.");
361         return HC_ERR_ALLOC_MEMORY;
362     }
363     if (memcpy_s(combineString, len, params->devIdPeer.val, params->devIdPeer.length) != EOK) {
364         LOGE("Failed to copy peer devId.");
365         HcFree(combineString);
366         return HC_ERR_MEMORY_COPY;
367     }
368     if (memcpy_s(combineString + params->devIdPeer.length, len - params->devIdPeer.length, params->deviceIdPeer,
369         deviceIdPeerLen) != EOK) {
370         LOGE("Failed to copy peer deviceId.");
371         HcFree(combineString);
372         return HC_ERR_MEMORY_COPY;
373     }
374     if (memcmp(combineString, params->isoBaseParams.authIdPeer.val, len) != 0) {
375         LOGE("Payload is not equal.");
376         HcFree(combineString);
377         return HC_ERR_MEMORY_COMPARE;
378     }
379     HcFree(combineString);
380     return HC_SUCCESS;
381 }
382 
AuthIsoSendFinalToOut(IsoAuthParams * params,CJson * out)383 int32_t AuthIsoSendFinalToOut(IsoAuthParams *params, CJson *out)
384 {
385     CJson *sendToSelf = CreateJson();
386     if (sendToSelf == NULL) {
387         LOGE("Create sendToSelf json failed.");
388         return HC_ERR_JSON_CREATE;
389     }
390     if (AddByteToJson(sendToSelf, FIELD_SESSION_KEY,
391         params->isoBaseParams.sessionKey.val, params->isoBaseParams.sessionKey.length) != CLIB_SUCCESS) {
392         LOGE("Add sessionKey to json failed.");
393         goto CLEAN_UP;
394     }
395     if (AddStringToJson(sendToSelf, FIELD_USER_ID, params->userIdPeer) != CLIB_SUCCESS) {
396         LOGE("Add userIdPeer to json failed.");
397         goto CLEAN_UP;
398     }
399     if (AddStringToJson(sendToSelf, FIELD_DEVICE_ID, params->deviceIdPeer) != CLIB_SUCCESS) {
400         LOGE("Add deviceIdPeer to json failed.");
401         goto CLEAN_UP;
402     }
403     if (AddIntToJson(sendToSelf, FIELD_CREDENTIAL_TYPE, params->credentialType) != CLIB_SUCCESS) {
404         LOGE("Add credentialType to json failed.");
405         goto CLEAN_UP;
406     }
407     if (AddStringToJson(sendToSelf, FIELD_DEV_ID, (char *)params->devIdPeer.val) != CLIB_SUCCESS) {
408         LOGE("Add devIdPeer to json failed.");
409         goto CLEAN_UP;
410     }
411     if (AddObjToJson(out, FIELD_SEND_TO_SELF, sendToSelf) != CLIB_SUCCESS) {
412         LOGE("Add sendToSelf to json failed.");
413         goto CLEAN_UP;
414     }
415     FreeJson(sendToSelf);
416     FreeAndCleanKey(&(params->isoBaseParams.sessionKey));
417     return HC_SUCCESS;
418 CLEAN_UP:
419     FreeJson(sendToSelf);
420     FreeAndCleanKey(&(params->isoBaseParams.sessionKey));
421     return HC_ERR_JSON_ADD;
422 }
423