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