1 /*
2 * Copyright (c) 2024-2024 Huawei Device Co., Ltd.verify_cert_openssl_utils.h
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 #include "verify_cert_openssl_utils.h"
16 #include <cinttypes>
17 #include <cmath>
18 #include <fstream>
19
20 #include "openssl/pem.h"
21 #include "openssl/sha.h"
22
23 #include "constant.h"
24 #include "signature_tools_log.h"
25 #include "securec.h"
26 #include "verify_hap_openssl_utils.h"
27
28 namespace OHOS {
29 namespace SignatureTools {
30
31 const uint32_t VerifyCertOpensslUtils::MIN_CERT_CHAIN_LEN_NEED_VERIFY_CRL = 2;
32 const int32_t VerifyCertOpensslUtils::OPENSSL_READ_CRL_MAX_TIME = 1048576; // 1024 * 1024
33 const int32_t VerifyCertOpensslUtils::OPENSSL_READ_CRL_LEN_EACH_TIME = 1024;
34 const int32_t VerifyCertOpensslUtils::BASE64_ENCODE_LEN_OF_EACH_GROUP_DATA = 4;
35 const int32_t VerifyCertOpensslUtils::BASE64_ENCODE_PACKET_LEN = 3;
36
GenerateCertSignFromCertStack(STACK_OF (X509)* stackCerts,CertSign & certVisitSign)37 void VerifyCertOpensslUtils::GenerateCertSignFromCertStack(STACK_OF(X509)* stackCerts, CertSign& certVisitSign)
38 {
39 if (stackCerts == nullptr) {
40 return;
41 }
42 for (int32_t i = 0; i < sk_X509_num(stackCerts); i++) {
43 X509* x509Cert = sk_X509_value(stackCerts, i);
44 if (x509Cert == nullptr) {
45 continue;
46 }
47 certVisitSign[x509Cert] = false;
48 }
49 }
50
ClearCertVisitSign(CertSign & certVisitSign)51 void VerifyCertOpensslUtils::ClearCertVisitSign(CertSign& certVisitSign)
52 {
53 for (auto& certPair : certVisitSign) {
54 certPair.second = false;
55 }
56 }
57
GetCertsChain(CertChain & certsChain,CertSign & certVisitSign)58 bool VerifyCertOpensslUtils::GetCertsChain(CertChain& certsChain, CertSign& certVisitSign)
59 {
60 if (certsChain.empty() || certVisitSign.empty()) {
61 SIGNATURE_TOOLS_LOGE("input is invalid");
62 return false;
63 }
64 X509* issuerCert;
65 X509* cert = certsChain[0];
66 while ((issuerCert = FindCertOfIssuer(cert, certVisitSign)) != nullptr) {
67 certsChain.push_back(X509_dup(issuerCert));
68 certVisitSign[issuerCert] = true;
69 cert = issuerCert;
70 }
71
72 if (static_cast<int>(certsChain.size()) < MIN_CERTS_NUM) {
73 SIGNATURE_TOOLS_LOGE("certchain length is less than %d.", MIN_CERTS_NUM);
74 return false;
75 }
76
77 X509_NAME* aName = X509_get_issuer_name(cert);
78 X509_NAME* bName = X509_get_subject_name(cert);
79 if (aName == NULL || bName == NULL) {
80 SIGNATURE_TOOLS_LOGE("X509_NAME is NULL");
81 return false;
82 }
83 if (X509_NAME_cmp(aName, bName) != 0) {
84 SIGNATURE_TOOLS_LOGD("without root cert, ignore!");
85 return true;
86 }
87
88 if (CertVerify(cert, cert) == false) {
89 SIGNATURE_TOOLS_LOGE("root cert is invalid");
90 return false;
91 }
92 return true;
93 }
94
FindCertOfIssuer(X509 * cert,CertSign & certVisitSign)95 X509* VerifyCertOpensslUtils::FindCertOfIssuer(X509* cert, CertSign& certVisitSign)
96 {
97 if (cert == nullptr) {
98 SIGNATURE_TOOLS_LOGE("input is invalid");
99 return nullptr;
100 }
101 X509_NAME* signCertIssuerName = X509_get_issuer_name(cert);
102 for (auto certPair : certVisitSign) {
103 if (certPair.second) {
104 continue;
105 }
106 X509* issuerCert = certPair.first;
107 X509_NAME* issuerCertSubjectName = X509_get_subject_name(issuerCert);
108 /* verify sign and issuer */
109 if (X509NameCompare(issuerCertSubjectName, signCertIssuerName) &&
110 CertVerify(cert, issuerCert)) {
111 return issuerCert;
112 }
113 }
114 return nullptr;
115 }
116
CertVerify(X509 * cert,const X509 * issuerCert)117 bool VerifyCertOpensslUtils::CertVerify(X509* cert, const X509* issuerCert)
118 {
119 if (cert == nullptr) {
120 SIGNATURE_TOOLS_LOGE("input is invalid");
121 return false;
122 }
123 EVP_PKEY* caPublicKey = X509_get0_pubkey(issuerCert);
124 if (caPublicKey == nullptr) {
125 VerifyHapOpensslUtils::GetOpensslErrorMessage();
126 SIGNATURE_TOOLS_LOGE("get pubkey from caCert failed");
127 return false;
128 }
129 return X509_verify(cert, caPublicKey) > 0;
130 }
131
VerifyCertChainPeriodOfValidity(CertChain & certsChain,const ASN1_TYPE * signTime)132 bool VerifyCertOpensslUtils::VerifyCertChainPeriodOfValidity(CertChain& certsChain,
133 const ASN1_TYPE* signTime)
134 {
135 if (certsChain.empty()) {
136 return false;
137 }
138 for (uint32_t i = 0; i < certsChain.size() - 1; i++) {
139 if (certsChain[i] == nullptr) {
140 SIGNATURE_TOOLS_LOGE("%dst cert is nullptr", i);
141 return false;
142 }
143 const ASN1_TIME* notBefore = X509_get0_notBefore(certsChain[i]);
144 const ASN1_TIME* notAfter = X509_get0_notAfter(certsChain[i]);
145 if (!CheckSignTimeInValidPeriod(signTime, notBefore, notAfter)) {
146 SIGNATURE_TOOLS_LOGE("%dst cert is not in period of validity", i);
147 return false;
148 }
149 }
150 return true;
151 }
152
CheckAsn1TimeIsValid(const ASN1_TIME * asn1Time)153 bool VerifyCertOpensslUtils::CheckAsn1TimeIsValid(const ASN1_TIME* asn1Time)
154 {
155 if (asn1Time == nullptr || asn1Time->data == nullptr) {
156 return false;
157 }
158 return true;
159 }
160
CheckAsn1TypeIsValid(const ASN1_TYPE * asn1Type)161 bool VerifyCertOpensslUtils::CheckAsn1TypeIsValid(const ASN1_TYPE* asn1Type)
162 {
163 if (asn1Type == nullptr || asn1Type->value.asn1_string == nullptr ||
164 asn1Type->value.asn1_string->data == nullptr) {
165 return false;
166 }
167 return true;
168 }
169
CheckSignTimeInValidPeriod(const ASN1_TYPE * signTime,const ASN1_TIME * notBefore,const ASN1_TIME * notAfter)170 bool VerifyCertOpensslUtils::CheckSignTimeInValidPeriod(const ASN1_TYPE* signTime,
171 const ASN1_TIME* notBefore,
172 const ASN1_TIME* notAfter)
173 {
174 if (!CheckAsn1TimeIsValid(notBefore) || !CheckAsn1TimeIsValid(notAfter)) {
175 SIGNATURE_TOOLS_LOGE("no valid period");
176 return false;
177 }
178 if (!CheckAsn1TypeIsValid(signTime)) {
179 SIGNATURE_TOOLS_LOGE("signTime is invalid");
180 return false;
181 }
182 if (ASN1_TIME_compare(notBefore, signTime->value.asn1_string) > 0 ||
183 ASN1_TIME_compare(notAfter, signTime->value.asn1_string) < 0) {
184 SIGNATURE_TOOLS_LOGE("Out of valid period, signTime: %s, "
185 "notBefore:%s, notAfter : %s",
186 signTime->value.asn1_string->data, notBefore->data, notAfter->data);
187 return false;
188 }
189 SIGNATURE_TOOLS_LOGD("signTime type: %d, data: %s, "
190 "notBefore:%s, notAfter : %s",
191 signTime->type, signTime->value.asn1_string->data,
192 notBefore->data, notAfter->data);
193 return true;
194 }
195
VerifyCrl(CertChain & certsChain,STACK_OF (X509_CRL)* crls,Pkcs7Context & pkcs7Context)196 bool VerifyCertOpensslUtils::VerifyCrl(CertChain& certsChain, STACK_OF(X509_CRL)* crls,
197 Pkcs7Context& pkcs7Context)
198 {
199 if (certsChain.empty()) {
200 SIGNATURE_TOOLS_LOGE("cert chain is null");
201 return false;
202 }
203 /* get signed cert's issuer and then it will be used to find local crl */
204 if (!GetIssuerFromX509(certsChain[0], pkcs7Context.certIssuer)) {
205 SIGNATURE_TOOLS_LOGE("get issuer of signed cert failed");
206 return false;
207 }
208 X509_CRL* targetCrl = GetCrlBySignedCertIssuer(crls, certsChain[0]);
209 /* crl is optional */
210 if (targetCrl != nullptr && certsChain.size() >= MIN_CERT_CHAIN_LEN_NEED_VERIFY_CRL) {
211 /* if it include crl, it must be verified by ca cert */
212 if (X509_CRL_verify(targetCrl, X509_get0_pubkey(certsChain[1])) <= 0) {
213 VerifyHapOpensslUtils::GetOpensslErrorMessage();
214 SIGNATURE_TOOLS_LOGE("verify crlInPackage failed");
215 return false;
216 }
217 }
218 return true;
219 }
220
GetCrlBySignedCertIssuer(STACK_OF (X509_CRL)* crls,const X509 * cert)221 X509_CRL* VerifyCertOpensslUtils::GetCrlBySignedCertIssuer(STACK_OF(X509_CRL)* crls, const X509* cert)
222 {
223 if (crls == nullptr || cert == nullptr) {
224 return nullptr;
225 }
226 X509_NAME* certIssuerName = X509_get_issuer_name(cert);
227 for (int32_t i = 0; i < sk_X509_CRL_num(crls); i++) {
228 X509_CRL* x509Crl = sk_X509_CRL_value(crls, i);
229 if (x509Crl == nullptr) {
230 continue;
231 }
232 X509_NAME* crlIssuer = X509_CRL_get_issuer(x509Crl);
233 if (X509NameCompare(crlIssuer, certIssuerName)) {
234 return x509Crl;
235 }
236 }
237 return nullptr;
238 }
239
X509NameCompare(const X509_NAME * a,const X509_NAME * b)240 bool VerifyCertOpensslUtils::X509NameCompare(const X509_NAME* a, const X509_NAME* b)
241 {
242 if (a == nullptr || b == nullptr) {
243 return false;
244 }
245 return X509_NAME_cmp(a, b) == 0;
246 }
247
GetSubjectFromX509(const X509 * cert,std::string & subject)248 bool VerifyCertOpensslUtils::GetSubjectFromX509(const X509* cert, std::string& subject)
249 {
250 if (cert == nullptr) {
251 SIGNATURE_TOOLS_LOGE("cert is nullptr");
252 return false;
253 }
254 X509_NAME* name = X509_get_subject_name(cert);
255 subject = GetDnToString(name);
256 SIGNATURE_TOOLS_LOGD("subject = %s", subject.c_str());
257 return true;
258 }
259
GetIssuerFromX509(const X509 * cert,std::string & issuer)260 bool VerifyCertOpensslUtils::GetIssuerFromX509(const X509* cert, std::string& issuer)
261 {
262 if (cert == nullptr) {
263 SIGNATURE_TOOLS_LOGE("cert is nullptr");
264 return false;
265 }
266 X509_NAME* name = X509_get_issuer_name(cert);
267 issuer = GetDnToString(name);
268 SIGNATURE_TOOLS_LOGD("cert issuer = %s", issuer.c_str());
269 return true;
270 }
271
GetDnToString(X509_NAME * x509Name)272 std::string VerifyCertOpensslUtils::GetDnToString(X509_NAME* x509Name)
273 {
274 if (x509Name == nullptr) {
275 return "";
276 }
277 std::string countryNameString;
278 GetTextFromX509Name(x509Name, NID_countryName, countryNameString);
279 std::string organizationName;
280 GetTextFromX509Name(x509Name, NID_organizationName, organizationName);
281 std::string organizationalUnitName;
282 GetTextFromX509Name(x509Name, NID_organizationalUnitName, organizationalUnitName);
283 std::string commonName;
284 GetTextFromX509Name(x509Name, NID_commonName, commonName);
285 return "C=" + countryNameString + ", O=" + organizationName + ", OU=" + organizationalUnitName +
286 ", CN=" + commonName;
287 }
288
GetTextFromX509Name(X509_NAME * name,int32_t nId,std::string & text)289 void VerifyCertOpensslUtils::GetTextFromX509Name(X509_NAME* name, int32_t nId, std::string& text)
290 {
291 int32_t textLen = X509_NAME_get_text_by_NID(name, nId, nullptr, 0);
292 if (textLen <= 0) {
293 return;
294 }
295 std::unique_ptr<char[]> buffer = std::make_unique<char[]>(textLen + 1);
296 if (X509_NAME_get_text_by_NID(name, nId, buffer.get(), textLen + 1) != textLen) {
297 return;
298 }
299 text = std::string(buffer.get());
300 }
301 } // namespace SignatureTools
302 } // namespace OHOS