• 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         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(&params->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, &params->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, &params->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, &params->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, &params->localDevType) != CLIB_SUCCESS) {
228         LOGE("Failed to get localDevType from json in sym auth.");
229         goto CLEAN_UP;
230     }
231     res = InitIsoBaseParams(&params->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(&params->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