• 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_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