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 
SetProtocolsToIdentityInfo(IdentityInfo * info)21 static int32_t SetProtocolsToIdentityInfo(IdentityInfo *info)
22 {
23     ProtocolEntity *ecSpekeEntity = (ProtocolEntity *)HcMalloc(sizeof(ProtocolEntity), 0);
24     if (ecSpekeEntity == NULL) {
25         LOGE("Failed to alloc memory for ec speke entity!");
26         return HC_ERR_ALLOC_MEMORY;
27     }
28     ecSpekeEntity->protocolType = ALG_EC_SPEKE;
29     ecSpekeEntity->expandProcessCmds = 0;
30     info->protocolVec.pushBack(&info->protocolVec, (const ProtocolEntity **)&ecSpekeEntity);
31 
32     return HC_SUCCESS;
33 }
34 
CombineQueryCredentialParams(const CJson * in,CJson * out)35 static int32_t CombineQueryCredentialParams(const CJson *in, CJson *out)
36 {
37     int32_t osAccountId = INVALID_OS_ACCOUNT;
38     if (GetIntFromJson(in, FIELD_OS_ACCOUNT_ID, &osAccountId) != HC_SUCCESS) {
39         LOGE("Failed to get osAccountId from context!");
40         return HC_ERR_JSON_GET;
41     }
42     const char *peerConnDeviceId = GetStringFromJson(in, FIELD_PEER_CONN_DEVICE_ID);
43     if (peerConnDeviceId == NULL) {
44         LOGE("Failed to get peerConnDeviceId from context, need peerConnDeviceId!");
45         return HC_ERR_JSON_GET;
46     }
47     int32_t acquireType = ACQUIRE_TYPE_INVALID;
48     if (GetIntFromJson(in, FIELD_ACQURIED_TYPE, &acquireType) != HC_SUCCESS) {
49         LOGE("Failed to get acquireType from context!");
50         return HC_ERR_JSON_GET;
51     }
52     if (acquireType != P2P_BIND) {
53         LOGE("acquireType invalid! only P2P_BIND is allowed now!");
54         return HC_ERR_INVALID_PARAMS;
55     }
56     if (AddIntToJson(out, FIELD_OS_ACCOUNT_ID, osAccountId) != HC_SUCCESS) {
57         LOGE("add osAccountId to json error!");
58         return HC_ERR_JSON_ADD;
59     }
60     if (AddIntToJson(out, FIELD_ACQURIED_TYPE, acquireType) != HC_SUCCESS) {
61         LOGE("add acquireType to json error!");
62         return HC_ERR_JSON_ADD;
63     }
64     if (AddIntToJson(out, FIELD_CRED_OP_FLAG, RETURN_FLAG_DEFAULT) != HC_SUCCESS) {
65         LOGE("add flag to json error!");
66         return HC_ERR_JSON_ADD;
67     }
68     if (AddStringToJson(out, FIELD_DEVICE_ID, peerConnDeviceId) != HC_SUCCESS) {
69         LOGE("add device id to json error!");
70         return HC_ERR_JSON_ADD;
71     }
72     return HC_SUCCESS;
73 }
74 
IsPeerDevicePublicKeyExist(const CJson * in)75 static int32_t IsPeerDevicePublicKeyExist(const CJson *in)
76 {
77     CJson *paramsJson = CreateJson();
78     if (paramsJson == NULL) {
79         LOGE("alloc memory error!");
80         return HC_ERR_ALLOC_MEMORY;
81     }
82     int32_t ret = CombineQueryCredentialParams(in, paramsJson);
83     if (ret != HC_SUCCESS) {
84         LOGE("Prepare query credential parmaters return error!");
85         FreeJson(paramsJson);
86         return ret;
87     }
88     const CredentialOperator *credOperator = GetCredentialOperator();
89     if (credOperator == NULL) {
90         LOGE("credOperator is null!");
91         FreeJson(paramsJson);
92         return HC_ERR_NOT_SUPPORT;
93     }
94     char *requestParams = PackJsonToString(paramsJson);
95     FreeJson(paramsJson);
96     if (requestParams == NULL) {
97         LOGE("Failed to pack query credentail params json to string!");
98         return HC_ERR_PACKAGE_JSON_TO_STRING_FAIL;
99     }
100     ret = credOperator->queryCredential(requestParams, NULL);
101     FreeJsonString(requestParams);
102     return ret;
103 }
104 
GetCredInfosByPeerIdentity(const CJson * in,IdentityInfoVec * vec)105 static int32_t GetCredInfosByPeerIdentity(const CJson *in, IdentityInfoVec *vec)
106 {
107     int32_t keyType = KEY_TYPE_ASYM;
108     (void)GetIntFromJson(in, FIELD_KEY_TYPE, &keyType);
109 
110     int32_t ret = IsPeerDevicePublicKeyExist(in);
111     if (ret != HC_SUCCESS) {
112         LOGE("Failed to get peer device public key!");
113         return ret;
114     }
115     CJson *urlJson = CreateCredUrlJson(PRE_SHARED, keyType, TRUST_TYPE_P2P);
116     if (!urlJson) {
117         LOGE("Failed to create CredUrlJson info!");
118         return HC_ERR_ALLOC_MEMORY;
119     }
120     if (AddBoolToJson(urlJson, FIELD_IS_DIRECT_AUTH, true) != HC_SUCCESS) {
121         LOGE("Failed to add isDirectAuth to preshared url!");
122         FreeJson(urlJson);
123         return HC_ERR_JSON_ADD;
124     } else {
125         LOGI("add isDirectAuth:true into urlJson!");
126     }
127     char *urlStr = PackJsonToString(urlJson);
128     FreeJson(urlJson);
129     if (urlStr == NULL) {
130         LOGE("Failed to pack url json to string!");
131         return HC_ERR_PACKAGE_JSON_TO_STRING_FAIL;
132     }
133     IdentityInfo *info = CreateIdentityInfo();
134     if (info == NULL) {
135         LOGE("Failed to create identity info!");
136         FreeJsonString(urlStr);
137         return HC_ERR_ALLOC_MEMORY;
138     }
139     ret = SetPreSharedUrlForProof(urlStr, &info->proof.preSharedUrl);
140     FreeJsonString(urlStr);
141     if (ret != HC_SUCCESS) {
142         LOGE("Failed to set preSharedUrl of proof!");
143         DestroyIdentityInfo(info);
144         return ret;
145     }
146     ret = SetProtocolsToIdentityInfo(info);
147     if (ret != HC_SUCCESS) {
148         LOGE("Failed to set protocols!");
149         DestroyIdentityInfo(info);
150         return ret;
151     }
152     info->proofType = PRE_SHARED;
153     info->IdInfoType = P2P_DIRECT_AUTH;
154     vec->pushBack(vec, (const IdentityInfo **)&info);
155     return HC_SUCCESS;
156 }
157 
GetCredInfoByPeerUrl(const CJson * in,const Uint8Buff * presharedUrl,IdentityInfo ** returnInfo)158 static int32_t GetCredInfoByPeerUrl(const CJson *in, const Uint8Buff *presharedUrl, IdentityInfo **returnInfo)
159 {
160     if (in == NULL || presharedUrl == NULL || returnInfo == NULL) {
161         LOGE("Invalid input params!");
162         return HC_ERR_INVALID_PARAMS;
163     }
164     IdentityInfo *info = CreateIdentityInfo();
165     if (info == NULL) {
166         LOGE("Failed to create identity info!");
167         return HC_ERR_ALLOC_MEMORY;
168     }
169     int32_t ret = SetPreSharedUrlForProof((const char *)presharedUrl->val, &info->proof.preSharedUrl);
170     if (ret != HC_SUCCESS) {
171         LOGE("Failed to set preSharedUrl of proof!");
172         DestroyIdentityInfo(info);
173         return ret;
174     }
175     ret = SetProtocolsToIdentityInfo(info);
176     if (ret != HC_SUCCESS) {
177         LOGE("Failed to set protocols!");
178         DestroyIdentityInfo(info);
179         return ret;
180     }
181     info->proofType = PRE_SHARED;
182     info->IdInfoType = P2P_DIRECT_AUTH;
183     *returnInfo = info;
184     return HC_SUCCESS;
185 }
186 
187 /**
188  * @brief compute shared key alias
189  *
190  * @param osAccountId
191  * @param selfAuthId self device udid
192  * @param peerAuthId  peer device udid
193  * @param sharedKeyAlias
194  * @return int32_t
195  */
ComputeAndSaveDirectAuthPsk(int32_t osAccountId,const char * selfAuthId,const char * peerAuthId,const char * peerServiceType,const Uint8Buff * sharedKeyAlias)196 static int32_t ComputeAndSaveDirectAuthPsk(int32_t osAccountId, const char *selfAuthId, const char *peerAuthId,
197     const char *peerServiceType, const Uint8Buff *sharedKeyAlias)
198 {
199     Uint8Buff selfAuthIdBuff = { (uint8_t *)selfAuthId, HcStrlen(selfAuthId) };
200     Uint8Buff pkgNameBuff = { (uint8_t *)DEFAULT_PACKAGE_NAME, HcStrlen(DEFAULT_PACKAGE_NAME) };
201     Uint8Buff serviceTypeBuff = { (uint8_t *)DEFAULT_SERVICE_TYPE, HcStrlen(DEFAULT_SERVICE_TYPE) };
202     KeyAliasType keyType = KEY_ALIAS_P2P_AUTH;
203     uint8_t selfKeyAliasVal[PAKE_KEY_ALIAS_LEN] = { 0 };
204     Uint8Buff selfKeyAlias = { selfKeyAliasVal, PAKE_KEY_ALIAS_LEN };
205     int32_t ret = GenerateKeyAlias(&pkgNameBuff, &serviceTypeBuff, keyType, &selfAuthIdBuff, &selfKeyAlias);
206     if (ret != HC_SUCCESS) {
207         LOGE("Failed to generate self key alias!");
208         return ret;
209     }
210     LOGI("selfKeyAlias: %x %x %x %x****.", selfKeyAlias.val[DEV_AUTH_ZERO], selfKeyAlias.val[DEV_AUTH_ONE],
211         selfKeyAlias.val[DEV_AUTH_TWO], selfKeyAlias.val[DEV_AUTH_THREE]);
212 
213     Uint8Buff peerServiceTypeBuff = { (uint8_t *)peerServiceType, HcStrlen(peerServiceType) };
214     KeyAliasType keyTypePeer = KEY_ALIAS_P2P_AUTH;
215     Uint8Buff peerAuthIdBuff = { (uint8_t *)peerAuthId, HcStrlen(peerAuthId) };
216     uint8_t peerKeyAliasVal[PAKE_KEY_ALIAS_LEN] = { 0 };
217     Uint8Buff peerKeyAlias = { peerKeyAliasVal, PAKE_KEY_ALIAS_LEN };
218     ret = GenerateKeyAlias(&pkgNameBuff, &peerServiceTypeBuff, keyTypePeer, &peerAuthIdBuff, &peerKeyAlias);
219     if (ret != HC_SUCCESS) {
220         LOGE("Failed to generate peer key alias!");
221         return ret;
222     }
223     LOGI("peerKeyAlias: %x %x %x %x****.", peerKeyAlias.val[DEV_AUTH_ZERO], peerKeyAlias.val[DEV_AUTH_ONE],
224         peerKeyAlias.val[DEV_AUTH_TWO], peerKeyAlias.val[DEV_AUTH_THREE]);
225 
226     ret = GetLoaderInstance()->checkKeyExist(&selfKeyAlias, false, osAccountId);
227     if (ret != HC_SUCCESS) {
228         LOGE("self auth keyPair not exist!");
229         return ret;
230     }
231     ret = GetLoaderInstance()->checkKeyExist(&peerKeyAlias, false, osAccountId);
232     if (ret != HC_SUCCESS) {
233         LOGE("peer auth pubKey not exist!");
234         return ret;
235     }
236 
237     KeyParams selfKeyParams = { { selfKeyAlias.val, selfKeyAlias.length, true }, false, osAccountId };
238     KeyBuff peerKeyBuff = { peerKeyAlias.val, peerKeyAlias.length, true };
239     return GetLoaderInstance()->agreeSharedSecretWithStorage(
240         &selfKeyParams, &peerKeyBuff, ED25519, PAKE_PSK_LEN, sharedKeyAlias);
241 }
242 
GetDirectAuthPskAliasCreateIfNeeded(const CJson * in,Uint8Buff * pskKeyAlias)243 static int32_t GetDirectAuthPskAliasCreateIfNeeded(const CJson *in, Uint8Buff *pskKeyAlias)
244 {
245     int32_t osAccountId = INVALID_OS_ACCOUNT;
246     if (GetIntFromJson(in, FIELD_OS_ACCOUNT_ID, &osAccountId) != HC_SUCCESS) {
247         LOGE("Failed to get osAccountId!");
248         return HC_ERR_JSON_GET;
249     }
250     const char *selfAuthId = GetStringFromJson(in, FIELD_AUTH_ID);
251     if (selfAuthId == NULL) {
252         LOGE("get authId from context fail.");
253         return HC_ERR_JSON_GET;
254     }
255     const char *peerAuthId = GetStringFromJson(in, FIELD_PEER_CONN_DEVICE_ID);
256     if (peerAuthId == NULL) {
257         LOGE("get peerConnDeviceId from json fail.");
258         return HC_ERR_JSON_GET;
259     }
260     const char *peerServieType = GetStringFromJson(in, FIELD_SERVICE_TYPE);
261     if (peerServieType == NULL) {
262         LOGI("get serviceType from json fail, replace by default");
263         peerServieType = DEFAULT_SERVICE_TYPE;
264     }
265     Uint8Buff pkgNameBuff = { (uint8_t *)DEFAULT_PACKAGE_NAME, HcStrlen(DEFAULT_PACKAGE_NAME) };
266     Uint8Buff serviceTypeBuff = { (uint8_t *)peerServieType, HcStrlen(peerServieType) };
267     Uint8Buff peerAuthIdBuff = { (uint8_t *)peerAuthId, HcStrlen(peerAuthId) };
268     int32_t ret = GenerateKeyAlias(&pkgNameBuff, &serviceTypeBuff, KEY_ALIAS_PSK, &peerAuthIdBuff, pskKeyAlias);
269     if (ret != HC_SUCCESS) {
270         LOGE("Failed to generate psk key alias!");
271         return ret;
272     }
273     LOGI("psk alias: %x %x %x %x****.", pskKeyAlias->val[DEV_AUTH_ZERO], pskKeyAlias->val[DEV_AUTH_ONE],
274         pskKeyAlias->val[DEV_AUTH_TWO], pskKeyAlias->val[DEV_AUTH_THREE]);
275     ret = GetLoaderInstance()->checkKeyExist(pskKeyAlias, false, osAccountId);
276     if (ret != HC_SUCCESS) {
277         ret = ComputeAndSaveDirectAuthPsk(osAccountId, selfAuthId, peerAuthId, peerServieType, pskKeyAlias);
278     }
279     return ret;
280 }
281 
GetSharedSecretByUrl(const CJson * in,const Uint8Buff * presharedUrl,ProtocolAlgType protocolType,Uint8Buff * sharedSecret)282 static int32_t GetSharedSecretByUrl(
283     const CJson *in, const Uint8Buff *presharedUrl, ProtocolAlgType protocolType, Uint8Buff *sharedSecret)
284 {
285     (void)protocolType;
286     if (in == NULL || presharedUrl == NULL || sharedSecret == NULL) {
287         LOGE("Invalid input params!");
288         return HC_ERR_INVALID_PARAMS;
289     }
290     int32_t osAccountId;
291     if (GetIntFromJson(in, FIELD_OS_ACCOUNT_ID, &osAccountId) != HC_SUCCESS) {
292         LOGE("Failed to get osAccountId!");
293         return HC_ERR_JSON_GET;
294     }
295     uint8_t pskKeyAliasVal[PAKE_KEY_ALIAS_LEN] = { 0 };
296     Uint8Buff pskKeyAlias = { pskKeyAliasVal, PAKE_KEY_ALIAS_LEN };
297     int32_t ret = GetDirectAuthPskAliasCreateIfNeeded(in, &pskKeyAlias);
298     if (ret != HC_SUCCESS) {
299         LOGE("Failed to generate key alias for psk!");
300         return ret;
301     }
302     uint8_t nonceVal[PAKE_NONCE_LEN] = { 0 };
303     Uint8Buff nonceBuff = { nonceVal, PAKE_NONCE_LEN };
304     if (GetByteFromJson(in, FIELD_NONCE, nonceBuff.val, nonceBuff.length) != HC_SUCCESS) {
305         LOGE("Failed to get nonce!");
306         return HC_ERR_JSON_GET;
307     }
308     uint8_t pskVal[PAKE_PSK_LEN] = { 0 };
309     Uint8Buff pskBuff = { pskVal, PAKE_PSK_LEN };
310     Uint8Buff keyInfo = { (uint8_t *)TMP_AUTH_KEY_FACTOR, HcStrlen(TMP_AUTH_KEY_FACTOR) };
311     KeyParams keyAliasParams = { { pskKeyAlias.val, pskKeyAlias.length, true }, false, osAccountId };
312     ret = GetLoaderInstance()->computeHkdf(&keyAliasParams, &nonceBuff, &keyInfo, &pskBuff);
313     if (ret != HC_SUCCESS) {
314         LOGE("Failed to compute hkdf for psk!");
315         return ret;
316     }
317     ret = ConvertPsk(&pskBuff, sharedSecret);
318     if (ret != HC_SUCCESS) {
319         LOGE("Failed to convert psk!");
320     }
321     return ret;
322 }
323 
GetCredInfoByPeerCert(const CJson * in,const CertInfo * certInfo,IdentityInfo ** returnInfo)324 static int32_t GetCredInfoByPeerCert(const CJson *in, const CertInfo *certInfo, IdentityInfo **returnInfo)
325 {
326     // NOT SUPPORT FOR P2P AUTH
327     (void)in;
328     (void)certInfo;
329     (void)returnInfo;
330     return HC_ERR_ALG_FAIL;
331 }
332 
GetSharedSecretByPeerCert(const CJson * in,const CertInfo * peerCertInfo,ProtocolAlgType protocolType,Uint8Buff * sharedSecret)333 static int32_t GetSharedSecretByPeerCert(
334     const CJson *in, const CertInfo *peerCertInfo, ProtocolAlgType protocolType, Uint8Buff *sharedSecret)
335 {
336     // NOT SUPPORT P2P AUTH
337     (void)in;
338     (void)peerCertInfo;
339     (void)protocolType;
340     (void)sharedSecret;
341     return HC_ERR_ALG_FAIL;
342 }
343 
344 static const AuthIdentity g_authIdentity = {
345     .getCredInfosByPeerIdentity = GetCredInfosByPeerIdentity,
346     .getCredInfoByPeerUrl = GetCredInfoByPeerUrl,
347     .getSharedSecretByUrl = GetSharedSecretByUrl,
348     .getCredInfoByPeerCert = GetCredInfoByPeerCert,
349     .getSharedSecretByPeerCert = GetSharedSecretByPeerCert,
350 };
351 
GetP2pAuthIdentity(void)352 const AuthIdentity *GetP2pAuthIdentity(void)
353 {
354     return &g_authIdentity;
355 }