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