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 <cstring>
17 #include <iostream>
18 #include <vector>
19 #include <string>
20
21 #include <openssl/ssl.h>
22
23 #include "net_ssl.h"
24 #include "net_ssl_c.h"
25 #include "net_ssl_c_type.h"
26 #include "securec.h"
27 #include "netstack_log.h"
28 #include "net_ssl_verify_cert.h"
29 #include "net_manager_constants.h"
30 #include "net_conn_client.h"
31
SwitchToCertBlob(const struct NetStack_CertBlob cert)32 struct OHOS::NetStack::Ssl::CertBlob SwitchToCertBlob(const struct NetStack_CertBlob cert)
33 {
34 OHOS::NetStack::Ssl::CertBlob cb;
35 switch (cert.type) {
36 case NETSTACK_CERT_TYPE_PEM:
37 cb.type = OHOS::NetStack::Ssl::CertType::CERT_TYPE_PEM;
38 break;
39 case NETSTACK_CERT_TYPE_DER:
40 cb.type = OHOS::NetStack::Ssl::CertType::CERT_TYPE_DER;
41 break;
42 case NETSTACK_CERT_TYPE_INVALID:
43 cb.type = OHOS::NetStack::Ssl::CertType::CERT_TYPE_MAX;
44 break;
45 default:
46 break;
47 }
48 cb.size = cert.size;
49 cb.data = cert.data;
50 return cb;
51 }
52
VerifyCert_With_RootCa(const struct NetStack_CertBlob * cert)53 uint32_t VerifyCert_With_RootCa(const struct NetStack_CertBlob *cert)
54 {
55 uint32_t verifyResult = X509_V_ERR_UNSPECIFIED;
56 OHOS::NetStack::Ssl::CertBlob cb = SwitchToCertBlob(*cert);
57 verifyResult = OHOS::NetStack::Ssl::NetStackVerifyCertification(&cb);
58 return verifyResult;
59 }
60
VerifyCert_With_DesignatedCa(const struct NetStack_CertBlob * cert,const struct NetStack_CertBlob * caCert)61 uint32_t VerifyCert_With_DesignatedCa(const struct NetStack_CertBlob *cert, const struct NetStack_CertBlob *caCert)
62 {
63 uint32_t verifyResult = X509_V_ERR_UNSPECIFIED;
64 OHOS::NetStack::Ssl::CertBlob cb = SwitchToCertBlob(*cert);
65 OHOS::NetStack::Ssl::CertBlob caCb = SwitchToCertBlob(*caCert);
66 verifyResult = OHOS::NetStack::Ssl::NetStackVerifyCertification(&cb, &caCb);
67 return verifyResult;
68 }
69
OH_NetStack_CertVerification(const struct NetStack_CertBlob * cert,const struct NetStack_CertBlob * caCert)70 uint32_t OH_NetStack_CertVerification(const struct NetStack_CertBlob *cert, const struct NetStack_CertBlob *caCert)
71 {
72 if (cert == nullptr) {
73 return X509_V_ERR_INVALID_CALL;
74 }
75 if (caCert == nullptr) {
76 return VerifyCert_With_RootCa(cert);
77 } else {
78 return VerifyCert_With_DesignatedCa(cert, caCert);
79 }
80 }
81
OH_NetStack_GetPinSetForHostName(const char * hostname,NetStack_CertificatePinning * pin)82 int32_t OH_NetStack_GetPinSetForHostName(const char *hostname, NetStack_CertificatePinning *pin)
83 {
84 if (hostname == nullptr || pin == nullptr) {
85 NETSTACK_LOGE("OH_NetStack_GetPinSetForHostName received invalid parameters");
86 return OHOS::NetManagerStandard::NETMANAGER_ERR_PARAMETER_ERROR;
87 }
88
89 std::string innerHostname = std::string(hostname);
90 std::string innerPins;
91
92 int32_t ret = OHOS::NetManagerStandard::NetConnClient::GetInstance().GetPinSetForHostName(innerHostname, innerPins);
93 if (ret != OHOS::NetManagerStandard::NETMANAGER_SUCCESS) {
94 return ret;
95 }
96
97 if (innerPins.length() <= 0) {
98 pin->hashAlgorithm = NetStack_HashAlgorithm::SHA_256;
99 pin->kind = NetStack_CertificatePinningKind::PUBLIC_KEY;
100 pin->publicKeyHash = nullptr;
101 return OHOS::NetManagerStandard::NETMANAGER_SUCCESS;
102 }
103
104 size_t size = innerPins.length() + 1;
105 char *key = (char *)malloc(size);
106 if (key == nullptr) {
107 NETSTACK_LOGE("OH_NetStack_GetPinSetForHostName malloc failed");
108 return OHOS::NetStack::Ssl::SslErrorCode::SSL_X509_V_ERR_OUT_OF_MEMORY;
109 }
110
111 if (strcpy_s(key, size, innerPins.c_str()) != 0) {
112 free(key);
113 NETSTACK_LOGE("OH_NetStack_GetPinSetForHostName string copy failed");
114 return OHOS::NetStack::Ssl::SslErrorCode::SSL_X509_V_ERR_OUT_OF_MEMORY;
115 }
116 pin->hashAlgorithm = NetStack_HashAlgorithm::SHA_256;
117 pin->kind = NetStack_CertificatePinningKind::PUBLIC_KEY;
118 pin->publicKeyHash = key;
119
120 return OHOS::NetManagerStandard::NETMANAGER_SUCCESS;
121 }
122
OH_NetStack_GetCertificatesForHostName(const char * hostname,NetStack_Certificates * certs)123 int32_t OH_NetStack_GetCertificatesForHostName(const char *hostname, NetStack_Certificates *certs)
124 {
125 if (hostname == nullptr || certs == nullptr) {
126 NETSTACK_LOGE("OH_NetStack_GetCertificatesForHostName received invalid parameters");
127 return OHOS::NetManagerStandard::NETMANAGER_ERR_PARAMETER_ERROR;
128 }
129
130 std::string innerHostname = std::string(hostname);
131 std::vector<std::string> innerCerts;
132
133 int32_t ret = OHOS::NetManagerStandard::NetConnClient::GetInstance()
134 .GetTrustAnchorsForHostName(innerHostname, innerCerts);
135 if (ret != OHOS::NetManagerStandard::NETMANAGER_SUCCESS) {
136 return ret;
137 }
138
139 size_t innerCertsLength = innerCerts.size();
140 if (innerCertsLength <= 0) {
141 certs->length = 0;
142 certs->content = nullptr;
143 return OHOS::NetManagerStandard::NETMANAGER_SUCCESS;
144 }
145
146 size_t contentPtrSize = innerCertsLength * sizeof(char *);
147 size_t totalMallocSize = contentPtrSize;
148 for (size_t i = 0; i < innerCertsLength; ++i) {
149 totalMallocSize += innerCerts[i].size() + 1;
150 }
151 char *ptr = (char *)malloc(totalMallocSize);
152 if (ptr == nullptr) {
153 NETSTACK_LOGE("OH_NetStack_GetCertificatesForHostName malloc failed");
154 return OHOS::NetStack::Ssl::SslErrorCode::SSL_X509_V_ERR_OUT_OF_MEMORY;
155 }
156 char **contentPtr = reinterpret_cast<char **>(ptr);
157 char *certPtr = ptr + contentPtrSize;
158
159 for (size_t i = 0; i < innerCertsLength; ++i) {
160 size_t certLen = innerCerts[i].size() + 1;
161 if (strcpy_s(certPtr, certLen, innerCerts[i].c_str()) != 0) {
162 free(ptr);
163 NETSTACK_LOGE("OH_NetStack_GetCertificatesForHostName string copy failed");
164 return OHOS::NetStack::Ssl::SslErrorCode::SSL_X509_V_ERR_OUT_OF_MEMORY;
165 }
166 contentPtr[i] = certPtr;
167 certPtr += certLen;
168 }
169
170 certs->length = innerCertsLength;
171 certs->content = contentPtr;
172 return OHOS::NetManagerStandard::NETMANAGER_SUCCESS;
173 }
174
OH_Netstack_DestroyCertificatesContent(NetStack_Certificates * certs)175 void OH_Netstack_DestroyCertificatesContent(NetStack_Certificates *certs)
176 {
177 if (certs == nullptr) {
178 NETSTACK_LOGE("OH_Netstack_DestroyCertificatesContent received invalid parameters");
179 return;
180 }
181
182 if (certs->content == nullptr) {
183 return;
184 }
185
186 free(certs->content);
187 certs->content = nullptr;
188 certs->length = 0;
189 }
190