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