• 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_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