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     info->protocolVec.pushBack(&info->protocolVec, (const ProtocolEntity **)&ecSpekeEntity);
129 #else
130 #endif
131 
132     return HC_SUCCESS;
133 }
134 
GetCredInfosByPeerIdentity(const CJson * in,IdentityInfoVec * vec)135 static int32_t GetCredInfosByPeerIdentity(const CJson *in, IdentityInfoVec *vec)
136 {
137     IdentityInfo *info = CreateIdentityInfo();
138     if (info == NULL) {
139         LOGE("Failed to create identity info!");
140         return HC_ERR_ALLOC_MEMORY;
141     }
142     CJson *urlJson = CreateCredUrlJson(PRE_SHARED, KEY_TYPE_SYM, TRUST_TYPE_PIN);
143     if (!urlJson) {
144         LOGE("Failed to create CredUrlJson info!");
145         DestroyIdentityInfo(info);
146         return HC_ERR_ALLOC_MEMORY;
147     }
148     if (IsDirectAuth(in) && AddBoolToJson(urlJson, FIELD_IS_DIRECT_AUTH, true) != HC_SUCCESS) {
149         LOGE("Failed to isDirectAuth to preshared url!");
150         FreeJson(urlJson);
151         DestroyIdentityInfo(info);
152         return HC_ERR_JSON_ADD;
153     }
154     char *urlStr = PackJsonToString(urlJson);
155     FreeJson(urlJson);
156     if (urlStr == NULL) {
157         LOGE("Failed to pack url json to string!");
158         DestroyIdentityInfo(info);
159         return HC_ERR_PACKAGE_JSON_TO_STRING_FAIL;
160     }
161     int32_t ret = SetPreSharedUrlForProof(urlStr, &info->proof.preSharedUrl);
162     FreeJsonString(urlStr);
163     if (ret != HC_SUCCESS) {
164         LOGE("Failed to set preSharedUrl of proof!");
165         DestroyIdentityInfo(info);
166         return ret;
167     }
168     if (IsDirectAuth(in)) {
169         ret = SetProtocolsForDirectAuth(info);
170         info->IdInfoType = P2P_DIRECT_AUTH;
171     } else {
172         ret = SetProtocolsForPinType(in, info);
173     }
174     if (ret != HC_SUCCESS) {
175         LOGE("Failed to set protocols!");
176         DestroyIdentityInfo(info);
177         return ret;
178     }
179     info->proofType = PRE_SHARED;
180     vec->pushBack(vec, (const IdentityInfo **)&info);
181     return HC_SUCCESS;
182 }
183 
GetCredInfoByPeerUrl(const CJson * in,const Uint8Buff * presharedUrl,IdentityInfo ** returnInfo)184 static int32_t GetCredInfoByPeerUrl(const CJson *in, const Uint8Buff *presharedUrl, IdentityInfo **returnInfo)
185 {
186     if (in == NULL || presharedUrl == NULL || returnInfo == NULL) {
187         LOGE("Invalid input params!");
188         return HC_ERR_INVALID_PARAMS;
189     }
190     IdentityInfo *info = CreateIdentityInfo();
191     if (info == NULL) {
192         LOGE("Failed to create identity info!");
193         return HC_ERR_ALLOC_MEMORY;
194     }
195     CJson *urlJson = CreateJsonFromString((const char *)presharedUrl->val);
196     if (urlJson == NULL) {
197         LOGE("Failed to create url json!");
198         DestroyIdentityInfo(info);
199         return HC_ERR_JSON_CREATE;
200     }
201     int32_t credentialType = PRE_SHARED;
202     if (GetIntFromJson(urlJson, PRESHARED_URL_CREDENTIAL_TYPE, &credentialType) != HC_SUCCESS) {
203         LOGE("Failed to get credential type!");
204         DestroyIdentityInfo(info);
205         FreeJson(urlJson);
206         return HC_ERR_JSON_GET;
207     }
208     FreeJson(urlJson);
209     int32_t ret = SetPreSharedUrlForProof((const char *)presharedUrl->val, &info->proof.preSharedUrl);
210     if (ret != HC_SUCCESS) {
211         LOGE("Failed to set preSharedUrl of proof!");
212         DestroyIdentityInfo(info);
213         return ret;
214     }
215     if (IsDirectAuth(in)) {
216         ret = SetProtocolsForDirectAuth(info);
217         info->IdInfoType = P2P_DIRECT_AUTH;
218     } else {
219         ret = SetProtocolsForPinType(in, info);
220     }
221     if (ret != HC_SUCCESS) {
222         LOGE("Failed to set protocols!");
223         DestroyIdentityInfo(info);
224         return ret;
225     }
226     info->proofType = credentialType;
227     *returnInfo = info;
228     return HC_SUCCESS;
229 }
230 
AuthGeneratePskUsePin(const CJson * in,const Uint8Buff * seed,const char * pinCode,Uint8Buff * sharedSecret)231 static int32_t AuthGeneratePskUsePin(const CJson *in, const Uint8Buff *seed, const char *pinCode,
232     Uint8Buff *sharedSecret)
233 {
234     int32_t osAccountId;
235     if (GetIntFromJson(in, FIELD_OS_ACCOUNT_ID, &osAccountId) != HC_SUCCESS) {
236         LOGE("Failed to get osAccountId!");
237         return HC_ERR_JSON_GET;
238     }
239     Uint8Buff messageBuf = { (uint8_t *)pinCode, (uint32_t)HcStrlen(pinCode) };
240     uint8_t hash[SHA256_LEN] = { 0 };
241     Uint8Buff hashBuf = { hash, sizeof(hash) };
242     int ret = GetLoaderInstance()->sha256(&messageBuf, &hashBuf);
243     if (ret != HC_SUCCESS) {
244         LOGE("sha256 failed, ret:%d", ret);
245         return ret;
246     }
247     KeyParams keyParams = { { hashBuf.val, hashBuf.length, false }, false, osAccountId };
248     return GetLoaderInstance()->computeHmac(&keyParams, seed, sharedSecret);
249 }
250 
251 #ifdef ENABLE_P2P_BIND_LITE_PROTOCOL_CHECK
CheckPinLenForStandardIso(const CJson * in,const char * pinCode)252 static bool CheckPinLenForStandardIso(const CJson *in, const char *pinCode)
253 {
254     int32_t protocolExpandVal = INVALID_PROTOCOL_EXPAND_VALUE;
255     (void)GetIntFromJson(in, FIELD_PROTOCOL_EXPAND, &protocolExpandVal);
256     if (protocolExpandVal != LITE_PROTOCOL_STANDARD_MODE) {
257         LOGI("not standard iso, no need to check.");
258         return true;
259     }
260     return HcStrlen(pinCode) >= PIN_CODE_LEN_LONG;
261 }
262 #endif
263 
GetSharedSecretForPinInIso(const CJson * in,Uint8Buff * sharedSecret)264 static int32_t GetSharedSecretForPinInIso(const CJson *in, Uint8Buff *sharedSecret)
265 {
266     const char *pinCode = GetStringFromJson(in, FIELD_PIN_CODE);
267     if (pinCode == NULL) {
268         LOGE("Failed to get pinCode!");
269         return HC_ERR_JSON_GET;
270     }
271     if (HcStrlen(pinCode) < PIN_CODE_LEN_SHORT) {
272         LOGE("Pin code is too short!");
273         return HC_ERR_INVALID_LEN;
274     }
275 #ifdef ENABLE_P2P_BIND_LITE_PROTOCOL_CHECK
276     if (!CheckPinLenForStandardIso(in, pinCode)) {
277         LOGE("Invalid pin code len!");
278         return HC_ERR_INVALID_LEN;
279     }
280 #endif
281     uint8_t *seedVal = (uint8_t *)HcMalloc(SEED_LEN, 0);
282     if (seedVal == NULL) {
283         LOGE("Failed to alloc seed memory!");
284         return HC_ERR_ALLOC_MEMORY;
285     }
286     Uint8Buff seedBuff = { seedVal, SEED_LEN };
287     int32_t ret = GetByteFromJson(in, FIELD_SEED, seedBuff.val, seedBuff.length);
288     if (ret != HC_SUCCESS) {
289         LOGE("Failed to get seed!");
290         HcFree(seedVal);
291         return HC_ERR_JSON_GET;
292     }
293     uint8_t *pskVal = (uint8_t *)HcMalloc(ISO_PSK_LEN, 0);
294     if (pskVal == NULL) {
295         LOGE("Failed to alloc psk memory!");
296         HcFree(seedVal);
297         return HC_ERR_ALLOC_MEMORY;
298     }
299     sharedSecret->val = pskVal;
300     sharedSecret->length = ISO_PSK_LEN;
301     ret = AuthGeneratePskUsePin(in, &seedBuff, pinCode, sharedSecret);
302     HcFree(seedVal);
303     if (ret != HC_SUCCESS) {
304         LOGE("Failed to generate psk use pin!");
305         FreeBuffData(sharedSecret);
306     }
307     return ret;
308 }
309 
GetSharedSecretForPinInPake(const CJson * in,Uint8Buff * sharedSecret)310 static int32_t GetSharedSecretForPinInPake(const CJson *in, Uint8Buff *sharedSecret)
311 {
312     const char *pinCode = GetStringFromJson(in, FIELD_PIN_CODE);
313     if (pinCode == NULL) {
314         LOGE("Failed to get pinCode!");
315         return HC_ERR_JSON_GET;
316     }
317     uint32_t pinLen = HcStrlen(pinCode);
318     if (pinLen < PIN_CODE_LEN_SHORT) {
319         LOGE("Invalid pin code len!");
320         return HC_ERR_INVALID_LEN;
321     }
322     sharedSecret->val = (uint8_t *)HcMalloc(pinLen, 0);
323     if (sharedSecret->val == NULL) {
324         LOGE("Failed to alloc sharedSecret memory!");
325         return HC_ERR_ALLOC_MEMORY;
326     }
327     if (memcpy_s(sharedSecret->val, pinLen, pinCode, pinLen) != HC_SUCCESS) {
328         LOGE("Failed to memcpy pinCode!");
329         FreeBuffData(sharedSecret);
330         return HC_ERR_MEMORY_COPY;
331     }
332     sharedSecret->length = pinLen;
333     return HC_SUCCESS;
334 }
335 
GetSharedSecretByUrl(const CJson * in,const Uint8Buff * presharedUrl,ProtocolAlgType protocolType,Uint8Buff * sharedSecret)336 static int32_t GetSharedSecretByUrl(
337     const CJson *in, const Uint8Buff *presharedUrl, ProtocolAlgType protocolType, Uint8Buff *sharedSecret)
338 {
339     if (in == NULL || presharedUrl == NULL || sharedSecret == NULL) {
340         LOGE("Invalid input params!");
341         return HC_ERR_INVALID_PARAMS;
342     }
343     int32_t ret;
344     if (protocolType == ALG_ISO) {
345         ret = GetSharedSecretForPinInIso(in, sharedSecret);
346         LOGI("get shared secret for pin in iso result: %d", ret);
347     } else {
348         ret = GetSharedSecretForPinInPake(in, sharedSecret);
349         LOGI("get shared secret for pin in pake result: %d", ret);
350     }
351 
352     return ret;
353 }
354 
GetCredInfoByPeerCert(const CJson * in,const CertInfo * certInfo,IdentityInfo ** returnInfo)355 static int32_t GetCredInfoByPeerCert(const CJson *in, const CertInfo *certInfo, IdentityInfo **returnInfo)
356 {
357     // NOT SUPPORT FOR PIN
358     (void)in;
359     (void)certInfo;
360     (void)returnInfo;
361     return HC_ERR_ALG_FAIL;
362 }
363 
GetSharedSecretByPeerCert(const CJson * in,const CertInfo * peerCertInfo,ProtocolAlgType protocolType,Uint8Buff * sharedSecret)364 static int32_t GetSharedSecretByPeerCert(
365     const CJson *in, const CertInfo *peerCertInfo, ProtocolAlgType protocolType, Uint8Buff *sharedSecret)
366 {
367     // NOT SUPPORT FOR PIN
368     (void)in;
369     (void)peerCertInfo;
370     (void)protocolType;
371     (void)sharedSecret;
372     return HC_ERR_ALG_FAIL;
373 }
374 
375 static const AuthIdentity g_authIdentity = {
376     .getCredInfosByPeerIdentity = GetCredInfosByPeerIdentity,
377     .getCredInfoByPeerUrl = GetCredInfoByPeerUrl,
378     .getSharedSecretByUrl = GetSharedSecretByUrl,
379     .getCredInfoByPeerCert = GetCredInfoByPeerCert,
380     .getSharedSecretByPeerCert = GetSharedSecretByPeerCert,
381 };
382 
GetPinAuthIdentity(void)383 const AuthIdentity *GetPinAuthIdentity(void)
384 {
385     return &g_authIdentity;
386 }