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
DecodeData(const SecureData & data,const SecureData & passPhrase)62 void TLSKey::DecodeData(const SecureData &data, const SecureData &passPhrase)
63 {
64 if (data.Length() == 0) {
65 NETSTACK_LOGE("The parameter data is empty");
66 return;
67 }
68 keyData_ = data;
69 keyPass_ = passPhrase;
70 BIO *bio = BIO_new_mem_buf(data.Data(), -1);
71 if (!bio) {
72 NETSTACK_LOGE("Failed to create bio buffer");
73 return;
74 }
75 EVP_PKEY *evp_pkey = PEM_read_bio_PrivateKey(bio, nullptr, nullptr, nullptr);
76 if (evp_pkey != nullptr) {
77 int alg_id = EVP_PKEY_base_id(evp_pkey);
78
79 switch (alg_id) {
80 case EVP_PKEY_RSA:
81 rsa_ = EVP_PKEY_get1_RSA(evp_pkey);
82 keyAlgorithm_ = ALGORITHM_RSA;
83 break;
84 case EVP_PKEY_DSA:
85 dsa_ = EVP_PKEY_get1_DSA(evp_pkey);
86 keyAlgorithm_ = ALGORITHM_DSA;
87 break;
88 case EVP_PKEY_DH:
89 dh_ = EVP_PKEY_get1_DH(evp_pkey);
90 keyAlgorithm_ = ALGORITHM_DH;
91 break;
92 case EVP_PKEY_EC:
93 ec_ = EVP_PKEY_get1_EC_KEY(evp_pkey);
94 keyAlgorithm_ = ALGORITHM_EC;
95 break;
96 default:
97 NETSTACK_LOGE("unknown key");
98 break;
99 }
100 } else {
101 rsa_ = PEM_read_bio_RSAPrivateKey(bio, nullptr, nullptr, nullptr);
102 }
103
104 EVP_PKEY_free(evp_pkey);
105 BIO_free(bio);
106
107 if (ec_ || rsa_ || dh_ || dsa_) {
108 keyIsNull_ = false;
109 }
110 }
111
DecodeData(const SecureData & data,KeyAlgorithm algorithm,const SecureData & passPhrase)112 void TLSKey::DecodeData(const SecureData &data, KeyAlgorithm algorithm, const SecureData &passPhrase)
113 {
114 if (data.Length() == 0) {
115 NETSTACK_LOGE("The parameter data is empty");
116 return;
117 }
118 keyAlgorithm_ = algorithm;
119 keyData_ = data;
120 keyPass_ = passPhrase;
121 BIO *bio = BIO_new_mem_buf(data.Data(), -1);
122 if (!bio) {
123 NETSTACK_LOGE("Failed to create bio buffer");
124 return;
125 }
126 rsa_ = PEM_read_bio_RSAPrivateKey(bio, nullptr, nullptr, nullptr);
127 if (rsa_) {
128 keyIsNull_ = false;
129 }
130 }
131
DecodeDer(KeyType type,KeyAlgorithm algorithm,const std::string & fileName,const SecureData & passPhrase)132 void TLSKey::DecodeDer(KeyType type, KeyAlgorithm algorithm, const std::string &fileName, const SecureData &passPhrase)
133 {
134 if (fileName.empty()) {
135 NETSTACK_LOGI("The parameter filename is empty");
136 return;
137 }
138 keyType_ = type;
139 keyAlgorithm_ = algorithm;
140 keyPass_ = passPhrase;
141 std::string realPath;
142 if (!CheckFilePath(fileName, realPath)) {
143 NETSTACK_LOGE("file name is error");
144 return;
145 }
146
147 FILE *fp = fopen(realPath.c_str(), FILE_OPEN_FLAG);
148 if (!fp) {
149 NETSTACK_LOGE("open file false");
150 return;
151 }
152 char keyDer[FILE_READ_KEY_LEN] = {0};
153 size_t keyLen = fread(keyDer, 1, FILE_READ_KEY_LEN, fp);
154 (void)fclose(fp);
155 if (!keyLen) {
156 NETSTACK_LOGE("Insufficient size bytes were read");
157 return;
158 }
159
160 const auto *key_data = reinterpret_cast<const unsigned char *>(keyDer);
161 if (type == PUBLIC_KEY) {
162 rsa_ = d2i_RSA_PUBKEY(nullptr, &key_data, static_cast<long>(keyLen));
163 } else {
164 rsa_ = d2i_RSAPrivateKey(nullptr, &key_data, static_cast<long>(keyLen));
165 }
166 if (!rsa_) {
167 NETSTACK_LOGE("rsa is null");
168 return;
169 }
170 keyIsNull_ = false;
171 }
172
SwitchAlgorithm(KeyType type,KeyAlgorithm algorithm,BIO * bio)173 void TLSKey::SwitchAlgorithm(KeyType type, KeyAlgorithm algorithm, BIO *bio)
174 {
175 switch (algorithm) {
176 case ALGORITHM_RSA:
177 rsa_ = (type == PUBLIC_KEY) ? PEM_read_bio_RSA_PUBKEY(bio, nullptr, nullptr, nullptr)
178 : PEM_read_bio_RSAPrivateKey(bio, nullptr, nullptr, nullptr);
179 if (rsa_) {
180 keyIsNull_ = false;
181 }
182 break;
183 case ALGORITHM_DSA:
184 dsa_ = (type == PUBLIC_KEY) ? PEM_read_bio_DSA_PUBKEY(bio, nullptr, nullptr, nullptr)
185 : PEM_read_bio_DSAPrivateKey(bio, nullptr, nullptr, nullptr);
186 if (dsa_) {
187 keyIsNull_ = false;
188 }
189 break;
190 case ALGORITHM_DH: {
191 EVP_PKEY *result = (type == PUBLIC_KEY) ? PEM_read_bio_PUBKEY(bio, nullptr, nullptr, nullptr)
192 : PEM_read_bio_PrivateKey(bio, nullptr, nullptr, nullptr);
193 if (result) {
194 dh_ = EVP_PKEY_get1_DH(result);
195 }
196 if (dh_) {
197 keyIsNull_ = false;
198 }
199 EVP_PKEY_free(result);
200 break;
201 }
202 case ALGORITHM_EC:
203 ec_ = (type == PUBLIC_KEY) ? PEM_read_bio_EC_PUBKEY(bio, nullptr, nullptr, nullptr)
204 : PEM_read_bio_ECPrivateKey(bio, nullptr, nullptr, nullptr);
205 if (ec_) {
206 keyIsNull_ = false;
207 }
208 break;
209 default:
210 NETSTACK_LOGE("algorithm = %{public}d is error", algorithm);
211 }
212 }
213
DecodePem(KeyType type,KeyAlgorithm algorithm,const std::string & fileName,const SecureData & passPhrase)214 void TLSKey::DecodePem(KeyType type, KeyAlgorithm algorithm, const std::string &fileName, const SecureData &passPhrase)
215 {
216 if (fileName.empty()) {
217 NETSTACK_LOGE("filename is empty");
218 return;
219 }
220 keyType_ = type;
221 keyAlgorithm_ = algorithm;
222 std::string realPath;
223 if (!CheckFilePath(fileName, realPath)) {
224 NETSTACK_LOGE("file name is error");
225 return;
226 }
227
228 FILE *fp = fopen(realPath.c_str(), FILE_OPEN_FLAG);
229 if (!fp) {
230 NETSTACK_LOGE("open file failed");
231 return;
232 }
233 char privateKey[FILE_READ_KEY_LEN] = {0};
234 if (!fread(privateKey, 1, FILE_READ_KEY_LEN, fp)) {
235 NETSTACK_LOGE("read file failed");
236 (void)fclose(fp);
237 return;
238 }
239 (void)fclose(fp);
240 const char *privateKeyData = static_cast<const char *>(privateKey);
241 BIO *bio = BIO_new_mem_buf(privateKeyData, -1);
242 if (!bio) {
243 NETSTACK_LOGE("bio is null");
244 return;
245 }
246 keyPass_ = passPhrase;
247 SwitchAlgorithm(type, algorithm, bio);
248 BIO_free(bio);
249 }
250
Clear(bool deep)251 void TLSKey::Clear(bool deep)
252 {
253 keyIsNull_ = true;
254 const auto algo = Algorithm();
255 if (algo == ALGORITHM_RSA && rsa_) {
256 if (deep) {
257 RSA_free(rsa_);
258 }
259 rsa_ = nullptr;
260 }
261 if (algo == ALGORITHM_DSA && dsa_) {
262 if (deep) {
263 DSA_free(dsa_);
264 }
265 dsa_ = nullptr;
266 }
267 if (algo == ALGORITHM_DH && dh_) {
268 if (deep) {
269 DH_free(dh_);
270 }
271 dh_ = nullptr;
272 }
273 if (algo == ALGORITHM_EC && ec_) {
274 if (deep) {
275 EC_KEY_free(ec_);
276 }
277 ec_ = nullptr;
278 }
279 if (algo == OPAQUE && opaque_) {
280 if (deep) {
281 EVP_PKEY_free(opaque_);
282 }
283 opaque_ = nullptr;
284 }
285 }
286
Algorithm() const287 KeyAlgorithm TLSKey::Algorithm() const
288 {
289 return keyAlgorithm_;
290 }
291
handle() const292 Handle TLSKey::handle() const
293 {
294 switch (keyAlgorithm_) {
295 case OPAQUE:
296 return Handle(OPAQUE);
297 case ALGORITHM_RSA:
298 return Handle(rsa_);
299 case ALGORITHM_DSA:
300 return Handle(dsa_);
301 case ALGORITHM_DH:
302 return Handle(dh_);
303 case ALGORITHM_EC:
304 return Handle(ec_);
305 default:
306 return Handle(nullptr);
307 }
308 }
309
GetKeyPass() const310 const SecureData &TLSKey::GetKeyPass() const
311 {
312 return keyPass_;
313 }
314
GetKeyData() const315 const SecureData &TLSKey::GetKeyData() const
316 {
317 return keyData_;
318 }
319 } // namespace TlsSocket
320 } // namespace NetStack
321 } // namespace OHOS
322