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