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_certificate.h"
17
18 #include <cerrno>
19 #include <cstdlib>
20 #include <memory>
21 #include <map>
22 #include <securec.h>
23
24 #include <openssl/asn1.h>
25 #include <openssl/bn.h>
26 #include <openssl/pem.h>
27
28 #include "netstack_log.h"
29 #include "tls_utils.h"
30
31 namespace OHOS {
32 namespace NetStack {
33 namespace {
34 constexpr const char *BIO_FILE_FLAG = "r";
35 constexpr const char *FILE_OPEN_FLAG = "rb";
36 constexpr const char *CERT_VERSION_FLAG = "V";
37 constexpr int FILE_READ_CERT_LEN = 4096;
38 } // namespace
39
TLSCertificate(const std::string & data,EncodingFormat format,CertType certType)40 TLSCertificate::TLSCertificate(const std::string &data, EncodingFormat format, CertType certType)
41 {
42 rawData_.encodingFormat = PEM;
43 if (data.empty()) {
44 NETSTACK_LOGE("The parameter data is empty");
45 return;
46 }
47 switch (format) {
48 case PEM:
49 if (!CertificateFromPem(data, certType)) {
50 NETSTACK_LOGE("return CertificateFromPem(data, certs) is false");
51 }
52 break;
53 case DER:
54 if (!CertificateFromDer(data, certType)) {
55 NETSTACK_LOGE("return CertificateFromDer(data, certs) is false");
56 }
57 break;
58 default:
59 NETSTACK_LOGE("%{public}u is not supported, only support PEM =0 and DER = 1", format);
60 }
61 }
62
TLSCertificate(const std::string & data,CertType certType)63 TLSCertificate::TLSCertificate(const std::string &data, CertType certType)
64 {
65 rawData_.encodingFormat = PEM;
66 if (data.empty()) {
67 NETSTACK_LOGE("data is null in the TLSCertificate constructor");
68 return;
69 }
70 if (!CertificateFromData(data, certType)) {
71 NETSTACK_LOGE("return CertificatesFromPem(data, certs) is false");
72 }
73 }
74
TLSCertificate(const TLSCertificate & other)75 TLSCertificate::TLSCertificate(const TLSCertificate &other)
76 {
77 *this = other;
78 }
79
operator =(const TLSCertificate & other)80 TLSCertificate &TLSCertificate::operator=(const TLSCertificate &other)
81 {
82 if (other.x509_ != nullptr) {
83 x509_ = X509_new();
84 x509_ = other.x509_;
85 }
86 version_ = other.version_;
87 serialNumber_ = other.serialNumber_;
88 signatureAlgorithm_ = other.signatureAlgorithm_;
89 localCertString_ = other.localCertString_;
90 caCertString_ = other.caCertString_;
91 rawData_.data = other.rawData_.data;
92 rawData_.encodingFormat = other.rawData_.encodingFormat;
93 return *this;
94 }
95
CertificateFromData(const std::string & data,CertType certType)96 bool TLSCertificate::CertificateFromData(const std::string &data, CertType certType)
97 {
98 if (data.empty()) {
99 NETSTACK_LOGE("The parameter data is empty");
100 return false;
101 }
102 BIO *bio = BIO_new_mem_buf(data.c_str(), -1);
103 if (!bio) {
104 NETSTACK_LOGE("create BIO mem buf failed!");
105 return false;
106 }
107 X509 *x509 = PEM_read_bio_X509(bio, nullptr, nullptr, nullptr);
108 BIO_free(bio);
109
110 if (!x509) {
111 NETSTACK_LOGE("x509 is null");
112 return false;
113 }
114
115 x509_ = X509_dup(x509);
116 if (!AnalysisCertificate(certType, x509)) {
117 NETSTACK_LOGE("Analysis certificate is false");
118 X509_free(x509);
119 return false;
120 }
121 X509_free(x509);
122 return true;
123 }
124
CertificateFromPem(const std::string & data,CertType certType)125 bool TLSCertificate::CertificateFromPem(const std::string &data, CertType certType)
126 {
127 BIO *bio = BIO_new_file((data.c_str()), BIO_FILE_FLAG);
128 if (!bio) {
129 NETSTACK_LOGE("bio new file fail errno");
130 return false;
131 }
132 X509 *x509 = PEM_read_bio_X509(bio, nullptr, nullptr, nullptr);
133 BIO_free(bio);
134
135 if (!x509) {
136 NETSTACK_LOGE("x509 is null");
137 return false;
138 }
139
140 x509_ = X509_dup(x509);
141 if (!AnalysisCertificate(certType, x509)) {
142 NETSTACK_LOGE("Analysis certificate is false");
143 X509_free(x509);
144 return false;
145 }
146 X509_free(x509);
147 return true;
148 }
149
CertificateFromDer(const std::string & data,CertType certType)150 bool TLSCertificate::CertificateFromDer(const std::string &data, CertType certType)
151 {
152 if (data.empty()) {
153 NETSTACK_LOGE("The certificate file to be converted is empty");
154 return false;
155 }
156 std::string realPath;
157 if (!CheckFilePath(data, realPath)) {
158 NETSTACK_LOGE("file name is error");
159 return false;
160 }
161
162 FILE *fp = fopen(realPath.c_str(), FILE_OPEN_FLAG);
163 if (!fp) {
164 NETSTACK_LOGE("Couldn't open file for reading, error string %{public}s", strerror(errno));
165 return false;
166 }
167 unsigned char cert[FILE_READ_CERT_LEN] = {};
168 size_t certLen = fread(cert, 1, FILE_READ_CERT_LEN, fp);
169 fclose(fp);
170 if (!certLen) {
171 NETSTACK_LOGE("Insufficient size bytes were read");
172 return false;
173 }
174 const auto *cert_data = reinterpret_cast<const unsigned char *>(cert);
175 X509 *x509 = d2i_X509(nullptr, &cert_data, static_cast<long>(certLen));
176 if (!x509) {
177 NETSTACK_LOGE("x509 is null");
178 return false;
179 }
180 x509_ = X509_dup(x509);
181 if (!AnalysisCertificate(certType, x509)) {
182 NETSTACK_LOGE("Analysis certificate is false");
183 X509_free(x509);
184 return false;
185 }
186 X509_free(x509);
187 return true;
188 }
189
AnalysisCertificate(CertType certType,X509 * x509)190 bool TLSCertificate::AnalysisCertificate(CertType certType, X509 *x509)
191 {
192 if (!x509) {
193 NETSTACK_LOGE("x509 is null");
194 return false;
195 }
196 if (certType == CA_CERT) {
197 if (!CaCertToString(x509)) {
198 NETSTACK_LOGE("Get CA cert as string failed");
199 return false;
200 }
201 }
202 if (certType == LOCAL_CERT) {
203 if (!LocalCertToString(x509)) {
204 NETSTACK_LOGE("Failed to convert certificate to string");
205 return false;
206 }
207 }
208 if (!SetLocalCertRawData(x509)) {
209 NETSTACK_LOGE("Failed to set x509 certificata Serialization data");
210 return false;
211 }
212 if (!SetX509Version(x509)) {
213 NETSTACK_LOGE("Failed to set x509 version");
214 return false;
215 }
216 if (!SetSerialNumber(x509)) {
217 NETSTACK_LOGE("Failed to set serial number");
218 return false;
219 }
220 if (!SetNotValidTime(x509)) {
221 NETSTACK_LOGE("Failed to set not valid time");
222 return false;
223 }
224 if (!SetSignatureAlgorithm(x509)) {
225 NETSTACK_LOGE("Failed to set signature algorithm");
226 return false;
227 }
228 return true;
229 }
230
CaCertToString(X509 * x509)231 bool TLSCertificate::CaCertToString(X509 *x509)
232 {
233 if (!x509) {
234 NETSTACK_LOGE("x509 is null");
235 return false;
236 }
237 BIO *bio = BIO_new(BIO_s_mem());
238 X509_print(bio, x509);
239 char data[FILE_READ_CERT_LEN] = {};
240 if (!BIO_read(bio, data, FILE_READ_CERT_LEN)) {
241 NETSTACK_LOGE("Ca certificate to string BIO_read is false");
242 BIO_free(bio);
243 return false;
244 }
245 caCertString_ = std::string(data);
246 BIO_free(bio);
247 return true;
248 }
249
LocalCertToString(X509 * x509)250 bool TLSCertificate::LocalCertToString(X509 *x509)
251 {
252 if (!x509) {
253 NETSTACK_LOGE("x509 is null");
254 return false;
255 }
256 BIO *bio = BIO_new(BIO_s_mem());
257 if (!bio) {
258 NETSTACK_LOGE("bio is null");
259 return false;
260 }
261 X509_print(bio, x509);
262 char data[FILE_READ_CERT_LEN] = {};
263 if (!BIO_read(bio, data, FILE_READ_CERT_LEN)) {
264 NETSTACK_LOGE("Local certificate to string BIO_read is false");
265 BIO_free(bio);
266 return false;
267 }
268 localCertString_ = std::string(data);
269 BIO_free(bio);
270 return true;
271 }
272
SetX509Version(X509 * x509)273 bool TLSCertificate::SetX509Version(X509 *x509)
274 {
275 if (!x509) {
276 NETSTACK_LOGE("x509 is null");
277 return false;
278 }
279 auto ver = X509_get_version(x509) + 1;
280 version_ = CERT_VERSION_FLAG + std::to_string(ver);
281 NETSTACK_LOGI("tls version_ %{public}s", version_.c_str());
282 return true;
283 }
284
SetSerialNumber(X509 * x509)285 bool TLSCertificate::SetSerialNumber(X509 *x509)
286 {
287 if (!x509) {
288 NETSTACK_LOGE("x509 is null");
289 return false;
290 }
291 ASN1_INTEGER *serial = X509_get_serialNumber(x509);
292 if (!serial) {
293 NETSTACK_LOGE("Failed to get serial number");
294 return false;
295 }
296 if (!serial->length) {
297 NETSTACK_LOGE("Serial length error");
298 return false;
299 }
300 BIGNUM *bn = ASN1_INTEGER_to_BN(serial, nullptr);
301 if (!bn) {
302 NETSTACK_LOGE("Unable to convert ASN1INTEGER to BN");
303 return false;
304 }
305 serialNumber_ = BN_bn2hex(bn);
306 BN_free(bn);
307 return true;
308 }
309
SetNotValidTime(X509 * x509)310 bool TLSCertificate::SetNotValidTime(X509 *x509)
311 {
312 if (!x509) {
313 NETSTACK_LOGE("x509 is null");
314 return false;
315 }
316 ASN1_TIME *before = X509_get_notBefore(x509);
317 if (!before) {
318 NETSTACK_LOGE("before is null");
319 return false;
320 }
321 tm tmBefore = {0};
322 if (!ASN1_TIME_to_tm(before, &tmBefore)) {
323 NETSTACK_LOGE("ASN1_TIME_to_tm before is false");
324 return false;
325 }
326
327 ASN1_TIME *after = X509_get_notAfter(x509);
328 if (!after) {
329 NETSTACK_LOGE("after is null");
330 return false;
331 }
332 tm tmAfter;
333 if (!ASN1_TIME_to_tm(after, &tmAfter)) {
334 NETSTACK_LOGE("ASN1_TIME_to_tm before is false");
335 return false;
336 }
337 return true;
338 }
339
SetSignatureAlgorithm(X509 * x509)340 bool TLSCertificate::SetSignatureAlgorithm(X509 *x509)
341 {
342 if (!x509) {
343 NETSTACK_LOGE("x509 is null");
344 return false;
345 }
346 int signNid = X509_get_signature_nid(x509);
347 const char *sign = OBJ_nid2sn(signNid);
348 if (!sign) {
349 NETSTACK_LOGE("OBJ_nid2sn is null");
350 return false;
351 }
352 signatureAlgorithm_ = sign;
353 return true;
354 }
355
SetLocalCertRawData(X509 * x509)356 bool TLSCertificate::SetLocalCertRawData(X509 *x509)
357 {
358 if (!x509) {
359 NETSTACK_LOGE("x509 is null");
360 return false;
361 }
362 int32_t length = i2d_X509(x509, nullptr);
363 if (length <= 0) {
364 NETSTACK_LOGE("Failed to convert x509 to der format, length is %{public}d", length);
365 return false;
366 }
367 unsigned char *der = nullptr;
368 (void)i2d_X509(x509, &der);
369 SecureData data(der, length);
370 rawData_.data = data;
371 OPENSSL_free(der);
372 rawData_.encodingFormat = DER;
373 return true;
374 }
375
GetSignatureAlgorithm() const376 std::string TLSCertificate::GetSignatureAlgorithm() const
377 {
378 return signatureAlgorithm_;
379 }
GetLocalCertString() const380 std::string TLSCertificate::GetLocalCertString() const
381 {
382 return localCertString_;
383 }
384
handle() const385 Handle TLSCertificate::handle() const
386 {
387 return Handle(x509_);
388 }
389
GetLocalCertRawData() const390 const X509CertRawData &TLSCertificate::GetLocalCertRawData() const
391 {
392 return rawData_;
393 }
394 } // namespace NetStack
395 } // namespace OHOS
396