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 16#include "signature_tools_log.h" 17#include "signature_tools_errno.h" 18#include "verify_hap_openssl_utils.h" 19#include "signer.h" 20#include "securec.h" 21#include "constant.h" 22#include "pkcs7_data.h" 23 24namespace OHOS { 25namespace SignatureTools { 26 27static constexpr int BUFFER_SIZE = 4096; 28 29static int PKCS7AddAttribute(PKCS7* p7, const std::vector<PKCS7Attr>& attrs) 30{ 31 STACK_OF(PKCS7_SIGNER_INFO)* signerInfos = PKCS7_get_signer_info(p7); 32 if (signerInfos == NULL || sk_PKCS7_SIGNER_INFO_num(signerInfos) != 1) { 33 PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR, 34 "signer info count not equal 1,pkcs7 add customize attribute failed"); 35 return INVALIDPARAM_ERROR; 36 } 37 PKCS7_SIGNER_INFO* signerInfo = sk_PKCS7_SIGNER_INFO_value(signerInfos, 0); 38 for (PKCS7Attr attr : attrs) { 39 if (PKCS7_add_signed_attribute(signerInfo, attr.nid, attr.atrtype, attr.value) != 1) { 40 if (attr.atrtype == V_ASN1_UTF8STRING) 41 ASN1_STRING_free(reinterpret_cast<ASN1_STRING*>(attr.value)); 42 PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR, 43 "pkcs7 add customize attribute failed"); 44 return RET_FAILED; 45 } 46 } 47 return RET_OK; 48} 49 50static int I2dPkcs7Str(PKCS7* p7, std::string& ret) 51{ 52 /* raw data exported in pkcs7 */ 53 unsigned char* out = NULL; 54 int outSize = 0; 55 /* Deserialize to obtain the p7b byte stream */ 56 outSize = i2d_PKCS7(p7, &out); 57 if (out == NULL || outSize <= 0) { 58 PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR, 59 "pkcs7 is invalid"); 60 return INVALIDPARAM_ERROR; 61 } 62 ret.clear(); 63 ret.resize(outSize); 64 std::copy(out, out + outSize, &ret[0]); 65 OPENSSL_free(out); 66 return RET_OK; 67} 68 69static int SetSignerInfoSignAlgor(PKCS7_SIGNER_INFO* info) 70{ 71 int signNid = 0; 72 int hashNid = 0; 73 X509_ALGOR* dig; 74 X509_ALGOR* sig; 75 PKCS7_SIGNER_INFO_get0_algs(info, NULL, &dig, &sig); 76 if (dig == NULL || dig->algorithm == NULL || 77 (hashNid = OBJ_obj2nid(dig->algorithm)) == NID_undef || 78 !OBJ_find_sigid_by_algs(&signNid, hashNid, NID_X9_62_id_ecPublicKey) || 79 X509_ALGOR_set0(sig, OBJ_nid2obj(signNid), V_ASN1_UNDEF, 0) != 1) { 80 return 0; 81 } 82 return 1; 83} 84 85static int VerifySignature(PKCS7* pkcs7, BIO* p7bio) 86{ 87 /* signature information */ 88 STACK_OF(PKCS7_SIGNER_INFO)* skSignerInfo = NULL; 89 /* signature count */ 90 int signerCount = 0; 91 /* verify signature value */ 92 skSignerInfo = PKCS7_get_signer_info(pkcs7); 93 signerCount = sk_PKCS7_SIGNER_INFO_num(skSignerInfo); 94 for (int i = 0; i < signerCount; i++) { 95 PKCS7_SIGNER_INFO* signerInfo = sk_PKCS7_SIGNER_INFO_value(skSignerInfo, i); 96 X509* sigCert = PKCS7_cert_from_signer_info(pkcs7, signerInfo); 97 if (PKCS7_signatureVerify(p7bio, pkcs7, signerInfo, sigCert) != 1) { 98 PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, "signature value verify failed"); 99 return VERIFY_ERROR; 100 } 101 } 102 return RET_OK; 103} 104 105PKCS7Data::PKCS7Data(int flags) : m_p7(nullptr), m_flags(flags) 106{ 107} 108 109PKCS7Data::~PKCS7Data() 110{ 111 PKCS7_free(m_p7); 112 m_p7 = NULL; 113} 114 115int PKCS7Data::Sign(const std::string& content, const std::shared_ptr<Signer>& signer, 116 const std::string& sigAlg, std::string& ret, std::vector<PKCS7Attr> attrs) 117{ 118 int result = RET_OK; 119 if ((result = InitPkcs7(content, signer, sigAlg, attrs)) < 0) { 120 goto err; 121 } 122 123 /* serialization */ 124 if ((result = I2dPkcs7Str(m_p7, ret)) < 0) { 125 goto err; 126 } 127 /* release resources */ 128err: 129 if (result < 0) { 130 SIGNATURE_TOOLS_LOGE("sign failed"); 131 } 132 return result; 133} 134 135int PKCS7Data::Parse(const std::string& p7bBytes) 136{ 137 const unsigned char* data = reinterpret_cast<const unsigned char*>(&p7bBytes[0]); 138 return Parse(&data, static_cast<long>(p7bBytes.size())); 139} 140int PKCS7Data::Parse(const std::vector<int8_t>& p7bBytes) 141{ 142 const unsigned char* data = reinterpret_cast<const unsigned char*>(&p7bBytes[0]); 143 return Parse(&data, static_cast<long>(p7bBytes.size())); 144} 145int PKCS7Data::Parse(const unsigned char** in, long len) 146{ 147 /* If p7 has been initialized, it will be released */ 148 if (m_p7) { 149 PKCS7_free(m_p7); 150 m_p7 = NULL; 151 } 152 /* Deserialize */ 153 m_p7 = d2i_PKCS7(NULL, in, len); 154 if (m_p7 == NULL) { 155 PrintErrorNumberMsg("PARSE_ERROR", PARSE_ERROR, "invalid p7b data, parse failed"); 156 return PARSE_ERROR; 157 } 158 return RET_OK; 159} 160 161int PKCS7Data::Verify(const std::string& content) const 162{ 163 if (VerifySign(content) < 0) { 164 PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, "signature verify failed"); 165 return VERIFY_ERROR; 166 } 167 if (VerifyCertChain() < 0) { 168 PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, "cert Chain verify failed"); 169 PrintCertChainSub(m_p7->d.sign->cert); 170 return VERIFY_ERROR; 171 } 172 return RET_OK; 173} 174 175int PKCS7Data::GetContent(std::string& originalRawData) const 176{ 177 BIO* oriBio = PKCS7_dataDecode(m_p7, NULL, NULL, NULL); 178 if (oriBio == NULL) { 179 PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR, "pkcs7 get content data failed!"); 180 return INVALIDPARAM_ERROR; 181 } 182 char buf[BUFFER_SIZE]{0}; 183 size_t readBytes = 0; 184 while (BIO_read_ex(oriBio, buf, sizeof(buf), &readBytes) == 1) { 185 originalRawData.append(buf, readBytes); 186 } 187 BIO_free_all(oriBio); 188 return RET_OK; 189} 190 191static void PKCS7AddCrls(PKCS7* p7, STACK_OF(X509_CRL)* crls) 192{ 193 for (int i = 0; i < sk_X509_CRL_num(crls); i++) { 194 PKCS7_add_crl(p7, sk_X509_CRL_value(crls, i)); 195 } 196} 197 198int PKCS7Data::InitPkcs7(const std::string& content, const std::shared_ptr<Signer>& signer, 199 const std::string& sigAlg, std::vector<PKCS7Attr> attrs) 200{ 201 STACK_OF(X509)* certs = NULL; 202 /* hash algorithm */ 203 const EVP_MD* md = NULL; 204 /* entity certificate */ 205 X509* cert = NULL; 206 int result = RET_OK; 207 if (signer == NULL) { 208 PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR, "signer is NULL , sign failed"); 209 result = INVALIDPARAM_ERROR; 210 goto err; 211 } 212 m_signer = signer; 213 m_sigAlg = sigAlg; 214 certs = signer->GetCertificates(); 215 if (SortX509Stack(certs) < 0) { 216 result = RET_FAILED; 217 goto err; 218 } 219 if (sigAlg == SIGN_ALG_SHA384) { 220 md = EVP_sha384(); 221 } else if (sigAlg == SIGN_ALG_SHA256) { 222 md = EVP_sha256(); 223 } else { 224 PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR, 225 sigAlg + "is invalid sigAlg, please use SHA256withECDSA/SHA384withECDSA, sign failed"); 226 result = INVALIDPARAM_ERROR; 227 goto err; 228 } 229 /* Extract the entity certificate from the certificate chain */ 230 cert = sk_X509_delete(certs, 0); 231 m_p7 = Pkcs7Sign(cert, certs, md, content, m_flags, attrs); 232 if (m_p7 == NULL) { 233 PrintErrorNumberMsg("INVALIDPARAM_ERROR", SIGN_ERROR, "p7 is NULL, pkcs7 sign failed"); 234 result = SIGN_ERROR; 235 goto err; 236 } 237 PKCS7AddCrls(m_p7, signer->GetCrls()); 238 239err: 240 sk_X509_pop_free(certs, X509_free); 241 X509_free(cert); 242 return result; 243} 244 245void PKCS7Data::PrintCertChainSub(const STACK_OF(X509)* certs) 246{ 247 if (certs == NULL) 248 return; 249 SIGNATURE_TOOLS_LOGI("certChainSubject:"); 250 int certNum = sk_X509_num(certs); 251 SIGNATURE_TOOLS_LOGI("certNum%s", std::to_string(certNum).c_str()); 252 for (int i = 0; i < certNum; i++) { 253 SIGNATURE_TOOLS_LOGI("certificate %s", std::to_string(i).c_str()); 254 std::string sub; 255 VerifyCertOpensslUtils::GetSubjectFromX509(sk_X509_value(certs, i), sub); 256 SIGNATURE_TOOLS_LOGI("%s", sub.c_str()); 257 } 258} 259 260std::string PKCS7Data::GetASN1Time(const ASN1_TIME* tm) 261{ 262 if (tm == NULL) { 263 return ""; 264 } 265 /* Convert the ASN1_TIME structure to a standard tm structure. */ 266 struct tm time; 267 ASN1_TIME_to_tm(tm, &time); 268 /* Convert to local time(considering the time zone) */ 269 time_t t = mktime(&time); 270 if (t < 0) { 271 return ""; 272 } 273 struct tm* localTime = localtime(&t); 274 if (localTime == nullptr) { 275 return ""; 276 } 277 /* Print local time */ 278 char buf[128] = {0}; 279 if (sprintf_s(buf, sizeof(buf), "%04d-%02d-%02d %02d:%02d:%02d", 280 localTime->tm_year + YEAR1900, localTime->tm_mon + 1, localTime->tm_mday, 281 localTime->tm_hour, localTime->tm_min, localTime->tm_sec) == -1) { 282 return ""; 283 } 284 return std::string(buf, strlen(buf)); 285} 286 287bool PKCS7Data::X509NameCompare(const X509* cert, const X509* issuerCert) 288{ 289 if (cert == nullptr || issuerCert == nullptr) { 290 PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, 291 "input cert is NULL"); 292 return false; 293 } 294 X509_NAME* aName = X509_get_issuer_name(cert); 295 X509_NAME* bName = X509_get_subject_name(issuerCert); 296 if (X509_NAME_cmp(aName, bName) != 0) { 297 PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, 298 "cert issuer name is not equal to its issuer\'s name"); 299 return false; 300 } 301 return true; 302} 303 304int PKCS7Data::CheckSignTimeInValidPeriod(const ASN1_TYPE* signTime, 305 const ASN1_TIME* notBefore, const ASN1_TIME* notAfter) 306{ 307 if (notBefore == nullptr || notBefore->data == nullptr || notAfter == nullptr || notAfter->data == nullptr) { 308 PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR, 309 "invalid period, check signtime failed please use valid period to to check signtime"); 310 return INVALIDPARAM_ERROR; 311 } 312 if (signTime == nullptr || signTime->value.asn1_string == nullptr || 313 signTime->value.asn1_string->data == nullptr) { 314 PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR, "signtime is NULL"); 315 return INVALIDPARAM_ERROR; 316 } 317 ASN1_TIME* tm = ASN1_TIME_new(); 318 ASN1_TIME_set_string(tm, (reinterpret_cast<const char*>(signTime->value.asn1_string->data))); 319 if (ASN1_TIME_compare(notBefore, signTime->value.asn1_string) > 0 || 320 ASN1_TIME_compare(notAfter, signTime->value.asn1_string) < 0) { 321 SIGNATURE_TOOLS_LOGE("sign time invalid, signTime: %s, notBefore: %s, " 322 "notAfter: %s", GetASN1Time(tm).c_str(), 323 GetASN1Time(notBefore).c_str(), GetASN1Time(notAfter).c_str()); 324 ASN1_TIME_free(tm); 325 return RET_FAILED; 326 } 327 ASN1_TIME_free(tm); 328 return RET_OK; 329} 330 331static X509* FindSubCertThenEraseItFromSets(X509* cert, std::unordered_set<X509*>& x509Sets) 332{ 333 X509* ret = NULL; 334 for (X509* c : x509Sets) { 335 X509_NAME* name1 = X509_get_subject_name(cert); 336 X509_NAME* name2 = X509_get_issuer_name(c); 337 if (X509_NAME_cmp(name1, name2) == 0) { 338 x509Sets.erase(c); 339 ret = c; 340 break; 341 } 342 } 343 return ret; 344} 345 346int PKCS7Data::SortX509Stack(STACK_OF(X509)* certs) 347{ 348 std::unordered_set<X509*> x509Sets; 349 std::list<X509*>certChain; 350 X509* tmp = NULL; 351 int result = RET_FAILED; 352 353 if (sk_X509_num(certs) < MIN_CERTS_NUM) { 354 PrintErrorNumberMsg("CERTIFICATE_ERROR", CERTIFICATE_ERROR, "cert of certchain count less than two!"); 355 goto err; 356 } 357 for (int i = 0; i < sk_X509_num(certs); i++) { 358 x509Sets.insert(sk_X509_value(certs, i)); 359 } 360 if (sk_X509_num(certs) != static_cast<int>(x509Sets.size())) { 361 PrintErrorNumberMsg("CERTIFICATE_ERROR", CERTIFICATE_ERROR, "sort x509 certchain failed!"); 362 goto err; 363 } 364 for (X509* cert : x509Sets) { 365 if (X509_name_cmp(X509_get_subject_name(cert), X509_get_issuer_name(cert)) == 0) { 366 tmp = cert; 367 x509Sets.erase(cert); 368 break; 369 } 370 } 371 if (tmp == NULL) { 372 PrintErrorNumberMsg("CERTIFICATE_ERROR", CERTIFICATE_ERROR, 373 "can't find root cert from certchain ,sort x509 certchain failed!"); 374 goto err; 375 } 376 certChain.push_front(tmp); 377 while ((tmp = FindSubCertThenEraseItFromSets(tmp, x509Sets))) { 378 certChain.push_front(tmp); 379 } 380 if (x509Sets.size() != 0) { 381 PrintErrorNumberMsg("CERTIFICATE_ERROR", CERTIFICATE_ERROR, 382 "certchain contain invalid cert, sort x509 certchain failed!"); 383 goto err; 384 } 385 while (sk_X509_num(certs)) { 386 sk_X509_pop(certs); 387 } 388 for (X509* cert : certChain) { 389 sk_X509_push(certs, cert); 390 } 391 result = RET_OK; 392err: 393 return result; 394} 395 396int PKCS7Data::VerifySign(const std::string& content)const 397{ 398 BIO* inBio = NULL; 399 if ((m_flags & PKCS7_DETACHED)) { 400 inBio = BIO_new_mem_buf(reinterpret_cast<const void*>(content.c_str()), 401 static_cast<int>(content.size())); 402 if (inBio == NULL) { 403 PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, 404 "new mem buf error!,pkcs7 verify signature failed"); 405 return VERIFY_ERROR; 406 } 407 } 408 if (PKCS7_verify(m_p7, NULL, NULL, inBio, NULL, m_flags) != 1) { 409 PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, "pkcs7 verify signature failed"); 410 BIO_free(inBio); 411 return VERIFY_ERROR; 412 } 413 BIO_free(inBio); 414 return RET_OK; 415} 416 417int PKCS7Data::VerifyCertChain()const 418{ 419 /* Validate the certificate chain */ 420 STACK_OF(PKCS7_SIGNER_INFO)* skSignerInfo = PKCS7_get_signer_info(m_p7); 421 int signerCount = sk_PKCS7_SIGNER_INFO_num(skSignerInfo); 422 int c = signerCount; 423 STACK_OF(X509)* certs = NULL; 424 int result = RET_FAILED; 425 /* Original certificate chain */ 426 STACK_OF(X509)* certChain = m_p7->d.sign->cert; 427 /* Copy of the certificate chain, with the entity certificate removed later */ 428 certs = sk_X509_dup(certChain); 429 if (SortX509Stack(certs) < 0) { 430 SIGNATURE_TOOLS_LOGE("sort x509 stack failed, verify certchain failed"); 431 goto err; 432 } 433 /* Retrieve the certificate chain without the entity certificate */ 434 while (c--) { 435 sk_X509_delete(certs, 0); 436 } 437 for (int i = 0; i < signerCount; i++) { 438 PKCS7_SIGNER_INFO* signerInfo = sk_PKCS7_SIGNER_INFO_value(skSignerInfo, i); 439 if ((result = VerifySignerInfoCertchain(m_p7, signerInfo, certs, certChain)) < 0) { 440 SIGNATURE_TOOLS_LOGE("verify certchain failed"); 441 goto err; 442 } 443 } 444 result = RET_OK; 445err: 446 sk_X509_free(certs); 447 return result; 448} 449 450int PKCS7Data::CheckSginerInfoSignTimeInCertChainValidPeriod(PKCS7_SIGNER_INFO* signerInfo, 451 STACK_OF(X509)* certs) const 452{ 453 if (signerInfo == NULL || certs == NULL) { 454 PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR, "input is NULL, check signtime invalid"); 455 return INVALIDPARAM_ERROR; 456 } 457 ASN1_TYPE* signTime = PKCS7_get_signed_attribute(signerInfo, NID_pkcs9_signingTime); 458 for (int i = 0; i < sk_X509_num(certs); i++) { 459 X509* cert = sk_X509_value(certs, i); 460 const ASN1_TIME* notBefore = X509_get0_notBefore(cert); 461 const ASN1_TIME* notAfter = X509_get0_notAfter(cert); 462 if (CheckSignTimeInValidPeriod(signTime, notBefore, notAfter) < 0) { 463 SIGNATURE_TOOLS_LOGE("pkcs7 sign time check failed"); 464 return INVALIDPARAM_ERROR; 465 } 466 } 467 return RET_OK; 468} 469 470int PKCS7Data::VerifySignerInfoCertchain(PKCS7* pkcs7, PKCS7_SIGNER_INFO* signerInfo, 471 STACK_OF(X509)* certs, STACK_OF(X509)* certChain)const 472{ 473 X509* sigCert = PKCS7_cert_from_signer_info(pkcs7, signerInfo); 474 int j = 0; 475 /* Trace back through the subject information and validate the signature value of each certificate */ 476 if (!X509NameCompare(sigCert, sk_X509_value(certs, 0))) { 477 SIGNATURE_TOOLS_LOGE("entity name compare not equal, verify failed"); 478 return VERIFY_ERROR; 479 } 480 /* verify entity certificate signature value */ 481 if (!VerifyCertOpensslUtils::CertVerify(sigCert, sk_X509_value(certs, 0))) { 482 SIGNATURE_TOOLS_LOGE("entity cert signature verify failed"); 483 return VERIFY_ERROR; 484 } 485 for (; j + 1 < sk_X509_num(certs); j++) { 486 if (!X509NameCompare(sk_X509_value(certs, j), sk_X509_value(certs, j + 1))) { 487 SIGNATURE_TOOLS_LOGE("sub cert name compare not equal, verify failed"); 488 return VERIFY_ERROR; 489 } 490 /* Verify the signature value of the intermediate certificate */ 491 if (!VerifyCertOpensslUtils::CertVerify(sk_X509_value(certs, j), sk_X509_value(certs, j + 1))) { 492 SIGNATURE_TOOLS_LOGE("sub cert signature verify failed"); 493 return VERIFY_ERROR; 494 } 495 } 496 if (!X509NameCompare(sk_X509_value(certs, j), sk_X509_value(certs, j))) { 497 SIGNATURE_TOOLS_LOGE("root cert name compare not equal, verify failed"); 498 return VERIFY_ERROR; 499 } 500 /* Verify the signature value of the root certificate */ 501 if (!VerifyCertOpensslUtils::CertVerify(sk_X509_value(certs, j), sk_X509_value(certs, j))) { 502 SIGNATURE_TOOLS_LOGE("root cert signature verify failed"); 503 return VERIFY_ERROR; 504 } 505 /* Verify that the signature time in the signature information is within the validity period of 506 the certificate chain (entity certificate will be verified in PKCS7_verify) */ 507 if (CheckSginerInfoSignTimeInCertChainValidPeriod(signerInfo, certChain) < 0) { 508 SIGNATURE_TOOLS_LOGE("sign time is invalid,verify failed"); 509 return VERIFY_ERROR; 510 } 511 return RET_OK; 512} 513 514int PKCS7Data::Pkcs7SignAttr(PKCS7_SIGNER_INFO* info) 515{ 516 unsigned char* attrBuf = NULL; 517 int attrLen; 518 519 std::string data; 520 std::string signature; 521 unsigned char* sigRet = NULL; 522 int sigLen = 0; 523 524 attrLen = ASN1_item_i2d((ASN1_VALUE*)info->auth_attr, &attrBuf, 525 ASN1_ITEM_rptr(PKCS7_ATTR_SIGN)); 526 if (!attrBuf) { 527 OPENSSL_free(attrBuf); 528 return 0; 529 } 530 531 data.assign(reinterpret_cast<const char*>(attrBuf), attrLen); 532 signature = m_signer->GetSignature(data, m_sigAlg); 533 if (signature.empty()) { 534 OPENSSL_free(attrBuf); 535 return 0; 536 } 537 sigLen = signature.size(); 538 sigRet = reinterpret_cast<unsigned char*>(OPENSSL_malloc(sigLen)); 539 if (sigRet == NULL) { 540 OPENSSL_free(attrBuf); 541 return 0; 542 } 543 std::copy(&signature[0], &signature[0] + signature.size(), sigRet); 544 ASN1_STRING_set0(info->enc_digest, sigRet, sigLen); 545 OPENSSL_free(attrBuf); 546 return 1; 547} 548 549static ASN1_OCTET_STRING* PKCS7GetASN1Content(PKCS7* pkcs7) 550{ 551 if (PKCS7_type_is_data(pkcs7)) { 552 return pkcs7->d.data; 553 } 554 return NULL; 555} 556 557int PKCS7Data::Pkcs7AddTimeDigestAndSignAttr(PKCS7_SIGNER_INFO* info, EVP_MD_CTX* hashCtx) 558{ 559 unsigned char hashData[EVP_MAX_MD_SIZE]; 560 unsigned int hashLen; 561 562 /* add signing time */ 563 if (!PKCS7_get_signed_attribute(info, NID_pkcs9_signingTime)) { 564 if (!PKCS7_add0_attrib_signing_time(info, NULL)) { 565 return 0; 566 } 567 } 568 569 /* add digest */ 570 if (!EVP_DigestFinal_ex(hashCtx, hashData, &hashLen)) { 571 return 0; 572 } 573 if (!PKCS7_add1_attrib_digest(info, hashData, hashLen)) { 574 return 0; 575 } 576 577 /* sign the attributes */ 578 if (!Pkcs7SignAttr(info)) { 579 return 0; 580 } 581 582 return 1; 583} 584 585static BIO* PKCS7SearchDigest(EVP_MD_CTX** pHash, BIO* io, int numberID) 586{ 587 while ((io = BIO_find_type(io, BIO_TYPE_MD))) { 588 BIO_get_md_ctx(io, pHash); 589 if (*pHash == NULL) { 590 return NULL; 591 } 592 if (EVP_MD_CTX_type(*pHash) == numberID) { 593 return io; 594 } 595 io = BIO_next(io); 596 } 597 return NULL; 598} 599 600static int PKCS7DataFinalCheck(PKCS7* pkcs7, BIO* bio, 601 STACK_OF(PKCS7_SIGNER_INFO)** psk, ASN1_OCTET_STRING** pos) 602{ 603 int id = 0; 604 605 if (pkcs7 == NULL || pkcs7->d.ptr == NULL) { 606 return 0; 607 } 608 609 id = OBJ_obj2nid(pkcs7->type); 610 pkcs7->state = PKCS7_S_HEADER; 611 612 if (id == NID_pkcs7_signed) { 613 *psk = pkcs7->d.sign->signer_info; 614 *pos = PKCS7GetASN1Content(pkcs7->d.sign->contents); 615 if (PKCS7_type_is_data(pkcs7->d.sign->contents) && pkcs7->detached) { 616 ASN1_OCTET_STRING_free(*pos); 617 *pos = NULL; 618 pkcs7->d.sign->contents->d.data = NULL; 619 } 620 return 1; 621 } 622 return 0; 623} 624 625int PKCS7Data::Pkcs7DataFinalSignAttr(STACK_OF(PKCS7_SIGNER_INFO)* infoStack, BIO* bio) 626{ 627 EVP_MD_CTX* hashCtx = NULL; 628 STACK_OF(X509_ATTRIBUTE)* attrStack = NULL; 629 BIO* ioTmp = NULL; 630 int result = 0; 631 EVP_MD_CTX* ctxTmp = EVP_MD_CTX_new(); 632 if (ctxTmp == NULL) { 633 return 0; 634 } 635 636 if (infoStack == NULL) { 637 goto err; 638 } 639 for (int i = 0; i < sk_PKCS7_SIGNER_INFO_num(infoStack); i++) { 640 PKCS7_SIGNER_INFO* info = sk_PKCS7_SIGNER_INFO_value(infoStack, i); 641 642 int numberID = OBJ_obj2nid(info->digest_alg->algorithm); 643 644 ioTmp = bio; 645 646 ioTmp = PKCS7SearchDigest(&hashCtx, ioTmp, numberID); 647 648 if (ioTmp == NULL || !EVP_MD_CTX_copy_ex(ctxTmp, hashCtx)) { 649 goto err; 650 } 651 652 attrStack = info->auth_attr; 653 654 if (sk_X509_ATTRIBUTE_num(attrStack) > 0) { 655 if (!Pkcs7AddTimeDigestAndSignAttr(info, ctxTmp)) { 656 goto err; 657 } 658 } else { 659 goto err; 660 } 661 } 662 result = 1; 663err: 664 EVP_MD_CTX_free(ctxTmp); 665 return result; 666} 667 668static int PKCS7DataFinalSetContent(PKCS7* pkcs7, ASN1_OCTET_STRING* asn1Str, BIO* io) 669{ 670 BIO* ioTmp = NULL; 671 if (!PKCS7_is_detached(pkcs7)) { 672 if (asn1Str == NULL) { 673 return 0; 674 } 675 if (!(asn1Str->flags & ASN1_STRING_FLAG_NDEF)) { 676 char* contentData; 677 long contentLen; 678 ioTmp = BIO_find_type(io, BIO_TYPE_MEM); 679 if (ioTmp == NULL) { 680 return 0; 681 } 682 contentLen = BIO_get_mem_data(ioTmp, &contentData); 683 684 BIO_set_flags(ioTmp, BIO_FLAGS_MEM_RDONLY); 685 BIO_set_mem_eof_return(ioTmp, 0); 686 ASN1_STRING_set0(asn1Str, (unsigned char*)contentData, contentLen); 687 } 688 } 689 return 1; 690} 691int PKCS7Data::Pkcs7DataFinal(PKCS7* pkcs7, BIO* io) 692{ 693 STACK_OF(PKCS7_SIGNER_INFO)* infoStack = NULL; 694 ASN1_OCTET_STRING* os = NULL; 695 696 if (!PKCS7DataFinalCheck(pkcs7, io, &infoStack, &os) || 697 !Pkcs7DataFinalSignAttr(infoStack, io) || 698 !PKCS7DataFinalSetContent(pkcs7, os, io)) { 699 return 0; 700 } 701 return 1; 702} 703 704int PKCS7Data::Pkcs7Final(PKCS7* pkcs7, const std::string& content, int flags) 705{ 706 BIO* p7bio; 707 int result = 0; 708 709 if ((p7bio = PKCS7_dataInit(pkcs7, NULL)) == NULL) { 710 return 0; 711 } 712 713 if (BIO_write(p7bio, content.c_str(), static_cast<int>(content.size())) <= 0) { 714 SIGNATURE_TOOLS_LOGE("add json data to pkcs7 failed"); 715 goto err; 716 } 717 718 (void)BIO_flush(p7bio); 719 720 if (!Pkcs7DataFinal(pkcs7, p7bio)) { 721 goto err; 722 } 723 /* Verify the signature value */ 724 if (VerifySignature(pkcs7, p7bio) < 0) { 725 goto err; 726 } 727 result = 1; 728 729err: 730 BIO_free_all(p7bio); 731 return result; 732} 733 734static int Pkcs7SetSignerInfo(PKCS7_SIGNER_INFO* info, X509* cert, const EVP_MD* hash) 735{ 736 if (!ASN1_INTEGER_set(info->version, 1) || 737 !X509_NAME_set(&info->issuer_and_serial->issuer, X509_get_issuer_name(cert))) { 738 return 0; 739 } 740 741 ASN1_INTEGER_free(info->issuer_and_serial->serial); 742 if (!(info->issuer_and_serial->serial = 743 ASN1_INTEGER_dup(X509_get_serialNumber(cert)))) { 744 return 0; 745 } 746 747 X509_ALGOR_set0(info->digest_alg, OBJ_nid2obj(EVP_MD_type(hash)), 748 V_ASN1_NULL, NULL); 749 750 if (!SetSignerInfoSignAlgor(info)) { 751 return 0; 752 } 753 return 1; 754} 755 756static PKCS7_SIGNER_INFO* Pkcs7AddSignature(PKCS7* pkcs7, X509* cert, const EVP_MD* hash) 757{ 758 PKCS7_SIGNER_INFO* info = NULL; 759 760 if (!(info = PKCS7_SIGNER_INFO_new()) || 761 !Pkcs7SetSignerInfo(info, cert, hash) || 762 !PKCS7_add_signer(pkcs7, info)) { 763 goto err; 764 } 765 return info; 766err: 767 PKCS7_SIGNER_INFO_free(info); 768 return NULL; 769} 770 771 772static PKCS7_SIGNER_INFO* Pkcs7AddSignerInfo(PKCS7* pkcs7, X509* entityCert, const EVP_MD* hash, int flags) 773{ 774 PKCS7_SIGNER_INFO* info = NULL; 775 if ((info = Pkcs7AddSignature(pkcs7, entityCert, hash)) == NULL) { 776 return NULL; 777 } 778 if (!PKCS7_add_certificate(pkcs7, entityCert)) { 779 return NULL; 780 } 781 if (!PKCS7_add_attrib_content_type(info, NULL)) { 782 return NULL; 783 } 784 return info; 785} 786 787PKCS7* PKCS7Data::Pkcs7Sign(X509* entityCert, STACK_OF(X509)* certs, const EVP_MD* hash, 788 const std::string& content, int flags, const std::vector<PKCS7Attr>& attrs) 789{ 790 PKCS7* pkcs7; 791 792 if (!(pkcs7 = PKCS7_new()) || 793 !PKCS7_set_type(pkcs7, NID_pkcs7_signed) || 794 !PKCS7_content_new(pkcs7, NID_pkcs7_data) || 795 !Pkcs7AddSignerInfo(pkcs7, entityCert, hash, flags) || 796 (PKCS7AddAttribute(pkcs7, attrs) < 0)) { 797 PKCS7_free(pkcs7); 798 return NULL; 799 } 800 801 if (!(flags & PKCS7_NOCERTS)) { 802 for (int i = 0; i < sk_X509_num(certs); i++) { 803 if (!PKCS7_add_certificate(pkcs7, sk_X509_value(certs, i))) { 804 PKCS7_free(pkcs7); 805 return NULL; 806 } 807 } 808 } 809 810 if (flags & PKCS7_DETACHED) { 811 PKCS7_set_detached(pkcs7, 1); 812 } 813 814 if (Pkcs7Final(pkcs7, content, flags)) { 815 return pkcs7; 816 } 817 PKCS7_free(pkcs7); 818 return NULL; 819} 820} // namespace SignatureTools 821} // namespace OHOS