• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "das_task_common.h"
17 #include "alg_defs.h"
18 #include "alg_loader.h"
19 #include "device_auth_defines.h"
20 #include "hc_log.h"
21 #include "hc_types.h"
22 #include "protocol_common.h"
23 #include "string_util.h"
24 
25 #define KEY_TYPE_PAIR_LEN 2
26 #define PACKAGE_NAME_MAX_LEN 256
27 #define SERVICE_TYPE_MAX_LEN 256
28 #define AUTH_ID_MAX_LEN 64
29 
30 #define MESSAGE_RETURN 0x8000
31 #define MESSAGE_PREFIX 0x0010
32 
33 /* in order to expand to uint16_t */
34 static const uint8_t KEY_TYPE_PAIRS[KEY_ALIAS_TYPE_END][KEY_TYPE_PAIR_LEN] = {
35     { 0x00, 0x00 }, /* ACCESSOR_PK */
36     { 0x00, 0x01 }, /* CONTROLLER_PK */
37     { 0x00, 0x02 }, /* ed25519 KEYPAIR */
38     { 0x00, 0x03 }, /* KEK, key encryption key, used only by DeviceAuthService */
39     { 0x00, 0x04 }, /* DEK, data encryption key, used only by upper apps */
40     { 0x00, 0x05 }, /* key tmp */
41     { 0x00, 0x06 }, /* PSK, preshared key index */
42     { 0x00, 0x07 }  /* AUTHTOKEN */
43 };
44 
DasSendErrorToOut(CJson * out,int errCode)45 void DasSendErrorToOut(CJson *out, int errCode)
46 {
47     CJson *sendToSelf = CreateJson();
48     if (sendToSelf == NULL) {
49         LOGE("Create sendToSelf json failed.");
50         return;
51     }
52     CJson *sendToPeer = CreateJson();
53     if (sendToPeer == NULL) {
54         LOGE("Create sendToPeer json failed.");
55         FreeJson(sendToSelf);
56         return;
57     }
58     CJson *payload = CreateJson();
59     if (payload == NULL) {
60         LOGE("Create payload json failed.");
61         goto ERR;
62     }
63     int res;
64     GOTO_ERR_AND_SET_RET(AddIntToJson(sendToSelf, FIELD_AUTH_FORM, AUTH_FORM_ACCOUNT_UNRELATED), res);
65     GOTO_ERR_AND_SET_RET(AddIntToJson(sendToSelf, FIELD_ERROR_CODE, errCode), res);
66 
67     GOTO_ERR_AND_SET_RET(AddIntToJson(payload, FIELD_ERROR_CODE, errCode), res);
68     GOTO_ERR_AND_SET_RET(AddObjToJson(sendToPeer, FIELD_PAYLOAD, payload), res);
69     GOTO_ERR_AND_SET_RET(AddIntToJson(sendToPeer, FIELD_MESSAGE, ERR_MESSAGE), res);
70 
71     GOTO_ERR_AND_SET_RET(AddObjToJson(out, FIELD_SEND_TO_PEER, sendToPeer), res);
72     GOTO_ERR_AND_SET_RET(AddObjToJson(out, FIELD_SEND_TO_SELF, sendToSelf), res);
73 ERR:
74     FreeJson(sendToPeer);
75     FreeJson(sendToSelf);
76     FreeJson(payload);
77 }
78 
DasSendErrMsgToSelf(CJson * out,int errCode)79 void DasSendErrMsgToSelf(CJson *out, int errCode)
80 {
81     CJson *sendToSelf = CreateJson();
82     if (sendToSelf == NULL) {
83         LOGE("Create sendToSelf json failed.");
84         return;
85     }
86 
87     if (AddIntToJson(sendToSelf, FIELD_AUTH_FORM, AUTH_FORM_ACCOUNT_UNRELATED) != 0) {
88         FreeJson(sendToSelf);
89         LOGE("Add authForm failed.");
90         return;
91     }
92     if (AddIntToJson(sendToSelf, FIELD_ERROR_CODE, errCode) != 0) {
93         FreeJson(sendToSelf);
94         LOGE("Add errCode failed.");
95         return;
96     }
97     if (AddObjToJson(out, FIELD_SEND_TO_SELF, sendToSelf) != 0) {
98         FreeJson(sendToSelf);
99         LOGE("Add sendToSelf failed.");
100         return;
101     }
102     FreeJson(sendToSelf);
103 }
104 
ProtocolMessageIn(const CJson * in)105 uint32_t ProtocolMessageIn(const CJson *in)
106 {
107     int32_t message = 0;
108     if (GetIntFromJson(in, FIELD_MESSAGE, &message) != 0) {
109         return INVALID_MESSAGE;
110     }
111     if (message == ERR_MESSAGE) {
112         return ERR_MESSAGE;
113     }
114     return message & 0x000F; /* get lower 8 bit */
115 }
116 
ClientProtocolMessageOut(CJson * out,int opCode,uint32_t step)117 int ClientProtocolMessageOut(CJson *out, int opCode, uint32_t step)
118 {
119     CJson *sendToPeer = GetObjFromJson(out, FIELD_SEND_TO_PEER);
120     if (sendToPeer == NULL) {
121         LOGD("No need to send to peer");
122         return HC_SUCCESS;
123     }
124     int res;
125     switch (opCode) {
126         case OP_BIND:
127         case AUTH_KEY_AGREEMENT:
128             res = AddIntToJson(sendToPeer, FIELD_MESSAGE, step);
129             break;
130         case AUTHENTICATE:
131         case OP_UNBIND:
132             step = step | MESSAGE_PREFIX;
133             res = AddIntToJson(sendToPeer, FIELD_MESSAGE, step);
134             break;
135         default:
136             LOGE("Unsupported opCode: %d.", opCode);
137             return HC_ERR_NOT_SUPPORT;
138     }
139     return (res == 0) ? HC_SUCCESS : HC_ERR_JSON_ADD;
140 }
141 
ServerProtocolMessageOut(CJson * out,int opCode,uint32_t step)142 int ServerProtocolMessageOut(CJson *out, int opCode, uint32_t step)
143 {
144     int res;
145     CJson *sendToPeer = GetObjFromJson(out, FIELD_SEND_TO_PEER);
146     if (sendToPeer == NULL) {
147         LOGD("No need to send to peer");
148         return HC_SUCCESS;
149     }
150     switch (opCode) {
151         case OP_BIND:
152         case AUTH_KEY_AGREEMENT:
153             step = step | MESSAGE_RETURN;
154             res = AddIntToJson(sendToPeer, FIELD_MESSAGE, step);
155             break;
156         case AUTHENTICATE:
157         case OP_UNBIND:
158             step = step | MESSAGE_RETURN;
159             step = step | MESSAGE_PREFIX;
160             res = AddIntToJson(sendToPeer, FIELD_MESSAGE, step);
161             break;
162         default:
163             LOGE("Unsupported opCode: %d.", opCode);
164             return HC_ERR_NOT_SUPPORT;
165     }
166     return (res == 0) ? HC_SUCCESS : HC_ERR_JSON_ADD;
167 }
168 
CombineServiceId(const Uint8Buff * pkgName,const Uint8Buff * serviceType,Uint8Buff * serviceId)169 static int32_t CombineServiceId(const Uint8Buff *pkgName, const Uint8Buff *serviceType, Uint8Buff *serviceId)
170 {
171     int32_t res = HC_SUCCESS;
172     Uint8Buff serviceIdPlain = { NULL, 0 };
173     serviceIdPlain.length = pkgName->length + serviceType->length;
174     serviceIdPlain.val = (uint8_t *)HcMalloc(serviceIdPlain.length, 0);
175     if (serviceIdPlain.val == NULL) {
176         LOGE("malloc serviceIdPlain.val failed.");
177         res = HC_ERR_ALLOC_MEMORY;
178         goto ERR;
179     }
180 
181     if (memcpy_s(serviceIdPlain.val, serviceIdPlain.length, pkgName->val, pkgName->length) != EOK) {
182         LOGE("Copy service id: pkgName failed.");
183         res =  HC_ERR_MEMORY_COPY;
184         goto ERR;
185     }
186     if (memcpy_s(serviceIdPlain.val + pkgName->length,  serviceIdPlain.length - pkgName->length,
187         serviceType->val, serviceType->length) != EOK) {
188         LOGE("Copy service id: serviceType failed.");
189         res = HC_ERR_MEMORY_COPY;
190         goto ERR;
191     }
192 
193     res = GetLoaderInstance()->sha256(&serviceIdPlain, serviceId);
194     if (res != HC_SUCCESS) {
195         LOGE("Service id Sha256 failed.");
196         goto ERR;
197     }
198 ERR:
199     HcFree(serviceIdPlain.val);
200     return res;
201 }
202 
CombineKeyAlias(const Uint8Buff * serviceId,const Uint8Buff * keyType,const Uint8Buff * authId,Uint8Buff * keyAliasHash)203 static int32_t CombineKeyAlias(const Uint8Buff *serviceId, const Uint8Buff *keyType,
204     const Uint8Buff *authId, Uint8Buff *keyAliasHash)
205 {
206     int32_t res = HC_SUCCESS;
207     Uint8Buff keyAliasBuff = { NULL, 0 };
208     keyAliasBuff.length = serviceId->length + authId->length + keyType->length;
209     keyAliasBuff.val = (uint8_t *)HcMalloc(keyAliasBuff.length, 0);
210     if (keyAliasBuff.val == NULL) {
211         LOGE("Malloc mem failed.");
212         return HC_ERR_ALLOC_MEMORY;
213     }
214 
215     uint32_t totalLen = keyAliasBuff.length;
216     uint32_t usedLen = 0;
217     if (memcpy_s(keyAliasBuff.val, totalLen, serviceId->val, serviceId->length) != EOK) {
218         LOGE("Copy serviceId failed.");
219         res = HC_ERR_MEMORY_COPY;
220         goto ERR;
221     }
222     usedLen = usedLen + serviceId->length;
223 
224     if (memcpy_s(keyAliasBuff.val + usedLen, totalLen - usedLen, keyType->val, keyType->length) != EOK) {
225         LOGE("Copy keyType failed.");
226         res = HC_ERR_MEMORY_COPY;
227         goto ERR;
228     }
229     usedLen = usedLen + keyType->length;
230 
231     if (memcpy_s(keyAliasBuff.val + usedLen, totalLen - usedLen, authId->val, authId->length) != EOK) {
232         LOGE("Copy authId failed.");
233         res = HC_ERR_MEMORY_COPY;
234         goto ERR;
235     }
236 
237     res = GetLoaderInstance()->sha256(&keyAliasBuff, keyAliasHash);
238     if (res != HC_SUCCESS) {
239         LOGE("Sha256 failed.");
240         goto ERR;
241     }
242 ERR:
243     HcFree(keyAliasBuff.val);
244     return res;
245 }
246 
CombineKeyAliasForIso(const Uint8Buff * serviceId,const Uint8Buff * keyType,const Uint8Buff * authId,Uint8Buff * outKeyAlias)247 static int32_t CombineKeyAliasForIso(const Uint8Buff *serviceId, const Uint8Buff *keyType,
248     const Uint8Buff *authId, Uint8Buff *outKeyAlias)
249 {
250     if (outKeyAlias->length != SHA256_LEN) {
251         return HC_ERR_INVALID_LEN;
252     }
253     int32_t res = CombineKeyAlias(serviceId, keyType, authId, outKeyAlias);
254     if (res != HC_SUCCESS) {
255         LOGE("CombineKeyAlias failed.");
256         return res;
257     }
258     return res;
259 }
260 
CombineKeyAliasForPake(const Uint8Buff * serviceId,const Uint8Buff * keyType,const Uint8Buff * authId,Uint8Buff * outKeyAlias)261 static int32_t CombineKeyAliasForPake(const Uint8Buff *serviceId, const Uint8Buff *keyType,
262     const Uint8Buff *authId, Uint8Buff *outKeyAlias)
263 {
264     int32_t res;
265     Uint8Buff keyAliasHash = { NULL, SHA256_LEN };
266     char *outKeyAliasHex = NULL;
267     if (outKeyAlias->length != SHA256_LEN * BYTE_TO_HEX_OPER_LENGTH) {
268         res = HC_ERR_INVALID_LEN;
269         goto ERR;
270     }
271     keyAliasHash.val = (uint8_t *)HcMalloc(keyAliasHash.length, 0);
272     if (keyAliasHash.val == NULL) {
273         LOGE("Malloc keyAliasHash failed");
274         res = HC_ERR_ALLOC_MEMORY;
275         goto ERR;
276     }
277     res = CombineKeyAlias(serviceId, keyType, authId, &keyAliasHash);
278     if (res != HC_SUCCESS) {
279         LOGE("CombineKeyAlias failed.");
280         goto ERR;
281     }
282     uint32_t outKeyAliasHexLen = keyAliasHash.length * BYTE_TO_HEX_OPER_LENGTH + 1;
283     outKeyAliasHex = (char *)HcMalloc(outKeyAliasHexLen, 0);
284     res = ByteToHexString(keyAliasHash.val, keyAliasHash.length, outKeyAliasHex, outKeyAliasHexLen);
285     if (res != HC_SUCCESS) {
286         LOGE("ByteToHexString failed");
287         goto ERR;
288     }
289     if (memcpy_s(outKeyAlias->val, outKeyAlias->length, outKeyAliasHex, strlen(outKeyAliasHex)) != EOK) {
290         LOGE("memcpy outkeyalias failed.");
291         res = HC_ERR_MEMORY_COPY;
292         goto ERR;
293     }
294 ERR:
295     HcFree(keyAliasHash.val);
296     HcFree(outKeyAliasHex);
297     return res;
298 }
299 
GenerateKeyAlias(const Uint8Buff * pkgName,const Uint8Buff * serviceType,const KeyAliasType keyType,const Uint8Buff * authId,Uint8Buff * outKeyAlias)300 int32_t GenerateKeyAlias(const Uint8Buff *pkgName, const Uint8Buff *serviceType,
301     const KeyAliasType keyType, const Uint8Buff *authId, Uint8Buff *outKeyAlias)
302 {
303     CHECK_PTR_RETURN_ERROR_CODE(pkgName, "pkgName");
304     CHECK_PTR_RETURN_ERROR_CODE(pkgName->val, "pkgName->val");
305     CHECK_PTR_RETURN_ERROR_CODE(serviceType, "serviceType");
306     CHECK_PTR_RETURN_ERROR_CODE(serviceType->val, "serviceType->val");
307     CHECK_PTR_RETURN_ERROR_CODE(authId, "authId");
308     CHECK_PTR_RETURN_ERROR_CODE(authId->val, "authId->val");
309     CHECK_PTR_RETURN_ERROR_CODE(outKeyAlias, "outKeyAlias");
310     CHECK_PTR_RETURN_ERROR_CODE(outKeyAlias->val, "outKeyAlias->val");
311     if (pkgName->length == 0 || serviceType->length == 0 || authId->length == 0 || outKeyAlias->length == 0) {
312         LOGE("Invalid zero length params exist.");
313         return HC_ERR_INVALID_LEN;
314     }
315     if (pkgName->length > PACKAGE_NAME_MAX_LEN || serviceType->length > SERVICE_TYPE_MAX_LEN ||
316         authId->length > AUTH_ID_MAX_LEN || keyType >= KEY_ALIAS_TYPE_END) {
317         LOGE("Out of length params exist.");
318         return HC_ERR_INVALID_LEN;
319     }
320 
321     int32_t res;
322     Uint8Buff serviceId = { NULL, SHA256_LEN };
323     serviceId.val = (uint8_t *)HcMalloc(serviceId.length, 0);
324     if (serviceId.val == NULL) {
325         LOGE("Malloc for serviceId failed.");
326         res = HC_ERR_ALLOC_MEMORY;
327         goto ERR;
328     }
329     res = CombineServiceId(pkgName, serviceType, &serviceId);
330     if (res != HC_SUCCESS) {
331         LOGE("CombineServiceId failed, res: %x.", res);
332         goto ERR;
333     }
334     Uint8Buff keyTypeBuff = { (uint8_t *)KEY_TYPE_PAIRS[keyType], KEY_TYPE_PAIR_LEN };
335     if (keyType == KEY_ALIAS_AUTH_TOKEN) {
336         res = CombineKeyAliasForIso(&serviceId, &keyTypeBuff, authId, outKeyAlias);
337     } else {
338         res = CombineKeyAliasForPake(&serviceId, &keyTypeBuff, authId, outKeyAlias);
339     }
340     if (res != HC_SUCCESS) {
341         LOGE("CombineKeyAlias failed, keyType: %d, res: %d", keyType, res);
342     }
343 ERR:
344     HcFree(serviceId.val);
345     return res;
346 }
347 
GetIdPeer(const CJson * in,const char * peerIdKey,const Uint8Buff * authIdSelf,Uint8Buff * authIdPeer)348 int32_t GetIdPeer(const CJson *in, const char *peerIdKey, const Uint8Buff *authIdSelf, Uint8Buff *authIdPeer)
349 {
350     const char *authIdStr = GetStringFromJson(in, peerIdKey);
351     if (authIdStr == NULL) {
352         LOGE("Get peer id from json failed.");
353         return HC_ERR_JSON_GET;
354     }
355     uint32_t authIdLen = HcStrlen(authIdStr) / BYTE_TO_HEX_OPER_LENGTH;
356     if (authIdLen == 0 || authIdLen > MAX_AUTH_ID_LEN) {
357         LOGE("Invalid authIdPeerLen: %u.", authIdLen);
358         return HC_ERR_INVALID_LEN;
359     }
360     int32_t res = InitSingleParam(authIdPeer, authIdLen);
361     if (res != HC_SUCCESS) {
362         LOGE("InitSingleParam for peer authId failed, res: %d.", res);
363         return res;
364     }
365     if (HexStringToByte(authIdStr, authIdPeer->val, authIdPeer->length) != HC_SUCCESS) {
366         LOGE("HexStringToByte for authIdPeer failed.");
367         return HC_ERR_CONVERT_FAILED;
368     }
369     if ((authIdSelf->length == authIdPeer->length) &&
370         memcmp(authIdSelf->val, authIdPeer->val, authIdSelf->length) == 0) {
371         LOGE("Peer id can not be equal to self id.");
372         return HC_ERR_INVALID_PARAMS;
373     }
374     return HC_SUCCESS;
375 }
376 
GetAndCheckAuthIdPeer(const CJson * in,const Uint8Buff * authIdSelf,const Uint8Buff * authIdPeer)377 int32_t GetAndCheckAuthIdPeer(const CJson *in, const Uint8Buff *authIdSelf, const Uint8Buff *authIdPeer)
378 {
379     const CJson *payload = GetObjFromJson(in, FIELD_PAYLOAD);
380     if (payload == NULL) {
381         LOGE("Get payload failed.");
382         return HC_ERR_JSON_GET;
383     }
384     const char *authIdStr = GetStringFromJson(payload, FIELD_PEER_AUTH_ID);
385     if (authIdStr == NULL) {
386         LOGE("Get peer authId from payload failed.");
387         return HC_ERR_JSON_GET;
388     }
389     uint32_t authIdPeerLen = HcStrlen(authIdStr) / BYTE_TO_HEX_OPER_LENGTH;
390     if (authIdPeerLen == 0 || authIdPeerLen > MAX_AUTH_ID_LEN) {
391         LOGE("Invalid peer authId length.");
392         return HC_ERR_INVALID_LEN;
393     }
394     uint8_t *authIdPeerTmp = (uint8_t *)HcMalloc(authIdPeerLen, 0);
395     if (authIdPeerTmp == NULL) {
396         LOGE("Malloc for authIdPeerTmp failed.");
397         return HC_ERR_ALLOC_MEMORY;
398     }
399     if (HexStringToByte(authIdStr, authIdPeerTmp, authIdPeerLen) != HC_SUCCESS) {
400         LOGE("Convert peer authId from hex string to byte failed.");
401         HcFree(authIdPeerTmp);
402         return HC_ERR_CONVERT_FAILED;
403     }
404     if ((authIdSelf->length == authIdPeer->length) &&
405         memcmp(authIdSelf->val, authIdPeer->val, authIdSelf->length) == EOK) {
406         LOGE("Peer id can not be equal to self id.");
407         HcFree(authIdPeerTmp);
408         return HC_ERR_INVALID_PARAMS;
409     }
410     if (memcmp(authIdPeer->val, authIdPeerTmp, authIdPeer->length) != EOK) {
411         LOGE("Peer authId does not match.");
412         HcFree(authIdPeerTmp);
413         return HC_ERR_INVALID_PARAMS;
414     }
415     HcFree(authIdPeerTmp);
416     return HC_SUCCESS;
417 }
418 
GetAuthIdPeerFromPayload(const CJson * in,const Uint8Buff * authIdSelf,Uint8Buff * authIdPeer)419 int32_t GetAuthIdPeerFromPayload(const CJson *in, const Uint8Buff *authIdSelf, Uint8Buff *authIdPeer)
420 {
421     const CJson *payload = GetObjFromJson(in, FIELD_PAYLOAD);
422     if (payload == NULL) {
423         LOGE("Not have payload.");
424         return HC_ERR_JSON_GET;
425     }
426     int res = GetIdPeer(payload, FIELD_PEER_AUTH_ID, authIdSelf, authIdPeer);
427     if (res != HC_SUCCESS) {
428         LOGE("GetIdPeer failed, res: %d.", res);
429     }
430     return res;
431 }
432 
GetAndCheckKeyLenOnServer(const CJson * in,uint32_t * keyLen)433 int32_t GetAndCheckKeyLenOnServer(const CJson *in, uint32_t *keyLen)
434 {
435     const CJson *payload = GetObjFromJson(in, FIELD_PAYLOAD);
436     if (payload == NULL) {
437         LOGE("Get payload failed.");
438         return HC_ERR_JSON_GET;
439     }
440     uint32_t tmpKeyLen = 0;
441     if (GetIntFromJson(payload, FIELD_KEY_LENGTH, (int32_t *)&tmpKeyLen) != HC_SUCCESS) {
442         LOGE("Get tmpKeyLen from payload failed.");
443         return HC_ERR_JSON_GET;
444     }
445 
446     if (*keyLen != tmpKeyLen) {
447         LOGE("Key length is not equal.");
448         return HC_ERR_INVALID_PARAMS;
449     }
450     return HC_SUCCESS;
451 }
452