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