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 "creds_manager.h"
17
18#include "hc_log.h"
19
20static bool IsDirectAuth(const CJson *context)
21{
22    bool isDirectAuth = false;
23    (void)GetBoolFromJson(context, FIELD_IS_DIRECT_AUTH, &isDirectAuth);
24    return isDirectAuth;
25}
26
27static bool IsDeviceLevelAuth(const CJson *context)
28{
29    bool isDeviceLevel = false;
30    (void)GetBoolFromJson(context, FIELD_IS_DEVICE_LEVEL, &isDeviceLevel);
31    return isDeviceLevel;
32}
33
34static bool IsPinAuth(const CJson *context, const Uint8Buff *presharedUrl)
35{
36    const char *pinCode = GetStringFromJson(context, FIELD_PIN_CODE);
37    if (pinCode != NULL) {
38        return true;
39    }
40
41    CJson *urlJson = CreateJsonFromString((const char *)presharedUrl->val);
42    if (urlJson == NULL) {
43        LOGE("Failed to create url json!");
44        return false;
45    }
46    int32_t keyType = 0;
47    if (GetIntFromJson(urlJson, PRESHARED_URL_KEY_TYPE, &keyType) != HC_SUCCESS) {
48        LOGE("Failed to get trust type!");
49        FreeJson(urlJson);
50        return false;
51    }
52
53    int32_t trustType = 0;
54    if (GetIntFromJson(urlJson, PRESHARED_URL_TRUST_TYPE, &trustType) != HC_SUCCESS) {
55        LOGE("Failed to get trust type!");
56        FreeJson(urlJson);
57        return false;
58    }
59    FreeJson(urlJson);
60
61    return (keyType == KEY_TYPE_SYM) && (trustType == TRUST_TYPE_PIN);
62}
63
64static const AuthIdentity *getAuthIdentity(const CJson *in, const Uint8Buff *presharedUrl)
65{
66    AuthIdentityType identityType = AUTH_IDENTITY_TYPE_INVALID;
67
68    if (IsPinAuth(in, presharedUrl)) {
69        identityType = AUTH_IDENTITY_TYPE_PIN;
70    } else {
71        if (IsDirectAuth(in)) {
72            identityType = AUTH_IDENTITY_TYPE_P2P;
73        } else {
74            identityType = AUTH_IDENTITY_TYPE_GROUP;
75        }
76    }
77    LOGD("AuthIdentityType: %d", identityType);
78
79    if (identityType == AUTH_IDENTITY_TYPE_INVALID) {
80        LOGE("invalid AuthIdentityType !");
81        return NULL;
82    }
83    return GetAuthIdentityByType(identityType);
84}
85
86int32_t GetCredInfosByPeerIdentity(CJson *in, IdentityInfoVec *vec)
87{
88    if (in == NULL || vec == NULL) {
89        LOGE("Invalid input params!");
90        return HC_ERR_INVALID_PARAMS;
91    }
92    AuthIdentityType identityType = AUTH_IDENTITY_TYPE_INVALID;
93    const char *pinCode = GetStringFromJson(in, FIELD_PIN_CODE);
94    if (pinCode != NULL) {
95        identityType = AUTH_IDENTITY_TYPE_PIN;
96    } else {
97        if (IsDirectAuth(in)) {
98            identityType = AUTH_IDENTITY_TYPE_P2P;
99        } else {
100            identityType = AUTH_IDENTITY_TYPE_GROUP;
101        }
102    }
103    if (identityType == AUTH_IDENTITY_TYPE_INVALID) {
104        LOGE("invalid AuthIdentityType !");
105        return HC_ERR_INVALID_PARAMS;
106    }
107    LOGD("AuthIdentityType: %d", identityType);
108    const AuthIdentity *authIdentity = GetAuthIdentityByType(identityType);
109    if (authIdentity == NULL) {
110        LOGI("getAuthIdentity failed.");
111        return HC_ERR_INVALID_PARAMS;
112    }
113    int32_t ret = authIdentity->getCredInfosByPeerIdentity(in, vec);
114    if (!IsDeviceLevelAuth(in) || identityType != AUTH_IDENTITY_TYPE_GROUP) {
115        return ret;
116    }
117    // Device level auth also need to try auth with the direct auth identityInfo
118    uint32_t identityCount = HC_VECTOR_SIZE(vec);
119    authIdentity = GetAuthIdentityByType(AUTH_IDENTITY_TYPE_P2P);
120    if (authIdentity == NULL) {
121        LOGE("get p2p auth identity failed!");
122        return ret;
123    }
124    // Device level auth comes from old api: authDevice, it's context
125    // does not contain acquireType, so we need add it into context here.
126    if (AddIntToJson(in, FIELD_ACQURIED_TYPE, P2P_BIND) != HC_SUCCESS) {
127        LOGE("Device level auth, add acquire type to context failed!");
128        return ret;
129    }
130    int32_t res = authIdentity->getCredInfosByPeerIdentity(in, vec);
131    if (res != HC_SUCCESS && (identityCount > 0)) {
132        return HC_SUCCESS;
133    }
134    return res;
135}
136
137int32_t GetCredInfoByPeerUrl(const CJson *in, const Uint8Buff *presharedUrl, IdentityInfo **returnInfo)
138{
139    if (in == NULL || presharedUrl == NULL || returnInfo == NULL) {
140        LOGE("Invalid input params!");
141        return HC_ERR_INVALID_PARAMS;
142    }
143
144    const AuthIdentity *authIdentity = getAuthIdentity(in, presharedUrl);
145    if (!authIdentity) {
146        LOGI("getAuthIdentity failed.");
147        return HC_ERR_INVALID_PARAMS;
148    }
149
150    return authIdentity->getCredInfoByPeerUrl(in, presharedUrl, returnInfo);
151}
152
153int32_t GetSharedSecretByUrl(
154    const CJson *in, const Uint8Buff *presharedUrl, ProtocolAlgType protocolType, Uint8Buff *sharedSecret)
155{
156    if (in == NULL || presharedUrl == NULL || sharedSecret == NULL) {
157        LOGE("Invalid input params!");
158        return HC_ERR_INVALID_PARAMS;
159    }
160
161#ifdef DEV_AUTH_FUNC_TEST // Add for coverage test
162    const AuthIdentity *authIdentityTest = GetAuthIdentityByType(AUTH_IDENTITY_TYPE_P2P);
163    if (authIdentityTest == NULL) {
164        return HC_ERR_INVALID_PARAMS;
165    }
166    authIdentityTest->getSharedSecretByUrl(in, presharedUrl, protocolType, sharedSecret);
167
168    authIdentityTest = GetAuthIdentityByType(AUTH_IDENTITY_TYPE_PIN);
169    if (authIdentityTest == NULL) {
170        return HC_ERR_INVALID_PARAMS;
171    }
172    authIdentityTest->getSharedSecretByUrl(in, presharedUrl, protocolType, sharedSecret);
173#endif
174
175    const AuthIdentity *authIdentity = getAuthIdentity(in, presharedUrl);
176    if (!authIdentity) {
177        LOGI("getAuthIdentity failed.");
178        return HC_ERR_INVALID_PARAMS;
179    }
180
181    return authIdentity->getSharedSecretByUrl(in, presharedUrl, protocolType, sharedSecret);
182}
183
184int32_t GetCredInfoByPeerCert(const CJson *in, const CertInfo *certInfo, IdentityInfo **returnInfo)
185{
186    if (in == NULL || certInfo == NULL || returnInfo == NULL) {
187        LOGE("Invalid input params!");
188        return HC_ERR_INVALID_PARAMS;
189    }
190
191#ifdef DEV_AUTH_FUNC_TEST // Add for coverage test
192    const AuthIdentity *authIdentityTest = GetAuthIdentityByType(AUTH_IDENTITY_TYPE_P2P);
193    if (authIdentityTest == NULL) {
194        return HC_ERR_INVALID_PARAMS;
195    }
196    authIdentityTest->getCredInfoByPeerCert(in, certInfo, returnInfo);
197
198    authIdentityTest = GetAuthIdentityByType(AUTH_IDENTITY_TYPE_PIN);
199    if (authIdentityTest == NULL) {
200        return HC_ERR_INVALID_PARAMS;
201    }
202    authIdentityTest->getCredInfoByPeerCert(in, certInfo, returnInfo);
203#endif
204
205    const AuthIdentity *authIdentity = GetAuthIdentityByType(AUTH_IDENTITY_TYPE_GROUP);
206    if (authIdentity == NULL) {
207        return HC_ERR_INVALID_PARAMS;
208    }
209    return authIdentity->getCredInfoByPeerCert(in, certInfo, returnInfo);
210}
211
212int32_t GetSharedSecretByPeerCert(
213    const CJson *in, const CertInfo *peerCertInfo, ProtocolAlgType protocolType, Uint8Buff *sharedSecret)
214{
215    if (in == NULL || peerCertInfo == NULL || sharedSecret == NULL) {
216        LOGE("Invalid input params!");
217        return HC_ERR_INVALID_PARAMS;
218    }
219
220#ifdef DEV_AUTH_FUNC_TEST // Add for coverage test
221    const AuthIdentity *authIdentityTest = GetAuthIdentityByType(AUTH_IDENTITY_TYPE_P2P);
222    if (authIdentityTest == NULL) {
223        return HC_ERR_INVALID_PARAMS;
224    }
225    authIdentityTest->getSharedSecretByPeerCert(in, peerCertInfo, protocolType, sharedSecret);
226
227    authIdentityTest = GetAuthIdentityByType(AUTH_IDENTITY_TYPE_PIN);
228    if (authIdentityTest == NULL) {
229        return HC_ERR_INVALID_PARAMS;
230    }
231    authIdentityTest->getSharedSecretByPeerCert(in, peerCertInfo, protocolType, sharedSecret);
232#endif
233
234    const AuthIdentity *authIdentity = GetAuthIdentityByType(AUTH_IDENTITY_TYPE_GROUP);
235    if (authIdentity == NULL) {
236        return HC_ERR_INVALID_PARAMS;
237    }
238    return authIdentity->getSharedSecretByPeerCert(in, peerCertInfo, protocolType, sharedSecret);
239}