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