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 #endif // HAS_NETMANAGER_BASE
186     if (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 (access(userCertPath.c_str(), F_OK | R_OK) == 0) {
197         NETSTACK_LOGD("user CA certificates folder exist and can read");
198         if (!X509_STORE_load_path(SSL_CTX_get_cert_store(tlsContext->ctx_), userCertPath.c_str())) {
199             NETSTACK_LOGE("load user certificates failed");
200             return false;
201         }
202     } else {
203         NETSTACK_LOGD("user CA certificates folder not exist or can not read");
204     }
205     if (!X509_STORE_load_path(SSL_CTX_get_cert_store(tlsContext->ctx_), SYSTEM_REPLACE_CA_PATH.c_str())) {
206         NETSTACK_LOGE("load system replace certificates failed");
207         return false;
208     }
209     return true;
210 }
211 
SetCaAndVerify(TLSContext * tlsContext,const TLSConfiguration & configuration)212 bool TLSContext::SetCaAndVerify(TLSContext *tlsContext, const TLSConfiguration &configuration)
213 {
214     if (!tlsContext) {
215         NETSTACK_LOGE("tlsContext is null");
216         return false;
217     }
218 
219     if (configuration.GetCaCertificate().empty()) {
220         return SetDefaultCa(tlsContext, configuration);
221     } else {
222         for (const auto &cert : configuration.GetCaCertificate()) {
223             TLSCertificate ca(cert, CA_CERT);
224             if (X509_STORE_add_cert(SSL_CTX_get_cert_store(tlsContext->ctx_), static_cast<X509 *>(ca.handle())) != 1) {
225                 NETSTACK_LOGE("Failed to add x509 cert");
226                 return false;
227             }
228         }
229     }
230 
231     return true;
232 }
233 
SetLocalCertificate(TLSContext * tlsContext,const TLSConfiguration & configuration)234 bool TLSContext::SetLocalCertificate(TLSContext *tlsContext, const TLSConfiguration &configuration)
235 {
236     if (!tlsContext) {
237         NETSTACK_LOGE("tlsContext is null");
238         return false;
239     }
240     if (!SSL_CTX_use_certificate(tlsContext->ctx_, static_cast<X509 *>(configuration.GetLocalCertificate().handle()))) {
241         NETSTACK_LOGD("The local certificate is unavailable");
242         return false;
243     }
244     return true;
245 }
246 
SetKeyAndCheck(TLSContext * tlsContext,const TLSConfiguration & configuration)247 bool TLSContext::SetKeyAndCheck(TLSContext *tlsContext, const TLSConfiguration &configuration)
248 {
249     if (!tlsContext) {
250         NETSTACK_LOGE("The parameter tlsContext is null");
251         return false;
252     }
253     if (configuration.GetPrivateKey().Algorithm() == OPAQUE) {
254         tlsContext->pkey_ = reinterpret_cast<EVP_PKEY *>(configuration.GetPrivateKey().handle());
255     } else {
256         tlsContext->pkey_ = EVP_PKEY_new();
257         if (configuration.GetPrivateKey().Algorithm() == ALGORITHM_RSA) {
258             EVP_PKEY_assign_RSA(tlsContext->pkey_, reinterpret_cast<RSA *>(configuration.GetPrivateKey().handle()));
259         } else if (tlsContext->tlsConfiguration_.GetPrivateKey().Algorithm() == ALGORITHM_DSA) {
260             EVP_PKEY_assign_DSA(tlsContext->pkey_, reinterpret_cast<DSA *>(configuration.GetPrivateKey().handle()));
261         } else if (tlsContext->tlsConfiguration_.GetPrivateKey().Algorithm() == ALGORITHM_DH) {
262             EVP_PKEY_assign_DH(tlsContext->pkey_, reinterpret_cast<DH *>(configuration.GetPrivateKey().handle()));
263         } else if (tlsContext->tlsConfiguration_.GetPrivateKey().Algorithm() == ALGORITHM_EC) {
264             EVP_PKEY_assign_EC_KEY(tlsContext->pkey_,
265                                    reinterpret_cast<EC_KEY *>(configuration.GetPrivateKey().handle()));
266         }
267     }
268 
269     if (configuration.GetPrivateKey().Algorithm() == OPAQUE) {
270         tlsContext->pkey_ = nullptr;
271     }
272     auto pkey_ = tlsContext->pkey_;
273     if (!SSL_CTX_use_PrivateKey(tlsContext->ctx_, pkey_)) {
274         NETSTACK_LOGE("SSL_CTX_use_PrivateKey is error");
275         return false;
276     }
277 
278     if (!configuration.GetPrivateKey().GetKeyPass().Length()) {
279         SSL_CTX_set_default_passwd_cb_userdata(tlsContext->ctx_,
280                                                reinterpret_cast<void *>(const_cast<char *>(
281                                                    tlsContext->tlsConfiguration_.GetPrivateKey().GetKeyPass().Data())));
282     }
283     // Check if the certificate matches the private key.
284     if (!SSL_CTX_check_private_key(tlsContext->ctx_)) {
285         NETSTACK_LOGE("Check if the certificate matches the private key is error");
286         return false;
287     }
288     return true;
289 }
290 
SetVerify(TLSContext * tlsContext)291 void TLSContext::SetVerify(TLSContext *tlsContext)
292 {
293     if (!tlsContext) {
294         NETSTACK_LOGE("tlsContext is null");
295         return;
296     }
297 
298     if (!tlsContext->tlsConfiguration_.GetCertificate().data.Length() ||
299         !tlsContext->tlsConfiguration_.GetPrivateKey().GetKeyData().Length()) {
300         verifyMode_ = ONE_WAY_MODE;
301         SSL_CTX_set_verify(tlsContext->ctx_, SSL_VERIFY_PEER, nullptr);
302     } else {
303         verifyMode_ = TWO_WAY_MODE;
304         SSL_CTX_set_verify(tlsContext->ctx_, SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nullptr);
305     }
306 
307     if (tlsContext->tlsConfiguration_.GetSkipFlag()) {
308         NETSTACK_LOGI("Choose to skip remote validation.");
309         SSL_CTX_set_verify(tlsContext->ctx_, SSL_VERIFY_NONE, nullptr);
310     }
311 
312     NETSTACK_LOGD("Authentication mode is %{public}s",
313                   verifyMode_ ? "two-way authentication" : "one-way authentication");
314 }
315 
InitTlsContext(TLSContext * tlsContext,const TLSConfiguration & configuration)316 bool TLSContext::InitTlsContext(TLSContext *tlsContext, const TLSConfiguration &configuration)
317 {
318     if (!tlsContext) {
319         NETSTACK_LOGE("tlsContext is null");
320         return false;
321     }
322     InitEnv();
323     tlsContext->tlsConfiguration_ = configuration;
324     tlsContext->ctx_ = SSL_CTX_new(TLS_client_method());
325     if (tlsContext->ctx_ == nullptr) {
326         NETSTACK_LOGE("ctx is nullptr");
327         return false;
328     }
329     if (!configuration.GetCipherSuite().empty()) {
330         if (!SetCipherList(tlsContext, configuration)) {
331             NETSTACK_LOGE("Failed to set cipher suite");
332             return false;
333         }
334     }
335     if (!configuration.GetSignatureAlgorithms().empty()) {
336         if (!SetSignatureAlgorithms(tlsContext, configuration)) {
337             NETSTACK_LOGE("Failed to set signature algorithms");
338             return false;
339         }
340     }
341     GetCiphers(tlsContext);
342     UseRemoteCipher(tlsContext);
343     SetMinAndMaxProtocol(tlsContext);
344     SetVerify(tlsContext);
345     if (!SetCaAndVerify(tlsContext, configuration)) {
346         return false;
347     }
348     if (!verifyMode_) {
349         NETSTACK_LOGD("one way authentication");
350         return true;
351     }
352     if (!SetLocalCertificate(tlsContext, configuration)) {
353         return false;
354     }
355     if (!SetKeyAndCheck(tlsContext, configuration)) {
356         return false;
357     }
358     return true;
359 }
CreateSsl()360 SSL *TLSContext::CreateSsl()
361 {
362     ctxSsl_ = SSL_new(ctx_);
363     return ctxSsl_;
364 }
365 
CloseCtx()366 void TLSContext::CloseCtx()
367 {
368     SSL_CTX_free(ctx_);
369 }
370 } // namespace TlsSocket
371 } // namespace NetStack
372 } // namespace OHOS
373