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