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_key.h"
17
18 #include "netstack_log.h"
19 #include "tls_utils.h"
20
21 namespace OHOS {
22 namespace NetStack {
23 namespace TlsSocket {
24 namespace {
25 constexpr int FILE_READ_KEY_LEN = 4096;
26 constexpr const char *FILE_OPEN_FLAG = "rb";
27 } // namespace
28
TLSKey(const std::string & fileName,KeyAlgorithm algorithm,const SecureData & passPhrase,EncodingFormat encoding,KeyType type)29 TLSKey::TLSKey(const std::string &fileName, KeyAlgorithm algorithm, const SecureData &passPhrase,
30 EncodingFormat encoding, KeyType type)
31 {
32 if (encoding == DER) {
33 DecodeDer(type, algorithm, fileName, passPhrase);
34 } else {
35 DecodePem(type, algorithm, fileName, passPhrase);
36 }
37 }
38
TLSKey(const SecureData & data,KeyAlgorithm algorithm,const SecureData & passPhrase)39 TLSKey::TLSKey(const SecureData &data, KeyAlgorithm algorithm, const SecureData &passPhrase)
40 {
41 if (data.Length() == 0) {
42 NETSTACK_LOGD("data is empty");
43 } else {
44 DecodeData(data, algorithm, passPhrase);
45 }
46 }
47
TLSKey(const SecureData & data,const SecureData & passPhrase)48 TLSKey::TLSKey(const SecureData &data, const SecureData &passPhrase)
49 {
50 if (data.Length() == 0) {
51 NETSTACK_LOGD("data is empty");
52 } else {
53 DecodeData(data, passPhrase);
54 }
55 }
56
TLSKey(const TLSKey & other)57 TLSKey::TLSKey(const TLSKey &other)
58 {
59 *this = other;
60 }
61
operator =(const TLSKey & other)62 TLSKey &TLSKey::operator=(const TLSKey &other)
63 {
64 if (other.rsa_ != nullptr) {
65 rsa_ = RSA_new();
66 rsa_ = other.rsa_;
67 }
68 if (other.dsa_ != nullptr) {
69 dsa_ = DSA_new();
70 dsa_ = other.dsa_;
71 }
72 if (other.dh_ != nullptr) {
73 dh_ = DH_new();
74 dh_ = other.dh_;
75 }
76 if (other.ec_ != nullptr) {
77 ec_ = EC_KEY_new();
78 ec_ = other.ec_;
79 }
80 if (other.genericKey_ != nullptr) {
81 genericKey_ = EVP_PKEY_new();
82 genericKey_ = other.genericKey_;
83 }
84 keyIsNull_ = other.keyIsNull_;
85 keyType_ = other.keyType_;
86 keyAlgorithm_ = other.keyAlgorithm_;
87 keyPass_ = other.keyPass_;
88 keyData_ = other.keyData_;
89 return *this;
90 }
91
DecodeData(const SecureData & data,const SecureData & passPhrase)92 void TLSKey::DecodeData(const SecureData &data, const SecureData &passPhrase)
93 {
94 if (data.Length() == 0) {
95 NETSTACK_LOGE("The parameter data is empty");
96 return;
97 }
98 keyData_ = data;
99 keyPass_ = passPhrase;
100 BIO *bio = BIO_new_mem_buf(data.Data(), -1);
101 if (!bio) {
102 NETSTACK_LOGE("Failed to create bio buffer");
103 return;
104 }
105 EVP_PKEY *evp_pkey = PEM_read_bio_PrivateKey(bio, nullptr, nullptr, nullptr);
106 if (evp_pkey != nullptr) {
107 int alg_id = EVP_PKEY_base_id(evp_pkey);
108
109 switch (alg_id) {
110 case EVP_PKEY_RSA:
111 rsa_ = EVP_PKEY_get1_RSA(evp_pkey);
112 keyAlgorithm_ = ALGORITHM_RSA;
113 break;
114 case EVP_PKEY_DSA:
115 dsa_ = EVP_PKEY_get1_DSA(evp_pkey);
116 keyAlgorithm_ = ALGORITHM_DSA;
117 break;
118 case EVP_PKEY_DH:
119 dh_ = EVP_PKEY_get1_DH(evp_pkey);
120 keyAlgorithm_ = ALGORITHM_DH;
121 break;
122 case EVP_PKEY_EC:
123 ec_ = EVP_PKEY_get1_EC_KEY(evp_pkey);
124 keyAlgorithm_ = ALGORITHM_EC;
125 break;
126 default:
127 NETSTACK_LOGE("unknown key");
128 break;
129 }
130 } else {
131 rsa_ = PEM_read_bio_RSAPrivateKey(bio, nullptr, nullptr, nullptr);
132 }
133
134 EVP_PKEY_free(evp_pkey);
135 BIO_free(bio);
136
137 if (ec_ || rsa_ || dh_ || dsa_) {
138 keyIsNull_ = false;
139 }
140 }
141
DecodeData(const SecureData & data,KeyAlgorithm algorithm,const SecureData & passPhrase)142 void TLSKey::DecodeData(const SecureData &data, KeyAlgorithm algorithm, const SecureData &passPhrase)
143 {
144 if (data.Length() == 0) {
145 NETSTACK_LOGE("The parameter data is empty");
146 return;
147 }
148 keyAlgorithm_ = algorithm;
149 keyData_ = data;
150 keyPass_ = passPhrase;
151 BIO *bio = BIO_new_mem_buf(data.Data(), -1);
152 if (!bio) {
153 NETSTACK_LOGE("Failed to create bio buffer");
154 return;
155 }
156 rsa_ = PEM_read_bio_RSAPrivateKey(bio, nullptr, nullptr, nullptr);
157 if (rsa_) {
158 keyIsNull_ = false;
159 }
160 }
161
DecodeDer(KeyType type,KeyAlgorithm algorithm,const std::string & fileName,const SecureData & passPhrase)162 void TLSKey::DecodeDer(KeyType type, KeyAlgorithm algorithm, const std::string &fileName, const SecureData &passPhrase)
163 {
164 if (fileName.empty()) {
165 NETSTACK_LOGI("The parameter filename is empty");
166 return;
167 }
168 keyType_ = type;
169 keyAlgorithm_ = algorithm;
170 keyPass_ = passPhrase;
171 std::string realPath;
172 if (!CheckFilePath(fileName, realPath)) {
173 NETSTACK_LOGE("file name is error");
174 return;
175 }
176
177 FILE *fp = fopen(realPath.c_str(), FILE_OPEN_FLAG);
178 if (!fp) {
179 NETSTACK_LOGE("open file false");
180 return;
181 }
182 char keyDer[FILE_READ_KEY_LEN] = {0};
183 size_t keyLen = fread(keyDer, 1, FILE_READ_KEY_LEN, fp);
184 (void)fclose(fp);
185 if (!keyLen) {
186 NETSTACK_LOGE("Insufficient size bytes were read");
187 return;
188 }
189
190 const auto *key_data = reinterpret_cast<const unsigned char *>(keyDer);
191 if (type == PUBLIC_KEY) {
192 rsa_ = d2i_RSA_PUBKEY(nullptr, &key_data, static_cast<long>(keyLen));
193 } else {
194 rsa_ = d2i_RSAPrivateKey(nullptr, &key_data, static_cast<long>(keyLen));
195 }
196 if (!rsa_) {
197 NETSTACK_LOGE("rsa is null");
198 return;
199 }
200 keyIsNull_ = false;
201 }
202
SwitchAlgorithm(KeyType type,KeyAlgorithm algorithm,BIO * bio)203 void TLSKey::SwitchAlgorithm(KeyType type, KeyAlgorithm algorithm, BIO *bio)
204 {
205 switch (algorithm) {
206 case ALGORITHM_RSA:
207 rsa_ = (type == PUBLIC_KEY) ? PEM_read_bio_RSA_PUBKEY(bio, nullptr, nullptr, nullptr)
208 : PEM_read_bio_RSAPrivateKey(bio, nullptr, nullptr, nullptr);
209 if (rsa_) {
210 keyIsNull_ = false;
211 }
212 break;
213 case ALGORITHM_DSA:
214 dsa_ = (type == PUBLIC_KEY) ? PEM_read_bio_DSA_PUBKEY(bio, nullptr, nullptr, nullptr)
215 : PEM_read_bio_DSAPrivateKey(bio, nullptr, nullptr, nullptr);
216 if (dsa_) {
217 keyIsNull_ = false;
218 }
219 break;
220 case ALGORITHM_DH: {
221 EVP_PKEY *result = (type == PUBLIC_KEY) ? PEM_read_bio_PUBKEY(bio, nullptr, nullptr, nullptr)
222 : PEM_read_bio_PrivateKey(bio, nullptr, nullptr, nullptr);
223 if (result) {
224 dh_ = EVP_PKEY_get1_DH(result);
225 }
226 if (dh_) {
227 keyIsNull_ = false;
228 }
229 EVP_PKEY_free(result);
230 break;
231 }
232 case ALGORITHM_EC:
233 ec_ = (type == PUBLIC_KEY) ? PEM_read_bio_EC_PUBKEY(bio, nullptr, nullptr, nullptr)
234 : PEM_read_bio_ECPrivateKey(bio, nullptr, nullptr, nullptr);
235 if (ec_) {
236 keyIsNull_ = false;
237 }
238 break;
239 default:
240 NETSTACK_LOGE("algorithm = %{public}d is error", algorithm);
241 }
242 }
243
DecodePem(KeyType type,KeyAlgorithm algorithm,const std::string & fileName,const SecureData & passPhrase)244 void TLSKey::DecodePem(KeyType type, KeyAlgorithm algorithm, const std::string &fileName, const SecureData &passPhrase)
245 {
246 if (fileName.empty()) {
247 NETSTACK_LOGE("filename is empty");
248 return;
249 }
250 keyType_ = type;
251 keyAlgorithm_ = algorithm;
252 std::string realPath;
253 if (!CheckFilePath(fileName, realPath)) {
254 NETSTACK_LOGE("file name is error");
255 return;
256 }
257
258 FILE *fp = fopen(realPath.c_str(), FILE_OPEN_FLAG);
259 if (!fp) {
260 NETSTACK_LOGE("open file failed");
261 return;
262 }
263 char privateKey[FILE_READ_KEY_LEN] = {0};
264 if (!fread(privateKey, 1, FILE_READ_KEY_LEN, fp)) {
265 NETSTACK_LOGE("read file failed");
266 (void)fclose(fp);
267 return;
268 }
269 (void)fclose(fp);
270 const char *privateKeyData = static_cast<const char *>(privateKey);
271 BIO *bio = BIO_new_mem_buf(privateKeyData, -1);
272 if (!bio) {
273 NETSTACK_LOGE("bio is null");
274 return;
275 }
276 keyPass_ = passPhrase;
277 SwitchAlgorithm(type, algorithm, bio);
278 BIO_free(bio);
279 }
280
Clear(bool deep)281 void TLSKey::Clear(bool deep)
282 {
283 keyIsNull_ = true;
284 const auto algo = Algorithm();
285 if (algo == ALGORITHM_RSA && rsa_) {
286 if (deep) {
287 RSA_free(rsa_);
288 }
289 rsa_ = nullptr;
290 }
291 if (algo == ALGORITHM_DSA && dsa_) {
292 if (deep) {
293 DSA_free(dsa_);
294 }
295 dsa_ = nullptr;
296 }
297 if (algo == ALGORITHM_DH && dh_) {
298 if (deep) {
299 DH_free(dh_);
300 }
301 dh_ = nullptr;
302 }
303 if (algo == ALGORITHM_EC && ec_) {
304 if (deep) {
305 EC_KEY_free(ec_);
306 }
307 ec_ = nullptr;
308 }
309 if (algo == OPAQUE && opaque_) {
310 if (deep) {
311 EVP_PKEY_free(opaque_);
312 }
313 opaque_ = nullptr;
314 }
315 }
316
Algorithm() const317 KeyAlgorithm TLSKey::Algorithm() const
318 {
319 return keyAlgorithm_;
320 }
321
handle() const322 Handle TLSKey::handle() const
323 {
324 switch (keyAlgorithm_) {
325 case OPAQUE:
326 return Handle(OPAQUE);
327 case ALGORITHM_RSA:
328 return Handle(rsa_);
329 case ALGORITHM_DSA:
330 return Handle(dsa_);
331 case ALGORITHM_DH:
332 return Handle(dh_);
333 case ALGORITHM_EC:
334 return Handle(ec_);
335 default:
336 return Handle(nullptr);
337 }
338 }
339
GetKeyPass() const340 const SecureData &TLSKey::GetKeyPass() const
341 {
342 return keyPass_;
343 }
344
GetKeyData() const345 const SecureData &TLSKey::GetKeyData() const
346 {
347 return keyData_;
348 }
349 } // namespace TlsSocket
350 } // namespace NetStack
351 } // namespace OHOS
352