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