1 /*
2 * Copyright (c) 2022 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 "tls_context.h"
17
18 #include <cinttypes>
19 #include <string>
20 #include <openssl/ssl.h>
21 #include <openssl/x509_vfy.h>
22 #include <dirent.h>
23
24 #include "netstack_log.h"
25 #include "netstack_common_utils.h"
26 #include "tls_utils.h"
27 #ifdef HAS_NETMANAGER_BASE
28 #include "net_conn_client.h"
29 #endif
30
31 namespace OHOS {
32 namespace NetStack {
33 namespace TlsSocket {
34 VerifyMode TLSContext::verifyMode_ = TWO_WAY_MODE;
CreateConfiguration(const TLSConfiguration & configuration)35 std::unique_ptr<TLSContext> TLSContext::CreateConfiguration(const TLSConfiguration &configuration)
36 {
37 auto tlsContext = std::make_unique<TLSContext>();
38 if (!InitTlsContext(tlsContext.get(), configuration)) {
39 NETSTACK_LOGE("Failed to init tls context");
40 return nullptr;
41 }
42 return tlsContext;
43 }
44
InitEnv()45 void InitEnv()
46 {
47 SSL_library_init();
48 OpenSSL_add_all_algorithms();
49 SSL_load_error_strings();
50 }
51
SetCipherList(TLSContext * tlsContext,const TLSConfiguration & configuration)52 bool TLSContext::SetCipherList(TLSContext *tlsContext, const TLSConfiguration &configuration)
53 {
54 if (!tlsContext) {
55 NETSTACK_LOGE("tlsContext is null");
56 return false;
57 }
58 NETSTACK_LOGD("GetCipherSuite = %{public}s", configuration.GetCipherSuite().c_str());
59 if (SSL_CTX_set_cipher_list(tlsContext->ctx_, configuration.GetCipherSuite().c_str()) <= 0) {
60 NETSTACK_LOGE("Error setting the cipher list");
61 return false;
62 }
63 return true;
64 }
65
GetCiphers(TLSContext * tlsContext)66 void TLSContext::GetCiphers(TLSContext *tlsContext)
67 {
68 if (!tlsContext) {
69 NETSTACK_LOGE("tlsContext is null");
70 return;
71 }
72 std::vector<CipherSuite> cipherSuiteVec;
73 STACK_OF(SSL_CIPHER) *sk = SSL_CTX_get_ciphers(tlsContext->ctx_);
74 if (!sk) {
75 NETSTACK_LOGE("sk is null");
76 return;
77 }
78 CipherSuite cipherSuite;
79 for (int i = 0; i < sk_SSL_CIPHER_num(sk); i++) {
80 const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(sk, i);
81 cipherSuite.cipherId_ = SSL_CIPHER_get_id(cipher);
82 cipherSuite.cipherName_ = SSL_CIPHER_get_name(cipher);
83 cipherSuiteVec.push_back(cipherSuite);
84 }
85 }
86
SetSignatureAlgorithms(TLSContext * tlsContext,const TLSConfiguration & configuration)87 bool TLSContext::SetSignatureAlgorithms(TLSContext *tlsContext, const TLSConfiguration &configuration)
88 {
89 if (!tlsContext) {
90 NETSTACK_LOGE("tlsContext is null");
91 return false;
92 }
93 if (configuration.GetSignatureAlgorithms().empty()) {
94 NETSTACK_LOGE("configuration get signature algorithms is empty");
95 return false;
96 }
97
98 if (!SSL_CTX_set1_sigalgs_list(tlsContext->ctx_, configuration.GetSignatureAlgorithms().c_str())) {
99 NETSTACK_LOGE("Error setting the Signature Algorithms");
100 return false;
101 }
102 return true;
103 }
104
UseRemoteCipher(TLSContext * tlsContext)105 void TLSContext::UseRemoteCipher(TLSContext *tlsContext)
106 {
107 if (!tlsContext) {
108 NETSTACK_LOGE("TLSContext::UseRemoteCipher: tlsContext is null");
109 return;
110 }
111 if (tlsContext->tlsConfiguration_.GetUseRemoteCipherPrefer()) {
112 SSL_CTX_set_options(tlsContext->ctx_, SSL_OP_CIPHER_SERVER_PREFERENCE);
113 }
114 NETSTACK_LOGI("SSL_CTX_get_options = %{public}" PRIx64,
115 static_cast<uint64_t>(SSL_CTX_get_options(tlsContext->ctx_)));
116 }
117
SetMinAndMaxProtocol(TLSContext * tlsContext)118 void TLSContext::SetMinAndMaxProtocol(TLSContext *tlsContext)
119 {
120 if (!tlsContext) {
121 NETSTACK_LOGE("TLSContext::SetMinAndMaxProtocol: tlsContext is null");
122 return;
123 }
124 const long anyVersion = TLS_ANY_VERSION;
125 long minVersion = anyVersion;
126 long maxVersion = anyVersion;
127
128 switch (tlsContext->tlsConfiguration_.GetMinProtocol()) {
129 case TLS_V1_2:
130 minVersion = TLS1_2_VERSION;
131 break;
132 case TLS_V1_3:
133 minVersion = TLS1_3_VERSION;
134 break;
135 case UNKNOW_PROTOCOL:
136 break;
137 default:
138 break;
139 }
140
141 switch (tlsContext->tlsConfiguration_.GetMaxProtocol()) {
142 case TLS_V1_2:
143 maxVersion = TLS1_2_VERSION;
144 break;
145 case TLS_V1_3:
146 maxVersion = TLS1_3_VERSION;
147 break;
148 case UNKNOW_PROTOCOL:
149 break;
150 default:
151 break;
152 }
153
154 if (minVersion != anyVersion && !SSL_CTX_set_min_proto_version(tlsContext->ctx_, minVersion)) {
155 NETSTACK_LOGE("Error while setting the minimal protocol version");
156 return;
157 }
158
159 if (maxVersion != anyVersion && !SSL_CTX_set_max_proto_version(tlsContext->ctx_, maxVersion)) {
160 NETSTACK_LOGE("Error while setting the maximum protocol version");
161 return;
162 }
163
164 NETSTACK_LOGD("minProtocol = %{public}lx, maxProtocol = %{public}lx",
165 SSL_CTX_get_min_proto_version(tlsContext->ctx_), SSL_CTX_get_max_proto_version(tlsContext->ctx_));
166 }
167
SetDefaultCa(TLSContext * tlsContext,const TLSConfiguration & configuration)168 bool TLSContext::SetDefaultCa(TLSContext *tlsContext, const TLSConfiguration &configuration)
169 {
170 #ifdef HAS_NETMANAGER_BASE
171 auto hostname = CommonUtils::GetHostnameFromURL(configuration.GetNetAddress().GetAddress());
172 // customize trusted CAs.
173 std::vector<std::string> cert_paths;
174
175 if (NetManagerStandard::NetConnClient::GetInstance().GetTrustAnchorsForHostName(hostname, cert_paths) != 0) {
176 NETSTACK_LOGE("get customize trusted CAs failed");
177 return false;
178 }
179 for (const auto &path : cert_paths) {
180 if (!X509_STORE_load_path(SSL_CTX_get_cert_store(tlsContext->ctx_), path.c_str())) {
181 NETSTACK_LOGE("load customize certificates failed");
182 return false;
183 }
184 }
185 if (NetManagerStandard::NetConnClient::GetInstance().TrustUser0Ca() &&
186 access(ROOT_CERT_PATH.c_str(), F_OK | R_OK) == 0) {
187 NETSTACK_LOGD("root CA certificates folder exist and can read");
188 if (!X509_STORE_load_path(SSL_CTX_get_cert_store(tlsContext->ctx_), ROOT_CERT_PATH.c_str())) {
189 NETSTACK_LOGE("load root certificates failed");
190 return false;
191 }
192 } else {
193 NETSTACK_LOGD("root CA certificates folder not exist or can not read");
194 }
195 std::string userCertPath = BASE_PATH + std::to_string(getuid() / UID_TRANSFORM_DIVISOR);
196 if (NetManagerStandard::NetConnClient::GetInstance().TrustUserCa() &&
197 access(userCertPath.c_str(), F_OK | R_OK) == 0) {
198 NETSTACK_LOGD("user CA certificates folder exist and can read");
199 if (!X509_STORE_load_path(SSL_CTX_get_cert_store(tlsContext->ctx_), userCertPath.c_str())) {
200 NETSTACK_LOGE("load user certificates failed");
201 return false;
202 }
203 } else {
204 NETSTACK_LOGD("user CA certificates folder not exist or can not read");
205 }
206 #endif // HAS_NETMANAGER_BASE
207 if (!X509_STORE_load_path(SSL_CTX_get_cert_store(tlsContext->ctx_), SYSTEM_REPLACE_CA_PATH.c_str())) {
208 NETSTACK_LOGE("load system replace certificates failed");
209 return false;
210 }
211 return true;
212 }
213
SetCaAndVerify(TLSContext * tlsContext,const TLSConfiguration & configuration)214 bool TLSContext::SetCaAndVerify(TLSContext *tlsContext, const TLSConfiguration &configuration)
215 {
216 if (!tlsContext) {
217 NETSTACK_LOGE("tlsContext is null");
218 return false;
219 }
220
221 if (configuration.GetCaCertificate().empty()) {
222 return SetDefaultCa(tlsContext, configuration);
223 } else {
224 for (const auto &cert : configuration.GetCaCertificate()) {
225 TLSCertificate ca(cert, CA_CERT);
226 if (X509_STORE_add_cert(SSL_CTX_get_cert_store(tlsContext->ctx_), static_cast<X509 *>(ca.handle())) != 1) {
227 NETSTACK_LOGE("Failed to add x509 cert");
228 return false;
229 }
230 }
231 }
232
233 return true;
234 }
235
SetLocalCertificate(TLSContext * tlsContext,const TLSConfiguration & configuration)236 bool TLSContext::SetLocalCertificate(TLSContext *tlsContext, const TLSConfiguration &configuration)
237 {
238 if (!tlsContext) {
239 NETSTACK_LOGE("tlsContext is null");
240 return false;
241 }
242 if (!SSL_CTX_use_certificate(tlsContext->ctx_, static_cast<X509 *>(configuration.GetLocalCertificate().handle()))) {
243 NETSTACK_LOGD("The local certificate is unavailable");
244 return false;
245 }
246 return true;
247 }
248
SetKeyAndCheck(TLSContext * tlsContext,const TLSConfiguration & configuration)249 bool TLSContext::SetKeyAndCheck(TLSContext *tlsContext, const TLSConfiguration &configuration)
250 {
251 if (!tlsContext) {
252 NETSTACK_LOGE("The parameter tlsContext is null");
253 return false;
254 }
255 if (configuration.GetPrivateKey().Algorithm() == OPAQUE) {
256 tlsContext->pkey_ = reinterpret_cast<EVP_PKEY *>(configuration.GetPrivateKey().handle());
257 } else {
258 tlsContext->pkey_ = EVP_PKEY_new();
259 if (configuration.GetPrivateKey().Algorithm() == ALGORITHM_RSA) {
260 EVP_PKEY_assign_RSA(tlsContext->pkey_, reinterpret_cast<RSA *>(configuration.GetPrivateKey().handle()));
261 } else if (tlsContext->tlsConfiguration_.GetPrivateKey().Algorithm() == ALGORITHM_DSA) {
262 EVP_PKEY_assign_DSA(tlsContext->pkey_, reinterpret_cast<DSA *>(configuration.GetPrivateKey().handle()));
263 } else if (tlsContext->tlsConfiguration_.GetPrivateKey().Algorithm() == ALGORITHM_DH) {
264 EVP_PKEY_assign_DH(tlsContext->pkey_, reinterpret_cast<DH *>(configuration.GetPrivateKey().handle()));
265 } else if (tlsContext->tlsConfiguration_.GetPrivateKey().Algorithm() == ALGORITHM_EC) {
266 EVP_PKEY_assign_EC_KEY(tlsContext->pkey_,
267 reinterpret_cast<EC_KEY *>(configuration.GetPrivateKey().handle()));
268 }
269 }
270
271 if (configuration.GetPrivateKey().Algorithm() == OPAQUE) {
272 tlsContext->pkey_ = nullptr;
273 }
274 auto pkey_ = tlsContext->pkey_;
275 if (!SSL_CTX_use_PrivateKey(tlsContext->ctx_, pkey_)) {
276 NETSTACK_LOGE("SSL_CTX_use_PrivateKey is error");
277 return false;
278 }
279
280 if (!configuration.GetPrivateKey().GetKeyPass().Length()) {
281 SSL_CTX_set_default_passwd_cb_userdata(tlsContext->ctx_,
282 reinterpret_cast<void *>(const_cast<char *>(
283 tlsContext->tlsConfiguration_.GetPrivateKey().GetKeyPass().Data())));
284 }
285 // Check if the certificate matches the private key.
286 if (!SSL_CTX_check_private_key(tlsContext->ctx_)) {
287 NETSTACK_LOGE("Check if the certificate matches the private key is error");
288 return false;
289 }
290 return true;
291 }
292
SetVerify(TLSContext * tlsContext)293 void TLSContext::SetVerify(TLSContext *tlsContext)
294 {
295 if (!tlsContext) {
296 NETSTACK_LOGE("tlsContext is null");
297 return;
298 }
299
300 if (!tlsContext->tlsConfiguration_.GetCertificate().data.Length() ||
301 !tlsContext->tlsConfiguration_.GetPrivateKey().GetKeyData().Length()) {
302 verifyMode_ = ONE_WAY_MODE;
303 SSL_CTX_set_verify(tlsContext->ctx_, SSL_VERIFY_PEER, nullptr);
304 } else {
305 verifyMode_ = TWO_WAY_MODE;
306 SSL_CTX_set_verify(tlsContext->ctx_, SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nullptr);
307 }
308
309 if (tlsContext->tlsConfiguration_.GetSkipFlag()) {
310 NETSTACK_LOGI("Choose to skip remote validation.");
311 SSL_CTX_set_verify(tlsContext->ctx_, SSL_VERIFY_NONE, nullptr);
312 }
313
314 NETSTACK_LOGD("Authentication mode is %{public}s",
315 verifyMode_ ? "two-way authentication" : "one-way authentication");
316 }
317
InitTlsContext(TLSContext * tlsContext,const TLSConfiguration & configuration)318 bool TLSContext::InitTlsContext(TLSContext *tlsContext, const TLSConfiguration &configuration)
319 {
320 if (!tlsContext) {
321 NETSTACK_LOGE("tlsContext is null");
322 return false;
323 }
324 InitEnv();
325 tlsContext->tlsConfiguration_ = configuration;
326 tlsContext->ctx_ = SSL_CTX_new(TLS_client_method());
327 if (tlsContext->ctx_ == nullptr) {
328 NETSTACK_LOGE("ctx is nullptr");
329 return false;
330 }
331 if (!configuration.GetCipherSuite().empty()) {
332 if (!SetCipherList(tlsContext, configuration)) {
333 NETSTACK_LOGE("Failed to set cipher suite");
334 return false;
335 }
336 }
337 if (!configuration.GetSignatureAlgorithms().empty()) {
338 if (!SetSignatureAlgorithms(tlsContext, configuration)) {
339 NETSTACK_LOGE("Failed to set signature algorithms");
340 return false;
341 }
342 }
343 GetCiphers(tlsContext);
344 UseRemoteCipher(tlsContext);
345 SetMinAndMaxProtocol(tlsContext);
346 SetVerify(tlsContext);
347 if (!SetCaAndVerify(tlsContext, configuration)) {
348 return false;
349 }
350 if (!verifyMode_) {
351 NETSTACK_LOGD("one way authentication");
352 return true;
353 }
354 if (!SetLocalCertificate(tlsContext, configuration)) {
355 return false;
356 }
357 if (!SetKeyAndCheck(tlsContext, configuration)) {
358 return false;
359 }
360 return true;
361 }
CreateSsl()362 SSL *TLSContext::CreateSsl()
363 {
364 ctxSsl_ = SSL_new(ctx_);
365 return ctxSsl_;
366 }
367
CloseCtx()368 void TLSContext::CloseCtx()
369 {
370 if (ctx_ != nullptr) {
371 SSL_CTX_free(ctx_);
372 ctx_ = nullptr;
373 }
374 }
375 } // namespace TlsSocket
376 } // namespace NetStack
377 } // namespace OHOS
378