1 /*
2  * Copyright (C) 2023 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 "alg_defs.h"
17 #include "alg_loader.h"
18 #include "hc_log.h"
19 #include "identity_manager.h"
20 
SetDlSpekeProtocol(IdentityInfo *info)21 static int32_t SetDlSpekeProtocol(IdentityInfo *info)
22 {
23 #ifdef ENABLE_P2P_BIND_DL_SPEKE
24     ProtocolEntity *dlSpekeEntity = (ProtocolEntity *)HcMalloc(sizeof(ProtocolEntity), 0);
25     if (dlSpekeEntity == NULL) {
26         LOGE("Failed to alloc memory for dl speke entity!");
27         return HC_ERR_ALLOC_MEMORY;
28     }
29     dlSpekeEntity->protocolType = ALG_DL_SPEKE;
30     dlSpekeEntity->expandProcessCmds = CMD_IMPORT_AUTH_CODE | CMD_ADD_TRUST_DEVICE;
31     if (info->protocolVec.pushBack(&info->protocolVec, (const ProtocolEntity **)&dlSpekeEntity) == NULL) {
32         LOGE("Failed to push dl speke entity!");
33         HcFree(dlSpekeEntity);
34         return HC_ERR_ALLOC_MEMORY;
35     }
36     return HC_SUCCESS;
37 #else
38     (void)info;
39     return HC_SUCCESS;
40 #endif
41 }
42 
SetIsoProtocol(IdentityInfo *info)43 static int32_t SetIsoProtocol(IdentityInfo *info)
44 {
45 #ifdef ENABLE_P2P_BIND_ISO
46     ProtocolEntity *isoEntity = (ProtocolEntity *)HcMalloc(sizeof(ProtocolEntity), 0);
47     if (isoEntity == NULL) {
48         LOGE("Failed to alloc memory for iso entity!");
49         return HC_ERR_ALLOC_MEMORY;
50     }
51     isoEntity->protocolType = ALG_ISO;
52     isoEntity->expandProcessCmds = CMD_IMPORT_AUTH_CODE | CMD_ADD_TRUST_DEVICE;
53     if (info->protocolVec.pushBack(&info->protocolVec, (const ProtocolEntity **)&isoEntity) == NULL) {
54         LOGE("Failed to push iso entity!");
55         HcFree(isoEntity);
56         return HC_ERR_ALLOC_MEMORY;
57     }
58     return HC_SUCCESS;
59 #else
60     (void)info;
61     return HC_SUCCESS;
62 #endif
63 }
64 
SetLiteProtocols(IdentityInfo *info)65 static int32_t SetLiteProtocols(IdentityInfo *info)
66 {
67     int32_t res = SetDlSpekeProtocol(info);
68     if (res != HC_SUCCESS) {
69         return res;
70     }
71     return SetIsoProtocol(info);
72 }
73 
SetLiteProtocolsForPinType(const CJson *in, IdentityInfo *info)74 static int32_t SetLiteProtocolsForPinType(const CJson *in, IdentityInfo *info)
75 {
76 #ifndef ENABLE_P2P_BIND_LITE_PROTOCOL_CHECK
77     (void)in;
78     return SetLiteProtocols(info);
79 #else
80     int32_t protocolExpandVal = INVALID_PROTOCOL_EXPAND_VALUE;
81     (void)GetIntFromJson(in, FIELD_PROTOCOL_EXPAND, &protocolExpandVal);
82     int32_t res = HC_SUCCESS;
83     if (protocolExpandVal == LITE_PROTOCOL_STANDARD_MODE ||
84         protocolExpandVal == LITE_PROTOCOL_COMPATIBILITY_MODE) {
85         res = SetLiteProtocols(info);
86     }
87     return res;
88 #endif
89 }
90 
SetProtocolsForPinType(const CJson *in, IdentityInfo *info)91 static int32_t SetProtocolsForPinType(const CJson *in, IdentityInfo *info)
92 {
93 #ifdef ENABLE_P2P_BIND_EC_SPEKE
94     ProtocolEntity *ecSpekeEntity = (ProtocolEntity *)HcMalloc(sizeof(ProtocolEntity), 0);
95     if (ecSpekeEntity == NULL) {
96         LOGE("Failed to alloc memory for ec speke entity!");
97         return HC_ERR_ALLOC_MEMORY;
98     }
99     ecSpekeEntity->protocolType = ALG_EC_SPEKE;
100     ecSpekeEntity->expandProcessCmds = CMD_EXCHANGE_PK | CMD_ADD_TRUST_DEVICE;
101     if (info->protocolVec.pushBack(&info->protocolVec, (const ProtocolEntity **)&ecSpekeEntity) == NULL) {
102         LOGE("Failed to push ec speke entity!");
103         HcFree(ecSpekeEntity);
104         return HC_ERR_ALLOC_MEMORY;
105     }
106 #endif
107 
108     return SetLiteProtocolsForPinType(in, info);
109 }
110 
IsDirectAuth(const CJson *context)111 static bool IsDirectAuth(const CJson *context)
112 {
113     bool isDirectAuth = false;
114     (void)GetBoolFromJson(context, FIELD_IS_DIRECT_AUTH, &isDirectAuth);
115     return isDirectAuth;
116 }
117 
SetProtocolsForDirectAuth(IdentityInfo *info)118 static int32_t SetProtocolsForDirectAuth(IdentityInfo *info)
119 {
120 #ifdef ENABLE_P2P_AUTH_EC_SPEKE
121     ProtocolEntity *ecSpekeEntity = (ProtocolEntity *)HcMalloc(sizeof(ProtocolEntity), 0);
122     if (ecSpekeEntity == NULL) {
123         LOGE("Failed to alloc memory for ec speke entity!");
124         return HC_ERR_ALLOC_MEMORY;
125     }
126     ecSpekeEntity->protocolType = ALG_EC_SPEKE;
127     ecSpekeEntity->expandProcessCmds = 0;
128     if (info->protocolVec.pushBack(&info->protocolVec, (const ProtocolEntity **)&ecSpekeEntity) == NULL) {
129         LOGE("Failed to push ecspeke entity!");
130         HcFree(ecSpekeEntity);
131         return HC_ERR_ALLOC_MEMORY;
132     }
133 #else
134 #endif
135 
136     return HC_SUCCESS;
137 }
138 
GetCredInfosByPeerIdentity(const CJson *in, IdentityInfoVec *vec)139 static int32_t GetCredInfosByPeerIdentity(const CJson *in, IdentityInfoVec *vec)
140 {
141     IdentityInfo *info = CreateIdentityInfo();
142     if (info == NULL) {
143         LOGE("Failed to create identity info!");
144         return HC_ERR_ALLOC_MEMORY;
145     }
146     CJson *urlJson = CreateCredUrlJson(PRE_SHARED, KEY_TYPE_SYM, TRUST_TYPE_PIN);
147     if (!urlJson) {
148         LOGE("Failed to create CredUrlJson info!");
149         DestroyIdentityInfo(info);
150         return HC_ERR_ALLOC_MEMORY;
151     }
152     if (IsDirectAuth(in) && AddBoolToJson(urlJson, FIELD_IS_DIRECT_AUTH, true) != HC_SUCCESS) {
153         LOGE("Failed to isDirectAuth to preshared url!");
154         FreeJson(urlJson);
155         DestroyIdentityInfo(info);
156         return HC_ERR_JSON_ADD;
157     }
158     char *urlStr = PackJsonToString(urlJson);
159     FreeJson(urlJson);
160     if (urlStr == NULL) {
161         LOGE("Failed to pack url json to string!");
162         DestroyIdentityInfo(info);
163         return HC_ERR_PACKAGE_JSON_TO_STRING_FAIL;
164     }
165     int32_t ret = SetPreSharedUrlForProof(urlStr, &info->proof.preSharedUrl);
166     FreeJsonString(urlStr);
167     if (ret != HC_SUCCESS) {
168         LOGE("Failed to set preSharedUrl of proof!");
169         DestroyIdentityInfo(info);
170         return ret;
171     }
172     if (IsDirectAuth(in)) {
173         ret = SetProtocolsForDirectAuth(info);
174         info->IdInfoType = P2P_DIRECT_AUTH;
175     } else {
176         ret = SetProtocolsForPinType(in, info);
177     }
178     if (ret != HC_SUCCESS) {
179         LOGE("Failed to set protocols!");
180         DestroyIdentityInfo(info);
181         return ret;
182     }
183     info->proofType = PRE_SHARED;
184     vec->pushBack(vec, (const IdentityInfo **)&info);
185     return HC_SUCCESS;
186 }
187 
GetCredInfoByPeerUrl(const CJson *in, const Uint8Buff *presharedUrl, IdentityInfo **returnInfo)188 static int32_t GetCredInfoByPeerUrl(const CJson *in, const Uint8Buff *presharedUrl, IdentityInfo **returnInfo)
189 {
190     if (in == NULL || presharedUrl == NULL || returnInfo == NULL) {
191         LOGE("Invalid input params!");
192         return HC_ERR_INVALID_PARAMS;
193     }
194     IdentityInfo *info = CreateIdentityInfo();
195     if (info == NULL) {
196         LOGE("Failed to create identity info!");
197         return HC_ERR_ALLOC_MEMORY;
198     }
199     CJson *urlJson = CreateJsonFromString((const char *)presharedUrl->val);
200     if (urlJson == NULL) {
201         LOGE("Failed to create url json!");
202         DestroyIdentityInfo(info);
203         return HC_ERR_JSON_CREATE;
204     }
205     int32_t credentialType = PRE_SHARED;
206     if (GetIntFromJson(urlJson, PRESHARED_URL_CREDENTIAL_TYPE, &credentialType) != HC_SUCCESS) {
207         LOGE("Failed to get credential type!");
208         DestroyIdentityInfo(info);
209         FreeJson(urlJson);
210         return HC_ERR_JSON_GET;
211     }
212     FreeJson(urlJson);
213     int32_t ret = SetPreSharedUrlForProof((const char *)presharedUrl->val, &info->proof.preSharedUrl);
214     if (ret != HC_SUCCESS) {
215         LOGE("Failed to set preSharedUrl of proof!");
216         DestroyIdentityInfo(info);
217         return ret;
218     }
219     if (IsDirectAuth(in)) {
220         ret = SetProtocolsForDirectAuth(info);
221         info->IdInfoType = P2P_DIRECT_AUTH;
222     } else {
223         ret = SetProtocolsForPinType(in, info);
224     }
225     if (ret != HC_SUCCESS) {
226         LOGE("Failed to set protocols!");
227         DestroyIdentityInfo(info);
228         return ret;
229     }
230     info->proofType = credentialType;
231     *returnInfo = info;
232     return HC_SUCCESS;
233 }
234 
AuthGeneratePskUsePin(const CJson *in, const Uint8Buff *seed, const char *pinCode, Uint8Buff *sharedSecret)235 static int32_t AuthGeneratePskUsePin(const CJson *in, const Uint8Buff *seed, const char *pinCode,
236     Uint8Buff *sharedSecret)
237 {
238     int32_t osAccountId;
239     if (GetIntFromJson(in, FIELD_OS_ACCOUNT_ID, &osAccountId) != HC_SUCCESS) {
240         LOGE("Failed to get osAccountId!");
241         return HC_ERR_JSON_GET;
242     }
243     Uint8Buff messageBuf = { (uint8_t *)pinCode, (uint32_t)HcStrlen(pinCode) };
244     uint8_t hash[SHA256_LEN] = { 0 };
245     Uint8Buff hashBuf = { hash, sizeof(hash) };
246     int ret = GetLoaderInstance()->sha256(&messageBuf, &hashBuf);
247     if (ret != HC_SUCCESS) {
248         LOGE("sha256 failed, ret:%d", ret);
249         return ret;
250     }
251     KeyParams keyParams = { { hashBuf.val, hashBuf.length, false }, false, osAccountId };
252     return GetLoaderInstance()->computeHmac(&keyParams, seed, sharedSecret);
253 }
254 
255 #ifdef ENABLE_P2P_BIND_LITE_PROTOCOL_CHECK
CheckPinLenForStandardIso(const CJson *in, const char *pinCode)256 static bool CheckPinLenForStandardIso(const CJson *in, const char *pinCode)
257 {
258     int32_t protocolExpandVal = INVALID_PROTOCOL_EXPAND_VALUE;
259     (void)GetIntFromJson(in, FIELD_PROTOCOL_EXPAND, &protocolExpandVal);
260     if (protocolExpandVal != LITE_PROTOCOL_STANDARD_MODE) {
261         LOGI("not standard iso, no need to check.");
262         return true;
263     }
264     return HcStrlen(pinCode) >= PIN_CODE_LEN_LONG;
265 }
266 #endif
267 
GetSharedSecretForPinInIso(const CJson *in, Uint8Buff *sharedSecret)268 static int32_t GetSharedSecretForPinInIso(const CJson *in, Uint8Buff *sharedSecret)
269 {
270     const char *pinCode = GetStringFromJson(in, FIELD_PIN_CODE);
271     if (pinCode == NULL) {
272         LOGE("Failed to get pinCode!");
273         return HC_ERR_JSON_GET;
274     }
275     if (HcStrlen(pinCode) < PIN_CODE_LEN_SHORT) {
276         LOGE("Pin code is too short!");
277         return HC_ERR_INVALID_LEN;
278     }
279 #ifdef ENABLE_P2P_BIND_LITE_PROTOCOL_CHECK
280     if (!CheckPinLenForStandardIso(in, pinCode)) {
281         LOGE("Invalid pin code len!");
282         return HC_ERR_INVALID_LEN;
283     }
284 #endif
285     uint8_t *seedVal = (uint8_t *)HcMalloc(SEED_LEN, 0);
286     if (seedVal == NULL) {
287         LOGE("Failed to alloc seed memory!");
288         return HC_ERR_ALLOC_MEMORY;
289     }
290     Uint8Buff seedBuff = { seedVal, SEED_LEN };
291     int32_t ret = GetByteFromJson(in, FIELD_SEED, seedBuff.val, seedBuff.length);
292     if (ret != HC_SUCCESS) {
293         LOGE("Failed to get seed!");
294         HcFree(seedVal);
295         return HC_ERR_JSON_GET;
296     }
297     uint8_t *pskVal = (uint8_t *)HcMalloc(ISO_PSK_LEN, 0);
298     if (pskVal == NULL) {
299         LOGE("Failed to alloc psk memory!");
300         HcFree(seedVal);
301         return HC_ERR_ALLOC_MEMORY;
302     }
303     sharedSecret->val = pskVal;
304     sharedSecret->length = ISO_PSK_LEN;
305     ret = AuthGeneratePskUsePin(in, &seedBuff, pinCode, sharedSecret);
306     HcFree(seedVal);
307     if (ret != HC_SUCCESS) {
308         LOGE("Failed to generate psk use pin!");
309         FreeBuffData(sharedSecret);
310     }
311     return ret;
312 }
313 
GetSharedSecretForPinInPake(const CJson *in, Uint8Buff *sharedSecret)314 static int32_t GetSharedSecretForPinInPake(const CJson *in, Uint8Buff *sharedSecret)
315 {
316     const char *pinCode = GetStringFromJson(in, FIELD_PIN_CODE);
317     if (pinCode == NULL) {
318         LOGE("Failed to get pinCode!");
319         return HC_ERR_JSON_GET;
320     }
321     uint32_t pinLen = HcStrlen(pinCode);
322     if (pinLen < PIN_CODE_LEN_SHORT) {
323         LOGE("Invalid pin code len!");
324         return HC_ERR_INVALID_LEN;
325     }
326     sharedSecret->val = (uint8_t *)HcMalloc(pinLen, 0);
327     if (sharedSecret->val == NULL) {
328         LOGE("Failed to alloc sharedSecret memory!");
329         return HC_ERR_ALLOC_MEMORY;
330     }
331     if (memcpy_s(sharedSecret->val, pinLen, pinCode, pinLen) != HC_SUCCESS) {
332         LOGE("Failed to memcpy pinCode!");
333         FreeBuffData(sharedSecret);
334         return HC_ERR_MEMORY_COPY;
335     }
336     sharedSecret->length = pinLen;
337     return HC_SUCCESS;
338 }
339 
GetSharedSecretByUrl( const CJson *in, const Uint8Buff *presharedUrl, ProtocolAlgType protocolType, Uint8Buff *sharedSecret)340 static int32_t GetSharedSecretByUrl(
341     const CJson *in, const Uint8Buff *presharedUrl, ProtocolAlgType protocolType, Uint8Buff *sharedSecret)
342 {
343     if (in == NULL || presharedUrl == NULL || sharedSecret == NULL) {
344         LOGE("Invalid input params!");
345         return HC_ERR_INVALID_PARAMS;
346     }
347     int32_t ret;
348     if (protocolType == ALG_ISO) {
349         ret = GetSharedSecretForPinInIso(in, sharedSecret);
350         LOGI("get shared secret for pin in iso result: %d", ret);
351     } else {
352         ret = GetSharedSecretForPinInPake(in, sharedSecret);
353         LOGI("get shared secret for pin in pake result: %d", ret);
354     }
355 
356     return ret;
357 }
358 
GetCredInfoByPeerCert(const CJson *in, const CertInfo *certInfo, IdentityInfo **returnInfo)359 static int32_t GetCredInfoByPeerCert(const CJson *in, const CertInfo *certInfo, IdentityInfo **returnInfo)
360 {
361     // NOT SUPPORT FOR PIN
362     (void)in;
363     (void)certInfo;
364     (void)returnInfo;
365     return HC_ERR_ALG_FAIL;
366 }
367 
GetSharedSecretByPeerCert( const CJson *in, const CertInfo *peerCertInfo, ProtocolAlgType protocolType, Uint8Buff *sharedSecret)368 static int32_t GetSharedSecretByPeerCert(
369     const CJson *in, const CertInfo *peerCertInfo, ProtocolAlgType protocolType, Uint8Buff *sharedSecret)
370 {
371     // NOT SUPPORT FOR PIN
372     (void)in;
373     (void)peerCertInfo;
374     (void)protocolType;
375     (void)sharedSecret;
376     return HC_ERR_ALG_FAIL;
377 }
378 
379 static const AuthIdentity g_authIdentity = {
380     .getCredInfosByPeerIdentity = GetCredInfosByPeerIdentity,
381     .getCredInfoByPeerUrl = GetCredInfoByPeerUrl,
382     .getSharedSecretByUrl = GetSharedSecretByUrl,
383     .getCredInfoByPeerCert = GetCredInfoByPeerCert,
384     .getSharedSecretByPeerCert = GetSharedSecretByPeerCert,
385 };
386 
GetPinAuthIdentity(void)387 const AuthIdentity *GetPinAuthIdentity(void)
388 {
389     return &g_authIdentity;
390 }