1/* 2 * Copyright (c) 2024-2024 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#include "verify_hap_openssl_utils.h" 16#include "signature_tools_log.h" 17#include "openssl/asn1.h" 18#include "openssl/bio.h" 19#include "openssl/crypto.h" 20#include "openssl/err.h" 21#include "openssl/obj_mac.h" 22#include "openssl/objects.h" 23#include "openssl/rsa.h" 24#include "openssl/x509.h" 25#include "openssl/pem.h" 26#include "constant.h" 27#include "signature_info.h" 28 29namespace OHOS { 30namespace SignatureTools { 31using Pkcs7SignerInfoStack = STACK_OF(PKCS7_SIGNER_INFO); 32using X509AttributeStack = STACK_OF(X509_ATTRIBUTE); 33const int32_t VerifyHapOpensslUtils::OPENSSL_PKCS7_VERIFY_SUCCESS = 1; 34const int32_t VerifyHapOpensslUtils::OPENSSL_ERR_MESSAGE_MAX_LEN = 1024; 35/* 36* OPENSSL_READ_DATA_MAX_TIME * OPENSSL_READ_DATA_LEN_EACH_TIME < 2GBytes. 37* make the maximum size of data that can be read each time be 1 KBytes, 38* so the maximum times of read data is 1024 * 1024 * 2 = 2097152; 39*/ 40const int32_t VerifyHapOpensslUtils::OPENSSL_READ_DATA_MAX_TIME = 2097152; 41const int32_t VerifyHapOpensslUtils::OPENSSL_READ_DATA_LEN_EACH_TIME = 1024; 42/* Signature algorithm OID for extended PKCS7 */ 43const std::string VerifyHapOpensslUtils::PKCS7_EXT_SHAWITHRSA_PSS = PKCS7_EXT_SIGNATURE_OID; 44const int32_t VerifyHapOpensslUtils::MAX_OID_LENGTH = 128; 45 46bool VerifyHapOpensslUtils::ParsePkcs7Package(const unsigned char packageData[], 47 uint32_t packageLen, Pkcs7Context& pkcs7Context) 48{ 49 if (packageData == nullptr || packageLen == 0) { 50 SIGNATURE_TOOLS_LOGE("invalid input"); 51 return false; 52 } 53 pkcs7Context.p7 = d2i_PKCS7(nullptr, &packageData, packageLen); 54 if (!CheckPkcs7SignedDataIsValid(pkcs7Context.p7)) { 55 GetOpensslErrorMessage(); 56 SIGNATURE_TOOLS_LOGE("p7 is invalid"); 57 return false; 58 } 59 if (!GetContentInfo(pkcs7Context.p7->d.sign->contents, pkcs7Context.content)) { 60 SIGNATURE_TOOLS_LOGE("Get content from pkcs7 failed"); 61 return false; 62 } 63 return true; 64} 65 66bool VerifyHapOpensslUtils::GetCertChains(PKCS7* p7, Pkcs7Context& pkcs7Context) 67{ 68 if (!CheckPkcs7SignedDataIsValid(p7)) { 69 SIGNATURE_TOOLS_LOGE("p7 is invalid"); 70 return false; 71 } 72 CertSign certVisitSign; 73 VerifyCertOpensslUtils::GenerateCertSignFromCertStack(p7->d.sign->cert, certVisitSign); 74 Pkcs7SignerInfoStack* signerInfoStack = PKCS7_get_signer_info(p7); 75 if (signerInfoStack == nullptr) { 76 SIGNATURE_TOOLS_LOGE("get signerInfoStack error"); 77 GetOpensslErrorMessage(); 78 return false; 79 } 80 int32_t signCount = sk_PKCS7_SIGNER_INFO_num(signerInfoStack); 81 if (signCount <= 0) { 82 SIGNATURE_TOOLS_LOGE("can not find signinfo"); 83 return false; 84 } 85 for (int32_t i = 0; i < signCount; i++) { 86 /* get ith signInfo */ 87 PKCS7_SIGNER_INFO* signInfo = sk_PKCS7_SIGNER_INFO_value(signerInfoStack, i); 88 if (signInfo == nullptr) { 89 SIGNATURE_TOOLS_LOGE("signInfo %dst is nullptr", i); 90 return false; 91 } 92 /* GET X509 certificate */ 93 X509* cert = PKCS7_cert_from_signer_info(p7, signInfo); 94 if (cert == nullptr) { 95 SIGNATURE_TOOLS_LOGE("get cert for %dst signInfo failed", i); 96 return false; 97 } 98 CertChain certChain; 99 pkcs7Context.certChain.push_back(certChain); 100 pkcs7Context.certChain[i].push_back(X509_dup(cert)); 101 VerifyCertOpensslUtils::ClearCertVisitSign(certVisitSign); 102 certVisitSign[cert] = true; 103 if (!VerifyCertChain(pkcs7Context.certChain[i], p7, signInfo, pkcs7Context, certVisitSign)) { 104 SIGNATURE_TOOLS_LOGE("verify %dst certchain failed", i); 105 return false; 106 } 107 } 108 return true; 109} 110 111bool VerifyHapOpensslUtils::VerifyCertChain(CertChain& certsChain, PKCS7* p7, 112 PKCS7_SIGNER_INFO* signInfo, 113 Pkcs7Context& pkcs7Context, 114 CertSign& certVisitSign) 115{ 116 if (!VerifyCertOpensslUtils::GetCertsChain(certsChain, certVisitSign)) { 117 SIGNATURE_TOOLS_LOGE("get cert chain for signInfo failed"); 118 return false; 119 } 120 ASN1_TYPE* signTime = PKCS7_get_signed_attribute(signInfo, NID_pkcs9_signingTime); 121 if (!VerifyCertOpensslUtils::VerifyCertChainPeriodOfValidity(certsChain, signTime)) { 122 SIGNATURE_TOOLS_LOGE("VerifyCertChainPeriodOfValidity for signInfo failed"); 123 return false; 124 } 125 return true; 126} 127 128bool VerifyHapOpensslUtils::CheckPkcs7SignedDataIsValid(const PKCS7* p7) 129{ 130 if (p7 == nullptr || !PKCS7_type_is_signed(p7) || p7->d.sign == nullptr) { 131 return false; 132 } 133 return true; 134} 135 136bool VerifyHapOpensslUtils::GetCrlStack(PKCS7* p7, STACK_OF(X509_CRL)* x509Crl) 137{ 138 if (!CheckPkcs7SignedDataIsValid(p7)) { 139 return false; 140 } 141 x509Crl = p7->d.sign->crl; 142 return true; 143} 144 145bool VerifyHapOpensslUtils::VerifyPkcs7(Pkcs7Context& pkcs7Context) 146{ 147 if (!CheckPkcs7SignedDataIsValid(pkcs7Context.p7)) { 148 SIGNATURE_TOOLS_LOGE("p7 type is invalid signed_data_pkcs7"); 149 return false; 150 } 151 if (!VerifyPkcs7SignedData(pkcs7Context)) { 152 SIGNATURE_TOOLS_LOGE("verify p7 error"); 153 return false; 154 } 155 return true; 156} 157 158bool VerifyHapOpensslUtils::VerifyPkcs7SignedData(Pkcs7Context& pkcs7Context) 159{ 160 /* get signed data which was used to be signed */ 161 BIO* p7Bio = PKCS7_dataDecode(pkcs7Context.p7, nullptr, nullptr, nullptr); 162 if (p7Bio == nullptr) { 163 SIGNATURE_TOOLS_LOGE("get p7bio error"); 164 GetOpensslErrorMessage(); 165 return false; 166 } 167 char buf[OPENSSL_READ_DATA_LEN_EACH_TIME] = { 0 }; 168 int32_t readLen = BIO_read(p7Bio, buf, sizeof(buf)); 169 int32_t readTime = 0; 170 while ((readLen > 0) && (++readTime < OPENSSL_READ_DATA_MAX_TIME)) { 171 readLen = BIO_read(p7Bio, buf, sizeof(buf)); 172 } 173 Pkcs7SignerInfoStack* signerInfoStack = PKCS7_get_signer_info(pkcs7Context.p7); 174 if (signerInfoStack == nullptr) { 175 SIGNATURE_TOOLS_LOGE("get signerInfoStack error"); 176 BIO_free_all(p7Bio); 177 GetOpensslErrorMessage(); 178 return false; 179 } 180 /* get the num of signInfo */ 181 int32_t signCount = sk_PKCS7_SIGNER_INFO_num(signerInfoStack); 182 if (signCount <= 0) { 183 SIGNATURE_TOOLS_LOGE("can not find signinfo"); 184 BIO_free_all(p7Bio); 185 return false; 186 } 187 for (int32_t i = 0; i < signCount; i++) { 188 if (!VerifySignInfo(signerInfoStack, p7Bio, i, pkcs7Context)) { 189 SIGNATURE_TOOLS_LOGE("Verify %dst signInfo failed", i); 190 BIO_free_all(p7Bio); 191 return false; 192 } 193 } 194 BIO_free_all(p7Bio); 195 return true; 196} 197 198bool VerifyHapOpensslUtils::VerifySignInfo(STACK_OF(PKCS7_SIGNER_INFO)* signerInfoStack, 199 BIO* p7Bio, int32_t signInfoNum, Pkcs7Context& pkcs7Context) 200{ 201 if (signerInfoStack == nullptr || p7Bio == nullptr) { 202 SIGNATURE_TOOLS_LOGE("invalid input"); 203 return false; 204 } 205 /* get signInfo */ 206 PKCS7_SIGNER_INFO* signInfo = sk_PKCS7_SIGNER_INFO_value(signerInfoStack, signInfoNum); 207 if (signInfo == nullptr) { 208 SIGNATURE_TOOLS_LOGE("signInfo %dst is nullptr", signInfoNum); 209 return false; 210 } 211 /* GET X509 certificate */ 212 X509* cert = pkcs7Context.certChain[signInfoNum][0]; 213 214 if (PKCS7_signatureVerify(p7Bio, pkcs7Context.p7, signInfo, cert) <= 0) { 215 SIGNATURE_TOOLS_LOGE("PKCS7_signatureVerify %dst signInfo failed", signInfoNum); 216 GetOpensslErrorMessage(); 217 return false; 218 } 219 220 return true; 221} 222 223bool VerifyHapOpensslUtils::GetContentInfo(const PKCS7* p7ContentInfo, ByteBuffer& content) 224{ 225 if ((p7ContentInfo == nullptr) || !PKCS7_type_is_data(p7ContentInfo)) { 226 SIGNATURE_TOOLS_LOGE("p7ContentInfo is invalid"); 227 return false; 228 } 229 ASN1_OCTET_STRING* strContentInfo = p7ContentInfo->d.data; 230 if (strContentInfo == nullptr) { 231 SIGNATURE_TOOLS_LOGE("strContentInfo is invalid"); 232 return false; 233 } 234 int32_t strContentInfoLen = strContentInfo->length; 235 unsigned char* strContentInfoData = strContentInfo->data; 236 if (strContentInfoData == nullptr || strContentInfoLen <= 0) { 237 SIGNATURE_TOOLS_LOGE("ASN1_OCTET_STRING is invalid"); 238 return false; 239 } 240 content.SetCapacity(strContentInfoLen); 241 content.PutData(0, reinterpret_cast<char*>(strContentInfoData), strContentInfoLen); 242 SIGNATURE_TOOLS_LOGD("strContentInfoLen: %d", strContentInfoLen); 243 return true; 244} 245 246void VerifyHapOpensslUtils::GetOpensslErrorMessage() 247{ 248 unsigned long retOpenssl; 249 char errOpenssl[OPENSSL_ERR_MESSAGE_MAX_LEN]; 250 while ((retOpenssl = ERR_get_error()) != 0) { 251 ERR_error_string(retOpenssl, errOpenssl); 252 SIGNATURE_TOOLS_LOGE("openssl err: %lu, message: %s", retOpenssl, errOpenssl); 253 } 254} 255} // namespace SignatureTools 256} // namespace OHOS