• 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 <cerrno>
19 #include <string>
20 
21 #include <openssl/err.h>
22 #include <openssl/evp.h>
23 #include <openssl/ssl.h>
24 
25 #include "netstack_log.h"
26 
27 namespace OHOS {
28 namespace NetStack {
29 VerifyMode TLSContext::verifyMode_ = TWO_WAY_MODE;
CreateConfiguration(const TLSConfiguration & configuration)30 std::unique_ptr<TLSContext> TLSContext::CreateConfiguration(const TLSConfiguration &configuration)
31 {
32     auto tlsContext = std::make_unique<TLSContext>();
33     if (!InitTlsContext(tlsContext.get(), configuration)) {
34         NETSTACK_LOGE("Failed to init tls context");
35         return nullptr;
36     }
37     return tlsContext;
38 }
39 
InitEnv()40 void InitEnv()
41 {
42     SSL_library_init();
43     OpenSSL_add_all_algorithms();
44     SSL_load_error_strings();
45 }
46 
SetCipherList(TLSContext * tlsContext,const TLSConfiguration & configuration)47 bool TLSContext::SetCipherList(TLSContext *tlsContext, const TLSConfiguration &configuration)
48 {
49     if (!tlsContext) {
50         NETSTACK_LOGE("tlsContext is null");
51         return false;
52     }
53     NETSTACK_LOGD("GetCipherSuite = %{public}s", configuration.GetCipherSuite().c_str());
54     if (SSL_CTX_set_cipher_list(tlsContext->ctx_, configuration.GetCipherSuite().c_str()) <= 0) {
55         NETSTACK_LOGE("Error setting the cipher list");
56         return false;
57     }
58     return true;
59 }
60 
GetCiphers(TLSContext * tlsContext)61 void TLSContext::GetCiphers(TLSContext *tlsContext)
62 {
63     if (!tlsContext) {
64         NETSTACK_LOGE("tlsContext is null");
65         return;
66     }
67     std::vector<CipherSuite> cipherSuiteVec;
68     STACK_OF(SSL_CIPHER) *sk = SSL_CTX_get_ciphers(tlsContext->ctx_);
69     if (!sk) {
70         NETSTACK_LOGE("sk is null");
71         return;
72     }
73     CipherSuite cipherSuite;
74     for (int i = 0; i < sk_SSL_CIPHER_num(sk); i++) {
75         const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(sk, i);
76         cipherSuite.cipherId_ = SSL_CIPHER_get_id(cipher);
77         cipherSuite.cipherName_ = SSL_CIPHER_get_name(cipher);
78         cipherSuiteVec.push_back(cipherSuite);
79     }
80 }
81 
SetSignatureAlgorithms(TLSContext * tlsContext,const TLSConfiguration & configuration)82 bool TLSContext::SetSignatureAlgorithms(TLSContext *tlsContext, const TLSConfiguration &configuration)
83 {
84     if (!tlsContext) {
85         NETSTACK_LOGE("tlsContext is null");
86         return false;
87     }
88     if (configuration.GetSignatureAlgorithms().empty()) {
89         NETSTACK_LOGE("configuration get signature algorithms is empty");
90         return false;
91     }
92 
93     if (!SSL_CTX_set1_sigalgs_list(tlsContext->ctx_, configuration.GetSignatureAlgorithms().c_str())) {
94         NETSTACK_LOGE("Error setting the Signature Algorithms");
95         return false;
96     }
97     return true;
98 }
99 
UseRemoteCipher(TLSContext * tlsContext)100 void TLSContext::UseRemoteCipher(TLSContext *tlsContext)
101 {
102     if (!tlsContext) {
103         NETSTACK_LOGE("TLSContext::UseRemoteCipher: tlsContext is null");
104         return;
105     }
106     if (tlsContext->tlsConfiguration_.GetUseRemoteCipherPrefer()) {
107         SSL_CTX_set_options(tlsContext->ctx_, SSL_OP_CIPHER_SERVER_PREFERENCE);
108     }
109     NETSTACK_LOGI("SSL_CTX_get_options = %{public}lx", SSL_CTX_get_options(tlsContext->ctx_));
110 }
111 
SetMinAndMaxProtocol(TLSContext * tlsContext)112 void TLSContext::SetMinAndMaxProtocol(TLSContext *tlsContext)
113 {
114     if (!tlsContext) {
115         NETSTACK_LOGE("TLSContext::SetMinAndMaxProtocol: tlsContext is null");
116         return;
117     }
118     const long anyVersion = TLS_ANY_VERSION;
119     long minVersion = anyVersion;
120     long maxVersion = anyVersion;
121 
122     switch (tlsContext->tlsConfiguration_.GetMinProtocol()) {
123         case TLS_V1_2:
124             minVersion = TLS1_2_VERSION;
125             break;
126         case TLS_V1_3:
127             minVersion = TLS1_3_VERSION;
128             break;
129         case UNKNOW_PROTOCOL:
130             break;
131         default:
132             break;
133     }
134 
135     switch (tlsContext->tlsConfiguration_.GetMaxProtocol()) {
136         case TLS_V1_2:
137             maxVersion = TLS1_2_VERSION;
138             break;
139         case TLS_V1_3:
140             maxVersion = TLS1_3_VERSION;
141             break;
142         case UNKNOW_PROTOCOL:
143             break;
144         default:
145             break;
146     }
147 
148     if (minVersion != anyVersion && !SSL_CTX_set_min_proto_version(tlsContext->ctx_, minVersion)) {
149         NETSTACK_LOGE("Error while setting the minimal protocol version");
150         return;
151     }
152 
153     if (maxVersion != anyVersion && !SSL_CTX_set_max_proto_version(tlsContext->ctx_, maxVersion)) {
154         NETSTACK_LOGE("Error while setting the maximum protocol version");
155         return;
156     }
157 
158     NETSTACK_LOGD("minProtocol = %{public}lx, maxProtocol = %{public}lx",
159                   SSL_CTX_get_min_proto_version(tlsContext->ctx_), SSL_CTX_get_max_proto_version(tlsContext->ctx_));
160 }
161 
SetCaAndVerify(TLSContext * tlsContext,const TLSConfiguration & configuration)162 bool TLSContext::SetCaAndVerify(TLSContext *tlsContext, const TLSConfiguration &configuration)
163 {
164     if (!tlsContext) {
165         NETSTACK_LOGE("tlsContext is null");
166         return false;
167     }
168     for (const auto &cert : configuration.GetCaCertificate()) {
169         TLSCertificate ca(cert, CA_CERT);
170         if (!X509_STORE_add_cert(SSL_CTX_get_cert_store(tlsContext->ctx_), static_cast<X509 *>(ca.handle()))) {
171             NETSTACK_LOGE("Failed to add x509 cert");
172             return false;
173         }
174     }
175     return true;
176 }
177 
SetLocalCertificate(TLSContext * tlsContext,const TLSConfiguration & configuration)178 bool TLSContext::SetLocalCertificate(TLSContext *tlsContext, const TLSConfiguration &configuration)
179 {
180     if (!tlsContext) {
181         NETSTACK_LOGE("tlsContext is null");
182         return false;
183     }
184     if (!SSL_CTX_use_certificate(tlsContext->ctx_, static_cast<X509 *>(configuration.GetLocalCertificate().handle()))) {
185         NETSTACK_LOGD("The local certificate is unavailable");
186         return false;
187     }
188     return true;
189 }
190 
SetKeyAndCheck(TLSContext * tlsContext,const TLSConfiguration & configuration)191 bool TLSContext::SetKeyAndCheck(TLSContext *tlsContext, const TLSConfiguration &configuration)
192 {
193     if (!tlsContext) {
194         NETSTACK_LOGE("The parameter tlsContext is null");
195         return false;
196     }
197     if (configuration.GetPrivateKey().Algorithm() == OPAQUE) {
198         tlsContext->pkey_ = reinterpret_cast<EVP_PKEY *>(configuration.GetPrivateKey().handle());
199     } else {
200         tlsContext->pkey_ = EVP_PKEY_new();
201         if (configuration.GetPrivateKey().Algorithm() == ALGORITHM_RSA) {
202             EVP_PKEY_set1_RSA(tlsContext->pkey_, reinterpret_cast<RSA *>(configuration.GetPrivateKey().handle()));
203         } else if (tlsContext->tlsConfiguration_.GetPrivateKey().Algorithm() == ALGORITHM_DSA) {
204             EVP_PKEY_set1_DSA(tlsContext->pkey_, reinterpret_cast<DSA *>(configuration.GetPrivateKey().handle()));
205         }
206     }
207 
208     if (configuration.GetPrivateKey().Algorithm() == OPAQUE) {
209         tlsContext->pkey_ = nullptr;
210     }
211     auto pkey_ = tlsContext->pkey_;
212     if (!SSL_CTX_use_PrivateKey(tlsContext->ctx_, pkey_)) {
213         NETSTACK_LOGE("SSL_CTX_use_PrivateKey is error");
214         return false;
215     }
216 
217     if (!configuration.GetPrivateKey().GetKeyPass().Length()) {
218         SSL_CTX_set_default_passwd_cb_userdata(tlsContext->ctx_,
219                                                reinterpret_cast<void *>(const_cast<char *>(
220                                                tlsContext->tlsConfiguration_.GetPrivateKey().GetKeyPass().Data())));
221     }
222     // Check if the certificate matches the private key.
223     if (!SSL_CTX_check_private_key(tlsContext->ctx_)) {
224         NETSTACK_LOGE("Check if the certificate matches the private key is error");
225         return false;
226     }
227     return true;
228 }
229 
SetVerify(TLSContext * tlsContext)230 void TLSContext::SetVerify(TLSContext *tlsContext)
231 {
232     if (!tlsContext) {
233         NETSTACK_LOGE("tlsContext is null");
234         return;
235     }
236 
237     if (tlsContext->tlsConfiguration_.GetCaCertificate().empty() ||
238         !tlsContext->tlsConfiguration_.GetCertificate().data.Length() ||
239         !tlsContext->tlsConfiguration_.GetPrivateKey().GetKeyData().Length()) {
240         verifyMode_ = ONE_WAY_MODE;
241         SSL_CTX_set_verify(tlsContext->ctx_, SSL_VERIFY_PEER, nullptr);
242     } else {
243         verifyMode_ = TWO_WAY_MODE;
244         SSL_CTX_set_verify(tlsContext->ctx_, SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nullptr);
245     }
246     NETSTACK_LOGD("Authentication mode is %{public}s", verifyMode_ ? "two-way authentication" : "one-way authentication");
247 }
248 
InitTlsContext(TLSContext * tlsContext,const TLSConfiguration & configuration)249 bool TLSContext::InitTlsContext(TLSContext *tlsContext, const TLSConfiguration &configuration)
250 {
251     if (!tlsContext) {
252         NETSTACK_LOGE("tlsContext is null");
253         return false;
254     }
255     InitEnv();
256     tlsContext->tlsConfiguration_ = configuration;
257     tlsContext->ctx_ = SSL_CTX_new(TLS_client_method());
258     if (tlsContext->ctx_ == nullptr) {
259         NETSTACK_LOGE("ctx is nullptr");
260         return false;
261     }
262     if (!configuration.GetCipherSuite().empty()) {
263         if (!SetCipherList(tlsContext, configuration)) {
264             NETSTACK_LOGE("Failed to set cipher suite");
265             return false;
266         }
267     }
268     if (!configuration.GetSignatureAlgorithms().empty()) {
269         if (!SetSignatureAlgorithms(tlsContext, configuration)) {
270             NETSTACK_LOGE("Failed to set signature algorithms");
271             return false;
272         }
273     }
274     GetCiphers(tlsContext);
275     UseRemoteCipher(tlsContext);
276     SetMinAndMaxProtocol(tlsContext);
277     SetVerify(tlsContext);
278     if (!SetCaAndVerify(tlsContext, configuration)) {
279         return false;
280     }
281     if (!verifyMode_) {
282         NETSTACK_LOGD("one way authentication");
283         return true;
284     }
285     if (!SetLocalCertificate(tlsContext, configuration)) {
286         return false;
287     }
288     if (!SetKeyAndCheck(tlsContext, configuration)) {
289         return false;
290     }
291     return true;
292 }
CreateSsl()293 SSL *TLSContext::CreateSsl()
294 {
295     ctxSsl_ = SSL_new(ctx_);
296     return ctxSsl_;
297 }
298 
CloseCtx()299 void TLSContext::CloseCtx()
300 {
301     SSL_CTX_free(ctx_);
302 }
303 } // namespace NetStack
304 } // namespace OHOS
305