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