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 "pkcs7_signed_data.h" 17#include <openssl/asn1.h> 18#include <openssl/bio.h> 19#include <openssl/pkcs7.h> 20#include <openssl/rsa.h> 21#include <openssl/sha.h> 22#include <openssl/x509.h> 23#include "cert_verify.h" 24#include "dump.h" 25#include "openssl_util.h" 26#include "pkg_utils.h" 27 28namespace Hpackage { 29namespace { 30constexpr size_t g_digestAlgoLength[][2] = { 31 {NID_sha256, SHA256_DIGEST_LENGTH}, 32}; 33 34size_t GetDigestLength(const size_t digestNid) 35{ 36 for (size_t i = 0; i < sizeof(g_digestAlgoLength) / sizeof(g_digestAlgoLength[0]); i++) { 37 if (digestNid == g_digestAlgoLength[i][0]) { 38 return g_digestAlgoLength[i][1]; 39 } 40 } 41 return 0; 42} 43} 44 45Pkcs7SignedData::~Pkcs7SignedData() 46{ 47 if (pkcs7_ != nullptr) { 48 PKCS7_free(pkcs7_); 49 pkcs7_ = nullptr; 50 } 51} 52 53int32_t Pkcs7SignedData::GetHashFromSignBlock(const uint8_t *srcData, const size_t dataLen, 54 std::vector<uint8_t> &hash) 55{ 56 int32_t ret = ParsePkcs7Data(srcData, dataLen); 57 if (ret != 0) { 58 PKG_LOGE("parse pkcs7 data fail"); 59 UPDATER_LAST_WORD(ret); 60 return ret; 61 } 62 63 ret = Verify(); 64 if (ret != 0) { 65 PKG_LOGE("verify pkcs7 data fail"); 66 UPDATER_LAST_WORD(ret); 67 return ret; 68 } 69 hash.assign(digest_.begin(), digest_.end()); 70 71 return 0; 72} 73 74int32_t Pkcs7SignedData::ParsePkcs7Data(const uint8_t *srcData, const size_t dataLen) 75{ 76 if (srcData == nullptr || dataLen == 0) { 77 UPDATER_LAST_WORD(-1); 78 return -1; 79 } 80 if (Init(srcData, dataLen) != 0) { 81 PKG_LOGE("init pkcs7 data fail"); 82 UPDATER_LAST_WORD(-1); 83 return -1; 84 } 85 86 return DoParse(); 87} 88 89int32_t Pkcs7SignedData::Verify() const 90{ 91 std::vector<uint8_t> digestForEVP; 92 for (unsigned int i = 0; i < signatureInfo.overall.length; i++) { 93 digestForEVP.push_back(static_cast<uint8_t>(signatureInfo.overall.buffer[i])); 94 } 95 if (Verify(digestForEVP, {}, true) == 0) { 96 return 0; 97 } 98 return Verify(digest_, {}, true); 99} 100 101int32_t Pkcs7SignedData::Verify(const std::vector<uint8_t> &hash, const std::vector<uint8_t> &sig, 102 bool sigInSignerInfo) const 103{ 104 if (hash.empty()) { 105 return -1; 106 } 107 int32_t ret = -1; 108 for (auto &signerInfo : signerInfos_) { 109 ret = Pkcs7SignleSignerVerify(signerInfo, hash, sigInSignerInfo ? signerInfo.digestEncryptData : sig); 110 if (ret == 0) { 111 PKG_LOGI("p7sourceData check success"); 112 break; 113 } 114 PKG_LOGI("p7sourceData continue"); 115 } 116 117 return ret; 118} 119 120int32_t Pkcs7SignedData::Init(const uint8_t *sourceData, const uint32_t sourceDataLen) 121{ 122 Updater::UPDATER_INIT_RECORD; 123 BIO *p7Bio = BIO_new(BIO_s_mem()); 124 if (p7Bio == nullptr) { 125 PKG_LOGE("BIO_new error!"); 126 UPDATER_LAST_WORD(-1); 127 return -1; 128 } 129 if (static_cast<uint32_t>(BIO_write(p7Bio, sourceData, sourceDataLen)) != sourceDataLen) { 130 PKG_LOGE("BIO_write error!"); 131 UPDATER_LAST_WORD(-1); 132 BIO_free(p7Bio); 133 return -1; 134 } 135 136 if (pkcs7_ != nullptr) { 137 PKCS7_free(pkcs7_); 138 pkcs7_ = nullptr; 139 } 140 pkcs7_ = d2i_PKCS7_bio(p7Bio, nullptr); 141 if (pkcs7_ == nullptr) { 142 PKG_LOGE("d2i_PKCS7_bio failed!"); 143 BIO_free(p7Bio); 144 UPDATER_LAST_WORD(-1); 145 return -1; 146 } 147 148 int32_t type = OBJ_obj2nid(pkcs7_->type); 149 if (type != NID_pkcs7_signed) { 150 PKG_LOGE("Invalid pkcs7 data type %d", type); 151 BIO_free(p7Bio); 152 UPDATER_LAST_WORD(-1); 153 return -1; 154 } 155 156 BIO_free(p7Bio); 157 if (CertVerify::GetInstance().Init() != 0) { 158 PKG_LOGE("init cert verify fail"); 159 UPDATER_LAST_WORD(-1); 160 return -1; 161 } 162 return 0; 163} 164 165/* 166 * tools.ietf.org/html/rfc2315#section-9.1 167 * SignedData ::= SEQUENCE(0x30) { 168 * INTEGER(0x02) version Version, 169 * SET(0x31) digestAlgorithms DigestAlgorithmIdentifiers, 170 * SEQUENCE(0x30) contentInfo ContentInfo, 171 * CONTET_SPECIFIC[0](0xA0) certificates [0] IMPLICIT ExtendedCertificatesAndCertificates OPTIONAL, 172 * CONTET_SPECIFIC[1](0xA1) crls [1] IMPLICIT CertificateRevocationLists OPTIONAL, 173 * SET(0x31) signerInfos SignerInfos } 174 */ 175int32_t Pkcs7SignedData::DoParse() 176{ 177 std::vector<uint8_t> contentInfo; 178 int32_t ret = ParseContentInfo(contentInfo); 179 if (ret != 0) { 180 PKG_LOGE("parse pkcs7 contentInfo fail"); 181 UPDATER_LAST_WORD(-1); 182 return -1; 183 } 184 185 if (GetInstance().GetDigest(contentInfo, signatureInfo, digest_) != 0) { 186 ret = GetDigestFromContentInfo(contentInfo); 187 if (ret != 0) { 188 PKG_LOGE("invalid pkcs7 contentInfo fail"); 189 UPDATER_LAST_WORD(-1); 190 return -1; 191 } 192 } 193 194 return SignerInfosParse(); 195} 196 197/* 198 * tools.ietf.org/html/rfc2315#section-7 199 * ContentInfo ::= SEQUENCE(0x30) { 200 * OBJECT_IDENTIFIER(0x06) contentType ContentType, 201 * CONTET_SPECIFIC[0](0xA0) content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL } 202 * 203 * tools.ietf.org/html/rfc2315#section-8 204 * Data ::= OCTET STRING 205 */ 206int32_t Pkcs7SignedData::ParseContentInfo(std::vector<uint8_t> &digestBlock) const 207{ 208 Updater::UPDATER_INIT_RECORD; 209 PKCS7_SIGNED *signData = pkcs7_->d.sign; 210 if (signData == nullptr) { 211 PKG_LOGE("invalid pkcs7 signed data!"); 212 UPDATER_LAST_WORD(-1); 213 return -1; 214 } 215 216 PKCS7 *contentInfo = signData->contents; 217 if (contentInfo == nullptr) { 218 PKG_LOGE("pkcs7 content is nullptr!"); 219 UPDATER_LAST_WORD(-1); 220 return -1; 221 } 222 if (OBJ_obj2nid(contentInfo->type) != NID_pkcs7_data) { 223 PKG_LOGE("invalid pkcs7 signed data type"); 224 UPDATER_LAST_WORD(-1); 225 return -1; 226 } 227 228 if (GetASN1OctetStringData(contentInfo->d.data, digestBlock) != 0) { 229 PKG_LOGE("get pkcs7 contentInfo fail"); 230 UPDATER_LAST_WORD(-1); 231 return -1; 232 } 233 234 return 0; 235} 236 237int32_t Pkcs7SignedData::GetDigestFromContentInfo(std::vector<uint8_t> &digestBlock) 238{ 239 Updater::UPDATER_INIT_RECORD; 240 if (digestBlock.size() <= sizeof(uint32_t)) { 241 PKG_LOGE("invalid digest block info."); 242 UPDATER_LAST_WORD(-1); 243 return -1; 244 } 245 246 size_t offset = 0; 247 size_t algoId = static_cast<size_t>(ReadLE16(digestBlock.data() + offset)); 248 offset += static_cast<size_t>(sizeof(uint16_t)); 249 size_t digestLen = static_cast<size_t>(ReadLE16(digestBlock.data() + offset)); 250 offset += static_cast<size_t>(sizeof(uint16_t)); 251 if ((GetDigestLength(algoId) != digestLen) || ((digestLen + offset) != digestBlock.size())) { 252 PKG_LOGE("invalid digestLen[%zu] and digestBlock len[%zu]", digestLen, digestBlock.size()); 253 UPDATER_LAST_WORD(-1); 254 return -1; 255 } 256 digest_.assign(digestBlock.begin() + offset, digestBlock.end()); 257 return 0; 258} 259 260Pkcs7SignedData &Pkcs7SignedData::GetInstance() 261{ 262 static Pkcs7SignedData checkPackagesInfo; 263 return checkPackagesInfo; 264} 265 266extern "C" __attribute__((constructor)) void RegisterVerifyHelper(void) 267{ 268 Pkcs7SignedData::GetInstance().RegisterVerifyHelper(std::make_unique<Pkcs7VerifyHelper>()); 269} 270 271void Pkcs7SignedData::RegisterVerifyHelper(std::unique_ptr<VerifyHelper> ptr) 272{ 273 helper_ = std::move(ptr); 274} 275 276Pkcs7VerifyHelper::~Pkcs7VerifyHelper() 277{ 278 return; 279} 280 281int32_t Pkcs7VerifyHelper::GetDigestFromSubBlocks(std::vector<uint8_t> &digestBlock, 282 HwSigningSigntureInfo &signatureInfo, std::vector<uint8_t> &digest) 283{ 284 PKG_LOGE("Pkcs7VerifyHelper in"); 285 return -1; 286} 287 288int32_t Pkcs7SignedData::GetDigest(std::vector<uint8_t> &digestBlock, 289 HwSigningSigntureInfo &signatureInfo, std::vector<uint8_t> &digest) 290{ 291 if (helper_ == nullptr) { 292 PKG_LOGE("helper_ null error"); 293 return -1; 294 } 295 return helper_->GetDigestFromSubBlocks(digestBlock, signatureInfo, digest); 296} 297 298/* 299 * tools.ietf.org/html/rfc2315#section-9.2 300 * SignerInfo ::= SEQUENCE(0x30) { 301 * INTEGER(0x02) version Version, 302 * SEQUENCE(0x30) issuerAndSerialNumber IssuerAndSerialNumber, 303 * SEQUENCE(0x30) digestAlgorithm DigestAlgorithmIdentifier, 304 * CONTET_SPECIFIC[0](0xA0) authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL, 305 * SEQUENCE(0x30) digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier, 306 * OCTET_STRING(0x30) encryptedDigest EncryptedDigest, 307 * CONTET_SPECIFIC[1](0xA1) unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL } 308 */ 309int32_t Pkcs7SignedData::ReadSig(const uint8_t *sourceData, const uint32_t sourceDataLen, 310 std::vector<std::vector<uint8_t>> &sigs) 311{ 312 if (sourceData == nullptr || sourceDataLen == 0) { 313 UPDATER_LAST_WORD(PKCS7_INVALID_PARAM_ERR); 314 return PKCS7_INVALID_PARAM_ERR; 315 } 316 if (Init(sourceData, sourceDataLen) != 0) { 317 PKG_LOGE("init pkcs7 data fail"); 318 UPDATER_LAST_WORD(PKCS7_INIT_ERR); 319 return PKCS7_INIT_ERR; 320 } 321 STACK_OF(PKCS7_SIGNER_INFO) *p7SignerInfos = PKCS7_get_signer_info(pkcs7_); 322 if (p7SignerInfos == nullptr) { 323 PKG_LOGE("get pkcs7 signers failed!"); 324 UPDATER_LAST_WORD(PKCS7_INVALID_VALUE_ERR); 325 return PKCS7_INVALID_VALUE_ERR; 326 } 327 int signerInfoNum = sk_PKCS7_SIGNER_INFO_num(p7SignerInfos); 328 if (signerInfoNum <= 0) { 329 PKG_LOGE("invalid signers info num %d!", signerInfoNum); 330 UPDATER_LAST_WORD(PKCS7_INVALID_VALUE_ERR); 331 return PKCS7_INVALID_VALUE_ERR; 332 } 333 for (int i = 0; i < signerInfoNum; i++) { 334 PKCS7_SIGNER_INFO *p7SiTmp = sk_PKCS7_SIGNER_INFO_value(p7SignerInfos, i); 335 Pkcs7SignerInfo signer; 336 int32_t ret = SignerInfoParse(p7SiTmp, signer); 337 if (ret != 0) { 338 PKG_LOGE("SignerInfo Parse failed!"); 339 continue; 340 } 341 sigs.push_back(signer.digestEncryptData); 342 } 343 if (sigs.size() == 0) { 344 PKG_LOGE("no valid sigs!"); 345 UPDATER_LAST_WORD(PKCS7_HAS_NO_VALID_SIG_ERR); 346 return PKCS7_HAS_NO_VALID_SIG_ERR; 347 } 348 return PKCS7_SUCCESS; 349} 350 351int32_t Pkcs7SignedData::SignerInfosParse() 352{ 353 Updater::UPDATER_INIT_RECORD; 354 STACK_OF(PKCS7_SIGNER_INFO) *p7SignerInfos = PKCS7_get_signer_info(pkcs7_); 355 if (p7SignerInfos == nullptr) { 356 PKG_LOGE("get pkcs7 signers info failed!"); 357 UPDATER_LAST_WORD(-1); 358 return -1; 359 } 360 361 int signerInfoNum = sk_PKCS7_SIGNER_INFO_num(p7SignerInfos); 362 if (signerInfoNum <= 0) { 363 PKG_LOGE("invalid signers info num %d!", signerInfoNum); 364 UPDATER_LAST_WORD(-1); 365 return -1; 366 } 367 368 for (int i = 0; i < signerInfoNum; i++) { 369 PKCS7_SIGNER_INFO *p7SiTmp = sk_PKCS7_SIGNER_INFO_value(p7SignerInfos, i); 370 Pkcs7SignerInfo signer; 371 int32_t ret = SignerInfoParse(p7SiTmp, signer); 372 if (ret != 0) { 373 PKG_LOGE("SignerInfoParse failed!"); 374 continue; 375 } 376 signerInfos_.push_back(std::move(signer)); 377 } 378 379 return 0; 380} 381 382int32_t Pkcs7SignedData::SignerInfoParse(PKCS7_SIGNER_INFO *p7SignerInfo, Pkcs7SignerInfo &signerInfo) 383{ 384 if (p7SignerInfo == nullptr) { 385 return -1; 386 } 387 PKCS7_ISSUER_AND_SERIAL *p7IssuerAndSerial = p7SignerInfo->issuer_and_serial; 388 if (p7IssuerAndSerial == nullptr) { 389 PKG_LOGE("signer cert info is nullptr!"); 390 UPDATER_LAST_WORD(-1); 391 return -1; 392 } 393 signerInfo.issuerName = p7IssuerAndSerial->issuer; 394 signerInfo.serialNumber = p7IssuerAndSerial->serial; 395 396 int32_t ret = GetX509AlgorithmNid(p7SignerInfo->digest_alg, signerInfo.digestNid); 397 if (ret != 0) { 398 PKG_LOGE("Parse signer info digest_alg failed!"); 399 return ret; 400 } 401 ret = GetX509AlgorithmNid(p7SignerInfo->digest_enc_alg, signerInfo.digestEncryptNid); 402 if (ret != 0) { 403 PKG_LOGE("Parse signer info digest_enc_alg failed!"); 404 return ret; 405 } 406 407 ret = GetASN1OctetStringData(p7SignerInfo->enc_digest, signerInfo.digestEncryptData); 408 if (ret != 0) { 409 PKG_LOGE("parse signer info enc_digest failed!"); 410 return ret; 411 } 412 413 return 0; 414} 415 416int32_t Pkcs7SignedData::Pkcs7SignleSignerVerify(const Pkcs7SignerInfo &signerInfo, const std::vector<uint8_t> &hash, 417 const std::vector<uint8_t> &sig) const 418{ 419 if (pkcs7_ == nullptr) { 420 UPDATER_LAST_WORD(-1); 421 return -1; 422 } 423 STACK_OF(X509) *certStack = pkcs7_->d.sign->cert; 424 if (certStack == nullptr) { 425 PKG_LOGE("certStack is empty!"); 426 UPDATER_LAST_WORD(-1); 427 return -1; 428 } 429 430 X509 *cert = X509_find_by_issuer_and_serial(certStack, signerInfo.issuerName, signerInfo.serialNumber); 431 if (cert == nullptr) { 432 PKG_LOGE("cert is empty"); 433 UPDATER_LAST_WORD(-1); 434 return -1; 435 } 436 437 if (CertVerify::GetInstance().CheckCertChain(certStack, cert) != 0) { 438 PKG_LOGE("public cert check fail"); 439 UPDATER_LAST_WORD(-1); 440 return -1; 441 } 442 443 return VerifyDigest(cert, signerInfo, hash, sig); 444} 445 446int32_t Pkcs7SignedData::VerifyDigest(X509 *cert, const Pkcs7SignerInfo &signer, const std::vector<uint8_t> &hash, 447 const std::vector<uint8_t> &sig) const 448{ 449 Updater::UPDATER_INIT_RECORD; 450 if (cert == nullptr) { 451 UPDATER_LAST_WORD(-1); 452 return -1; 453 } 454 455 EVP_PKEY *pubKey = X509_get_pubkey(cert); 456 if (pubKey == nullptr) { 457 PKG_LOGE("get pubkey from cert fail"); 458 UPDATER_LAST_WORD(-1); 459 return -1; 460 } 461 462 auto ret = VerifyDigestByPubKey(pubKey, signer.digestNid, hash, sig); 463 EVP_PKEY_free(pubKey); 464 return ret; 465} 466} // namespace Hpackage 467