154aa6d63Sopenharmony_ci/*
254aa6d63Sopenharmony_ci * Copyright (c) 2024-2024 Huawei Device Co., Ltd.
354aa6d63Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
454aa6d63Sopenharmony_ci * you may not use this file except in compliance with the License.
554aa6d63Sopenharmony_ci * You may obtain a copy of the License at
654aa6d63Sopenharmony_ci *
754aa6d63Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
854aa6d63Sopenharmony_ci *
954aa6d63Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1054aa6d63Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1154aa6d63Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1254aa6d63Sopenharmony_ci * See the License for the specific language governing permissions and
1354aa6d63Sopenharmony_ci * limitations under the License.
1454aa6d63Sopenharmony_ci */
1554aa6d63Sopenharmony_ci
1654aa6d63Sopenharmony_ci#include "signature_tools_log.h"
1754aa6d63Sopenharmony_ci#include "signature_tools_errno.h"
1854aa6d63Sopenharmony_ci#include "verify_hap_openssl_utils.h"
1954aa6d63Sopenharmony_ci#include "signer.h"
2054aa6d63Sopenharmony_ci#include "securec.h"
2154aa6d63Sopenharmony_ci#include "constant.h"
2254aa6d63Sopenharmony_ci#include "pkcs7_data.h"
2354aa6d63Sopenharmony_ci
2454aa6d63Sopenharmony_cinamespace OHOS {
2554aa6d63Sopenharmony_cinamespace SignatureTools {
2654aa6d63Sopenharmony_ci
2754aa6d63Sopenharmony_cistatic constexpr int BUFFER_SIZE = 4096;
2854aa6d63Sopenharmony_ci
2954aa6d63Sopenharmony_cistatic int PKCS7AddAttribute(PKCS7* p7, const std::vector<PKCS7Attr>& attrs)
3054aa6d63Sopenharmony_ci{
3154aa6d63Sopenharmony_ci    STACK_OF(PKCS7_SIGNER_INFO)* signerInfos = PKCS7_get_signer_info(p7);
3254aa6d63Sopenharmony_ci    if (signerInfos == NULL || sk_PKCS7_SIGNER_INFO_num(signerInfos) != 1) {
3354aa6d63Sopenharmony_ci        PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR,
3454aa6d63Sopenharmony_ci                            "signer info count not equal 1,pkcs7 add customize attribute failed");
3554aa6d63Sopenharmony_ci        return INVALIDPARAM_ERROR;
3654aa6d63Sopenharmony_ci    }
3754aa6d63Sopenharmony_ci    PKCS7_SIGNER_INFO* signerInfo = sk_PKCS7_SIGNER_INFO_value(signerInfos, 0);
3854aa6d63Sopenharmony_ci    for (PKCS7Attr attr : attrs) {
3954aa6d63Sopenharmony_ci        if (PKCS7_add_signed_attribute(signerInfo, attr.nid, attr.atrtype, attr.value) != 1) {
4054aa6d63Sopenharmony_ci            if (attr.atrtype == V_ASN1_UTF8STRING)
4154aa6d63Sopenharmony_ci                ASN1_STRING_free(reinterpret_cast<ASN1_STRING*>(attr.value));
4254aa6d63Sopenharmony_ci            PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR,
4354aa6d63Sopenharmony_ci                                "pkcs7 add customize attribute failed");
4454aa6d63Sopenharmony_ci            return RET_FAILED;
4554aa6d63Sopenharmony_ci        }
4654aa6d63Sopenharmony_ci    }
4754aa6d63Sopenharmony_ci    return RET_OK;
4854aa6d63Sopenharmony_ci}
4954aa6d63Sopenharmony_ci
5054aa6d63Sopenharmony_cistatic int I2dPkcs7Str(PKCS7* p7, std::string& ret)
5154aa6d63Sopenharmony_ci{
5254aa6d63Sopenharmony_ci    /* raw data exported in pkcs7 */
5354aa6d63Sopenharmony_ci    unsigned char* out = NULL;
5454aa6d63Sopenharmony_ci    int outSize = 0;
5554aa6d63Sopenharmony_ci    /* Deserialize to obtain the p7b byte stream */
5654aa6d63Sopenharmony_ci    outSize = i2d_PKCS7(p7, &out);
5754aa6d63Sopenharmony_ci    if (out == NULL || outSize <= 0) {
5854aa6d63Sopenharmony_ci        PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR,
5954aa6d63Sopenharmony_ci                            "pkcs7 is invalid");
6054aa6d63Sopenharmony_ci        return INVALIDPARAM_ERROR;
6154aa6d63Sopenharmony_ci    }
6254aa6d63Sopenharmony_ci    ret.clear();
6354aa6d63Sopenharmony_ci    ret.resize(outSize);
6454aa6d63Sopenharmony_ci    std::copy(out, out + outSize, &ret[0]);
6554aa6d63Sopenharmony_ci    OPENSSL_free(out);
6654aa6d63Sopenharmony_ci    return RET_OK;
6754aa6d63Sopenharmony_ci}
6854aa6d63Sopenharmony_ci
6954aa6d63Sopenharmony_cistatic int SetSignerInfoSignAlgor(PKCS7_SIGNER_INFO* info)
7054aa6d63Sopenharmony_ci{
7154aa6d63Sopenharmony_ci    int signNid = 0;
7254aa6d63Sopenharmony_ci    int hashNid = 0;
7354aa6d63Sopenharmony_ci    X509_ALGOR* dig;
7454aa6d63Sopenharmony_ci    X509_ALGOR* sig;
7554aa6d63Sopenharmony_ci    PKCS7_SIGNER_INFO_get0_algs(info, NULL, &dig, &sig);
7654aa6d63Sopenharmony_ci    if (dig == NULL || dig->algorithm == NULL ||
7754aa6d63Sopenharmony_ci        (hashNid = OBJ_obj2nid(dig->algorithm)) == NID_undef ||
7854aa6d63Sopenharmony_ci        !OBJ_find_sigid_by_algs(&signNid, hashNid, NID_X9_62_id_ecPublicKey) ||
7954aa6d63Sopenharmony_ci        X509_ALGOR_set0(sig, OBJ_nid2obj(signNid), V_ASN1_UNDEF, 0) != 1) {
8054aa6d63Sopenharmony_ci        return 0;
8154aa6d63Sopenharmony_ci    }
8254aa6d63Sopenharmony_ci    return 1;
8354aa6d63Sopenharmony_ci}
8454aa6d63Sopenharmony_ci
8554aa6d63Sopenharmony_cistatic int VerifySignature(PKCS7* pkcs7, BIO* p7bio)
8654aa6d63Sopenharmony_ci{
8754aa6d63Sopenharmony_ci    /* signature information */
8854aa6d63Sopenharmony_ci    STACK_OF(PKCS7_SIGNER_INFO)* skSignerInfo = NULL;
8954aa6d63Sopenharmony_ci    /* signature count */
9054aa6d63Sopenharmony_ci    int signerCount = 0;
9154aa6d63Sopenharmony_ci    /* verify signature value */
9254aa6d63Sopenharmony_ci    skSignerInfo = PKCS7_get_signer_info(pkcs7);
9354aa6d63Sopenharmony_ci    signerCount = sk_PKCS7_SIGNER_INFO_num(skSignerInfo);
9454aa6d63Sopenharmony_ci    for (int i = 0; i < signerCount; i++) {
9554aa6d63Sopenharmony_ci        PKCS7_SIGNER_INFO* signerInfo = sk_PKCS7_SIGNER_INFO_value(skSignerInfo, i);
9654aa6d63Sopenharmony_ci        X509* sigCert = PKCS7_cert_from_signer_info(pkcs7, signerInfo);
9754aa6d63Sopenharmony_ci        if (PKCS7_signatureVerify(p7bio, pkcs7, signerInfo, sigCert) != 1) {
9854aa6d63Sopenharmony_ci            PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, "signature value verify failed");
9954aa6d63Sopenharmony_ci            return VERIFY_ERROR;
10054aa6d63Sopenharmony_ci        }
10154aa6d63Sopenharmony_ci    }
10254aa6d63Sopenharmony_ci    return RET_OK;
10354aa6d63Sopenharmony_ci}
10454aa6d63Sopenharmony_ci
10554aa6d63Sopenharmony_ciPKCS7Data::PKCS7Data(int flags) : m_p7(nullptr), m_flags(flags)
10654aa6d63Sopenharmony_ci{
10754aa6d63Sopenharmony_ci}
10854aa6d63Sopenharmony_ci
10954aa6d63Sopenharmony_ciPKCS7Data::~PKCS7Data()
11054aa6d63Sopenharmony_ci{
11154aa6d63Sopenharmony_ci    PKCS7_free(m_p7);
11254aa6d63Sopenharmony_ci    m_p7 = NULL;
11354aa6d63Sopenharmony_ci}
11454aa6d63Sopenharmony_ci
11554aa6d63Sopenharmony_ciint PKCS7Data::Sign(const std::string& content, const std::shared_ptr<Signer>& signer,
11654aa6d63Sopenharmony_ci                    const std::string& sigAlg, std::string& ret, std::vector<PKCS7Attr> attrs)
11754aa6d63Sopenharmony_ci{
11854aa6d63Sopenharmony_ci    int result = RET_OK;
11954aa6d63Sopenharmony_ci    if ((result = InitPkcs7(content, signer, sigAlg, attrs)) < 0) {
12054aa6d63Sopenharmony_ci        goto err;
12154aa6d63Sopenharmony_ci    }
12254aa6d63Sopenharmony_ci
12354aa6d63Sopenharmony_ci    /* serialization */
12454aa6d63Sopenharmony_ci    if ((result = I2dPkcs7Str(m_p7, ret)) < 0) {
12554aa6d63Sopenharmony_ci        goto err;
12654aa6d63Sopenharmony_ci    }
12754aa6d63Sopenharmony_ci    /* release resources */
12854aa6d63Sopenharmony_cierr:
12954aa6d63Sopenharmony_ci    if (result < 0) {
13054aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("sign failed");
13154aa6d63Sopenharmony_ci    }
13254aa6d63Sopenharmony_ci    return result;
13354aa6d63Sopenharmony_ci}
13454aa6d63Sopenharmony_ci
13554aa6d63Sopenharmony_ciint PKCS7Data::Parse(const std::string& p7bBytes)
13654aa6d63Sopenharmony_ci{
13754aa6d63Sopenharmony_ci    const unsigned char* data = reinterpret_cast<const unsigned char*>(&p7bBytes[0]);
13854aa6d63Sopenharmony_ci    return Parse(&data, static_cast<long>(p7bBytes.size()));
13954aa6d63Sopenharmony_ci}
14054aa6d63Sopenharmony_ciint PKCS7Data::Parse(const std::vector<int8_t>& p7bBytes)
14154aa6d63Sopenharmony_ci{
14254aa6d63Sopenharmony_ci    const unsigned char* data = reinterpret_cast<const unsigned char*>(&p7bBytes[0]);
14354aa6d63Sopenharmony_ci    return Parse(&data, static_cast<long>(p7bBytes.size()));
14454aa6d63Sopenharmony_ci}
14554aa6d63Sopenharmony_ciint PKCS7Data::Parse(const unsigned char** in, long len)
14654aa6d63Sopenharmony_ci{
14754aa6d63Sopenharmony_ci    /* If p7 has been initialized, it will be released */
14854aa6d63Sopenharmony_ci    if (m_p7) {
14954aa6d63Sopenharmony_ci        PKCS7_free(m_p7);
15054aa6d63Sopenharmony_ci        m_p7 = NULL;
15154aa6d63Sopenharmony_ci    }
15254aa6d63Sopenharmony_ci    /* Deserialize */
15354aa6d63Sopenharmony_ci    m_p7 = d2i_PKCS7(NULL, in, len);
15454aa6d63Sopenharmony_ci    if (m_p7 == NULL) {
15554aa6d63Sopenharmony_ci        PrintErrorNumberMsg("PARSE_ERROR", PARSE_ERROR, "invalid p7b data, parse failed");
15654aa6d63Sopenharmony_ci        return PARSE_ERROR;
15754aa6d63Sopenharmony_ci    }
15854aa6d63Sopenharmony_ci    return RET_OK;
15954aa6d63Sopenharmony_ci}
16054aa6d63Sopenharmony_ci
16154aa6d63Sopenharmony_ciint PKCS7Data::Verify(const std::string& content) const
16254aa6d63Sopenharmony_ci{
16354aa6d63Sopenharmony_ci    if (VerifySign(content) < 0) {
16454aa6d63Sopenharmony_ci        PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, "signature verify failed");
16554aa6d63Sopenharmony_ci        return VERIFY_ERROR;
16654aa6d63Sopenharmony_ci    }
16754aa6d63Sopenharmony_ci    if (VerifyCertChain() < 0) {
16854aa6d63Sopenharmony_ci        PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, "cert Chain verify failed");
16954aa6d63Sopenharmony_ci        PrintCertChainSub(m_p7->d.sign->cert);
17054aa6d63Sopenharmony_ci        return VERIFY_ERROR;
17154aa6d63Sopenharmony_ci    }
17254aa6d63Sopenharmony_ci    return RET_OK;
17354aa6d63Sopenharmony_ci}
17454aa6d63Sopenharmony_ci
17554aa6d63Sopenharmony_ciint PKCS7Data::GetContent(std::string& originalRawData) const
17654aa6d63Sopenharmony_ci{
17754aa6d63Sopenharmony_ci    BIO* oriBio = PKCS7_dataDecode(m_p7, NULL, NULL, NULL);
17854aa6d63Sopenharmony_ci    if (oriBio == NULL) {
17954aa6d63Sopenharmony_ci        PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR, "pkcs7 get content data failed!");
18054aa6d63Sopenharmony_ci        return INVALIDPARAM_ERROR;
18154aa6d63Sopenharmony_ci    }
18254aa6d63Sopenharmony_ci    char buf[BUFFER_SIZE]{0};
18354aa6d63Sopenharmony_ci    size_t readBytes = 0;
18454aa6d63Sopenharmony_ci    while (BIO_read_ex(oriBio, buf, sizeof(buf), &readBytes) == 1) {
18554aa6d63Sopenharmony_ci        originalRawData.append(buf, readBytes);
18654aa6d63Sopenharmony_ci    }
18754aa6d63Sopenharmony_ci    BIO_free_all(oriBio);
18854aa6d63Sopenharmony_ci    return RET_OK;
18954aa6d63Sopenharmony_ci}
19054aa6d63Sopenharmony_ci
19154aa6d63Sopenharmony_cistatic void PKCS7AddCrls(PKCS7* p7, STACK_OF(X509_CRL)* crls)
19254aa6d63Sopenharmony_ci{
19354aa6d63Sopenharmony_ci    for (int i = 0; i < sk_X509_CRL_num(crls); i++) {
19454aa6d63Sopenharmony_ci        PKCS7_add_crl(p7, sk_X509_CRL_value(crls, i));
19554aa6d63Sopenharmony_ci    }
19654aa6d63Sopenharmony_ci}
19754aa6d63Sopenharmony_ci
19854aa6d63Sopenharmony_ciint PKCS7Data::InitPkcs7(const std::string& content, const std::shared_ptr<Signer>& signer,
19954aa6d63Sopenharmony_ci                         const std::string& sigAlg, std::vector<PKCS7Attr> attrs)
20054aa6d63Sopenharmony_ci{
20154aa6d63Sopenharmony_ci    STACK_OF(X509)* certs = NULL;
20254aa6d63Sopenharmony_ci    /* hash algorithm */
20354aa6d63Sopenharmony_ci    const EVP_MD* md = NULL;
20454aa6d63Sopenharmony_ci    /* entity certificate */
20554aa6d63Sopenharmony_ci    X509* cert = NULL;
20654aa6d63Sopenharmony_ci    int result = RET_OK;
20754aa6d63Sopenharmony_ci    if (signer == NULL) {
20854aa6d63Sopenharmony_ci        PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR, "signer is NULL , sign failed");
20954aa6d63Sopenharmony_ci        result = INVALIDPARAM_ERROR;
21054aa6d63Sopenharmony_ci        goto err;
21154aa6d63Sopenharmony_ci    }
21254aa6d63Sopenharmony_ci    m_signer = signer;
21354aa6d63Sopenharmony_ci    m_sigAlg = sigAlg;
21454aa6d63Sopenharmony_ci    certs = signer->GetCertificates();
21554aa6d63Sopenharmony_ci    if (SortX509Stack(certs) < 0) {
21654aa6d63Sopenharmony_ci        result = RET_FAILED;
21754aa6d63Sopenharmony_ci        goto err;
21854aa6d63Sopenharmony_ci    }
21954aa6d63Sopenharmony_ci    if (sigAlg == SIGN_ALG_SHA384) {
22054aa6d63Sopenharmony_ci        md = EVP_sha384();
22154aa6d63Sopenharmony_ci    } else if (sigAlg == SIGN_ALG_SHA256) {
22254aa6d63Sopenharmony_ci        md = EVP_sha256();
22354aa6d63Sopenharmony_ci    } else {
22454aa6d63Sopenharmony_ci        PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR,
22554aa6d63Sopenharmony_ci                            sigAlg + "is invalid sigAlg, please use SHA256withECDSA/SHA384withECDSA, sign failed");
22654aa6d63Sopenharmony_ci        result = INVALIDPARAM_ERROR;
22754aa6d63Sopenharmony_ci        goto err;
22854aa6d63Sopenharmony_ci    }
22954aa6d63Sopenharmony_ci    /* Extract the entity certificate from the certificate chain */
23054aa6d63Sopenharmony_ci    cert = sk_X509_delete(certs, 0);
23154aa6d63Sopenharmony_ci    m_p7 = Pkcs7Sign(cert, certs, md, content, m_flags, attrs);
23254aa6d63Sopenharmony_ci    if (m_p7 == NULL) {
23354aa6d63Sopenharmony_ci        PrintErrorNumberMsg("INVALIDPARAM_ERROR", SIGN_ERROR, "p7 is NULL, pkcs7 sign failed");
23454aa6d63Sopenharmony_ci        result = SIGN_ERROR;
23554aa6d63Sopenharmony_ci        goto err;
23654aa6d63Sopenharmony_ci    }
23754aa6d63Sopenharmony_ci    PKCS7AddCrls(m_p7, signer->GetCrls());
23854aa6d63Sopenharmony_ci
23954aa6d63Sopenharmony_cierr:
24054aa6d63Sopenharmony_ci    sk_X509_pop_free(certs, X509_free);
24154aa6d63Sopenharmony_ci    X509_free(cert);
24254aa6d63Sopenharmony_ci    return result;
24354aa6d63Sopenharmony_ci}
24454aa6d63Sopenharmony_ci
24554aa6d63Sopenharmony_civoid PKCS7Data::PrintCertChainSub(const STACK_OF(X509)* certs)
24654aa6d63Sopenharmony_ci{
24754aa6d63Sopenharmony_ci    if (certs == NULL)
24854aa6d63Sopenharmony_ci        return;
24954aa6d63Sopenharmony_ci    SIGNATURE_TOOLS_LOGI("certChainSubject:");
25054aa6d63Sopenharmony_ci    int certNum = sk_X509_num(certs);
25154aa6d63Sopenharmony_ci    SIGNATURE_TOOLS_LOGI("certNum%s", std::to_string(certNum).c_str());
25254aa6d63Sopenharmony_ci    for (int i = 0; i < certNum; i++) {
25354aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGI("certificate %s", std::to_string(i).c_str());
25454aa6d63Sopenharmony_ci        std::string sub;
25554aa6d63Sopenharmony_ci        VerifyCertOpensslUtils::GetSubjectFromX509(sk_X509_value(certs, i), sub);
25654aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGI("%s", sub.c_str());
25754aa6d63Sopenharmony_ci    }
25854aa6d63Sopenharmony_ci}
25954aa6d63Sopenharmony_ci
26054aa6d63Sopenharmony_cistd::string PKCS7Data::GetASN1Time(const ASN1_TIME* tm)
26154aa6d63Sopenharmony_ci{
26254aa6d63Sopenharmony_ci    if (tm == NULL) {
26354aa6d63Sopenharmony_ci        return "";
26454aa6d63Sopenharmony_ci    }
26554aa6d63Sopenharmony_ci    /* Convert the ASN1_TIME structure to a standard tm structure. */
26654aa6d63Sopenharmony_ci    struct tm time;
26754aa6d63Sopenharmony_ci    ASN1_TIME_to_tm(tm, &time);
26854aa6d63Sopenharmony_ci    /* Convert to local time(considering the time zone) */
26954aa6d63Sopenharmony_ci    time_t t = mktime(&time);
27054aa6d63Sopenharmony_ci    if (t < 0) {
27154aa6d63Sopenharmony_ci        return "";
27254aa6d63Sopenharmony_ci    }
27354aa6d63Sopenharmony_ci    struct tm* localTime = localtime(&t);
27454aa6d63Sopenharmony_ci    if (localTime == nullptr) {
27554aa6d63Sopenharmony_ci        return "";
27654aa6d63Sopenharmony_ci    }
27754aa6d63Sopenharmony_ci    /* Print local time */
27854aa6d63Sopenharmony_ci    char buf[128] = {0};
27954aa6d63Sopenharmony_ci    if (sprintf_s(buf, sizeof(buf), "%04d-%02d-%02d %02d:%02d:%02d",
28054aa6d63Sopenharmony_ci                  localTime->tm_year + YEAR1900, localTime->tm_mon + 1, localTime->tm_mday,
28154aa6d63Sopenharmony_ci                  localTime->tm_hour, localTime->tm_min, localTime->tm_sec) == -1) {
28254aa6d63Sopenharmony_ci        return "";
28354aa6d63Sopenharmony_ci    }
28454aa6d63Sopenharmony_ci    return std::string(buf, strlen(buf));
28554aa6d63Sopenharmony_ci}
28654aa6d63Sopenharmony_ci
28754aa6d63Sopenharmony_cibool PKCS7Data::X509NameCompare(const X509* cert, const X509* issuerCert)
28854aa6d63Sopenharmony_ci{
28954aa6d63Sopenharmony_ci    if (cert == nullptr || issuerCert == nullptr) {
29054aa6d63Sopenharmony_ci        PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR,
29154aa6d63Sopenharmony_ci                            "input cert is NULL");
29254aa6d63Sopenharmony_ci        return false;
29354aa6d63Sopenharmony_ci    }
29454aa6d63Sopenharmony_ci    X509_NAME* aName = X509_get_issuer_name(cert);
29554aa6d63Sopenharmony_ci    X509_NAME* bName = X509_get_subject_name(issuerCert);
29654aa6d63Sopenharmony_ci    if (X509_NAME_cmp(aName, bName) != 0) {
29754aa6d63Sopenharmony_ci        PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR,
29854aa6d63Sopenharmony_ci                            "cert issuer name is not equal to its issuer\'s  name");
29954aa6d63Sopenharmony_ci        return false;
30054aa6d63Sopenharmony_ci    }
30154aa6d63Sopenharmony_ci    return true;
30254aa6d63Sopenharmony_ci}
30354aa6d63Sopenharmony_ci
30454aa6d63Sopenharmony_ciint PKCS7Data::CheckSignTimeInValidPeriod(const ASN1_TYPE* signTime,
30554aa6d63Sopenharmony_ci                                          const ASN1_TIME* notBefore, const ASN1_TIME* notAfter)
30654aa6d63Sopenharmony_ci{
30754aa6d63Sopenharmony_ci    if (notBefore == nullptr || notBefore->data == nullptr || notAfter == nullptr || notAfter->data == nullptr) {
30854aa6d63Sopenharmony_ci        PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR,
30954aa6d63Sopenharmony_ci                            "invalid period, check signtime failed please use valid period to to check signtime");
31054aa6d63Sopenharmony_ci        return INVALIDPARAM_ERROR;
31154aa6d63Sopenharmony_ci    }
31254aa6d63Sopenharmony_ci    if (signTime == nullptr || signTime->value.asn1_string == nullptr ||
31354aa6d63Sopenharmony_ci        signTime->value.asn1_string->data == nullptr) {
31454aa6d63Sopenharmony_ci        PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR, "signtime is NULL");
31554aa6d63Sopenharmony_ci        return INVALIDPARAM_ERROR;
31654aa6d63Sopenharmony_ci    }
31754aa6d63Sopenharmony_ci    ASN1_TIME* tm = ASN1_TIME_new();
31854aa6d63Sopenharmony_ci    ASN1_TIME_set_string(tm, (reinterpret_cast<const char*>(signTime->value.asn1_string->data)));
31954aa6d63Sopenharmony_ci    if (ASN1_TIME_compare(notBefore, signTime->value.asn1_string) > 0 ||
32054aa6d63Sopenharmony_ci        ASN1_TIME_compare(notAfter, signTime->value.asn1_string) < 0) {
32154aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("sign time invalid, signTime: %s, notBefore: %s, "
32254aa6d63Sopenharmony_ci                             "notAfter: %s", GetASN1Time(tm).c_str(),
32354aa6d63Sopenharmony_ci                             GetASN1Time(notBefore).c_str(), GetASN1Time(notAfter).c_str());
32454aa6d63Sopenharmony_ci        ASN1_TIME_free(tm);
32554aa6d63Sopenharmony_ci        return RET_FAILED;
32654aa6d63Sopenharmony_ci    }
32754aa6d63Sopenharmony_ci    ASN1_TIME_free(tm);
32854aa6d63Sopenharmony_ci    return RET_OK;
32954aa6d63Sopenharmony_ci}
33054aa6d63Sopenharmony_ci
33154aa6d63Sopenharmony_cistatic X509* FindSubCertThenEraseItFromSets(X509* cert, std::unordered_set<X509*>& x509Sets)
33254aa6d63Sopenharmony_ci{
33354aa6d63Sopenharmony_ci    X509* ret = NULL;
33454aa6d63Sopenharmony_ci    for (X509* c : x509Sets) {
33554aa6d63Sopenharmony_ci        X509_NAME* name1 = X509_get_subject_name(cert);
33654aa6d63Sopenharmony_ci        X509_NAME* name2 = X509_get_issuer_name(c);
33754aa6d63Sopenharmony_ci        if (X509_NAME_cmp(name1, name2) == 0) {
33854aa6d63Sopenharmony_ci            x509Sets.erase(c);
33954aa6d63Sopenharmony_ci            ret = c;
34054aa6d63Sopenharmony_ci            break;
34154aa6d63Sopenharmony_ci        }
34254aa6d63Sopenharmony_ci    }
34354aa6d63Sopenharmony_ci    return ret;
34454aa6d63Sopenharmony_ci}
34554aa6d63Sopenharmony_ci
34654aa6d63Sopenharmony_ciint PKCS7Data::SortX509Stack(STACK_OF(X509)* certs)
34754aa6d63Sopenharmony_ci{
34854aa6d63Sopenharmony_ci    std::unordered_set<X509*> x509Sets;
34954aa6d63Sopenharmony_ci    std::list<X509*>certChain;
35054aa6d63Sopenharmony_ci    X509* tmp = NULL;
35154aa6d63Sopenharmony_ci    int result = RET_FAILED;
35254aa6d63Sopenharmony_ci
35354aa6d63Sopenharmony_ci    if (sk_X509_num(certs) < MIN_CERTS_NUM) {
35454aa6d63Sopenharmony_ci        PrintErrorNumberMsg("CERTIFICATE_ERROR", CERTIFICATE_ERROR, "cert of certchain count less than two!");
35554aa6d63Sopenharmony_ci        goto err;
35654aa6d63Sopenharmony_ci    }
35754aa6d63Sopenharmony_ci    for (int i = 0; i < sk_X509_num(certs); i++) {
35854aa6d63Sopenharmony_ci        x509Sets.insert(sk_X509_value(certs, i));
35954aa6d63Sopenharmony_ci    }
36054aa6d63Sopenharmony_ci    if (sk_X509_num(certs) != static_cast<int>(x509Sets.size())) {
36154aa6d63Sopenharmony_ci        PrintErrorNumberMsg("CERTIFICATE_ERROR", CERTIFICATE_ERROR, "sort x509 certchain failed!");
36254aa6d63Sopenharmony_ci        goto err;
36354aa6d63Sopenharmony_ci    }
36454aa6d63Sopenharmony_ci    for (X509* cert : x509Sets) {
36554aa6d63Sopenharmony_ci        if (X509_name_cmp(X509_get_subject_name(cert), X509_get_issuer_name(cert)) == 0) {
36654aa6d63Sopenharmony_ci            tmp = cert;
36754aa6d63Sopenharmony_ci            x509Sets.erase(cert);
36854aa6d63Sopenharmony_ci            break;
36954aa6d63Sopenharmony_ci        }
37054aa6d63Sopenharmony_ci    }
37154aa6d63Sopenharmony_ci    if (tmp == NULL) {
37254aa6d63Sopenharmony_ci        PrintErrorNumberMsg("CERTIFICATE_ERROR", CERTIFICATE_ERROR,
37354aa6d63Sopenharmony_ci                            "can't find root cert from certchain ,sort x509 certchain failed!");
37454aa6d63Sopenharmony_ci        goto err;
37554aa6d63Sopenharmony_ci    }
37654aa6d63Sopenharmony_ci    certChain.push_front(tmp);
37754aa6d63Sopenharmony_ci    while ((tmp = FindSubCertThenEraseItFromSets(tmp, x509Sets))) {
37854aa6d63Sopenharmony_ci        certChain.push_front(tmp);
37954aa6d63Sopenharmony_ci    }
38054aa6d63Sopenharmony_ci    if (x509Sets.size() != 0) {
38154aa6d63Sopenharmony_ci        PrintErrorNumberMsg("CERTIFICATE_ERROR", CERTIFICATE_ERROR,
38254aa6d63Sopenharmony_ci                            "certchain contain invalid cert, sort x509 certchain failed!");
38354aa6d63Sopenharmony_ci        goto err;
38454aa6d63Sopenharmony_ci    }
38554aa6d63Sopenharmony_ci    while (sk_X509_num(certs)) {
38654aa6d63Sopenharmony_ci        sk_X509_pop(certs);
38754aa6d63Sopenharmony_ci    }
38854aa6d63Sopenharmony_ci    for (X509* cert : certChain) {
38954aa6d63Sopenharmony_ci        sk_X509_push(certs, cert);
39054aa6d63Sopenharmony_ci    }
39154aa6d63Sopenharmony_ci    result = RET_OK;
39254aa6d63Sopenharmony_cierr:
39354aa6d63Sopenharmony_ci    return result;
39454aa6d63Sopenharmony_ci}
39554aa6d63Sopenharmony_ci
39654aa6d63Sopenharmony_ciint PKCS7Data::VerifySign(const std::string& content)const
39754aa6d63Sopenharmony_ci{
39854aa6d63Sopenharmony_ci    BIO* inBio = NULL;
39954aa6d63Sopenharmony_ci    if ((m_flags & PKCS7_DETACHED)) {
40054aa6d63Sopenharmony_ci        inBio = BIO_new_mem_buf(reinterpret_cast<const void*>(content.c_str()),
40154aa6d63Sopenharmony_ci                                static_cast<int>(content.size()));
40254aa6d63Sopenharmony_ci        if (inBio == NULL) {
40354aa6d63Sopenharmony_ci            PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR,
40454aa6d63Sopenharmony_ci                                "new mem buf error!,pkcs7 verify signature failed");
40554aa6d63Sopenharmony_ci            return VERIFY_ERROR;
40654aa6d63Sopenharmony_ci        }
40754aa6d63Sopenharmony_ci    }
40854aa6d63Sopenharmony_ci    if (PKCS7_verify(m_p7, NULL, NULL, inBio, NULL, m_flags) != 1) {
40954aa6d63Sopenharmony_ci        PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, "pkcs7 verify signature failed");
41054aa6d63Sopenharmony_ci        BIO_free(inBio);
41154aa6d63Sopenharmony_ci        return VERIFY_ERROR;
41254aa6d63Sopenharmony_ci    }
41354aa6d63Sopenharmony_ci    BIO_free(inBio);
41454aa6d63Sopenharmony_ci    return RET_OK;
41554aa6d63Sopenharmony_ci}
41654aa6d63Sopenharmony_ci
41754aa6d63Sopenharmony_ciint PKCS7Data::VerifyCertChain()const
41854aa6d63Sopenharmony_ci{
41954aa6d63Sopenharmony_ci    /* Validate the certificate chain */
42054aa6d63Sopenharmony_ci    STACK_OF(PKCS7_SIGNER_INFO)* skSignerInfo = PKCS7_get_signer_info(m_p7);
42154aa6d63Sopenharmony_ci    int signerCount = sk_PKCS7_SIGNER_INFO_num(skSignerInfo);
42254aa6d63Sopenharmony_ci    int c = signerCount;
42354aa6d63Sopenharmony_ci    STACK_OF(X509)* certs = NULL;
42454aa6d63Sopenharmony_ci    int result = RET_FAILED;
42554aa6d63Sopenharmony_ci    /* Original certificate chain */
42654aa6d63Sopenharmony_ci    STACK_OF(X509)* certChain = m_p7->d.sign->cert;
42754aa6d63Sopenharmony_ci    /* Copy of the certificate chain, with the entity certificate removed later */
42854aa6d63Sopenharmony_ci    certs = sk_X509_dup(certChain);
42954aa6d63Sopenharmony_ci    if (SortX509Stack(certs) < 0) {
43054aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("sort x509 stack failed, verify certchain failed");
43154aa6d63Sopenharmony_ci        goto err;
43254aa6d63Sopenharmony_ci    }
43354aa6d63Sopenharmony_ci    /* Retrieve the certificate chain without the entity certificate */
43454aa6d63Sopenharmony_ci    while (c--) {
43554aa6d63Sopenharmony_ci        sk_X509_delete(certs, 0);
43654aa6d63Sopenharmony_ci    }
43754aa6d63Sopenharmony_ci    for (int i = 0; i < signerCount; i++) {
43854aa6d63Sopenharmony_ci        PKCS7_SIGNER_INFO* signerInfo = sk_PKCS7_SIGNER_INFO_value(skSignerInfo, i);
43954aa6d63Sopenharmony_ci        if ((result = VerifySignerInfoCertchain(m_p7, signerInfo, certs, certChain)) < 0) {
44054aa6d63Sopenharmony_ci            SIGNATURE_TOOLS_LOGE("verify certchain failed");
44154aa6d63Sopenharmony_ci            goto err;
44254aa6d63Sopenharmony_ci        }
44354aa6d63Sopenharmony_ci    }
44454aa6d63Sopenharmony_ci    result = RET_OK;
44554aa6d63Sopenharmony_cierr:
44654aa6d63Sopenharmony_ci    sk_X509_free(certs);
44754aa6d63Sopenharmony_ci    return result;
44854aa6d63Sopenharmony_ci}
44954aa6d63Sopenharmony_ci
45054aa6d63Sopenharmony_ciint PKCS7Data::CheckSginerInfoSignTimeInCertChainValidPeriod(PKCS7_SIGNER_INFO* signerInfo,
45154aa6d63Sopenharmony_ci                                                             STACK_OF(X509)* certs) const
45254aa6d63Sopenharmony_ci{
45354aa6d63Sopenharmony_ci    if (signerInfo == NULL || certs == NULL) {
45454aa6d63Sopenharmony_ci        PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR, "input is NULL, check signtime invalid");
45554aa6d63Sopenharmony_ci        return INVALIDPARAM_ERROR;
45654aa6d63Sopenharmony_ci    }
45754aa6d63Sopenharmony_ci    ASN1_TYPE* signTime = PKCS7_get_signed_attribute(signerInfo, NID_pkcs9_signingTime);
45854aa6d63Sopenharmony_ci    for (int i = 0; i < sk_X509_num(certs); i++) {
45954aa6d63Sopenharmony_ci        X509* cert = sk_X509_value(certs, i);
46054aa6d63Sopenharmony_ci        const ASN1_TIME* notBefore = X509_get0_notBefore(cert);
46154aa6d63Sopenharmony_ci        const ASN1_TIME* notAfter = X509_get0_notAfter(cert);
46254aa6d63Sopenharmony_ci        if (CheckSignTimeInValidPeriod(signTime, notBefore, notAfter) < 0) {
46354aa6d63Sopenharmony_ci            SIGNATURE_TOOLS_LOGE("pkcs7 sign time check failed");
46454aa6d63Sopenharmony_ci            return INVALIDPARAM_ERROR;
46554aa6d63Sopenharmony_ci        }
46654aa6d63Sopenharmony_ci    }
46754aa6d63Sopenharmony_ci    return RET_OK;
46854aa6d63Sopenharmony_ci}
46954aa6d63Sopenharmony_ci
47054aa6d63Sopenharmony_ciint PKCS7Data::VerifySignerInfoCertchain(PKCS7* pkcs7, PKCS7_SIGNER_INFO* signerInfo,
47154aa6d63Sopenharmony_ci                                         STACK_OF(X509)* certs, STACK_OF(X509)* certChain)const
47254aa6d63Sopenharmony_ci{
47354aa6d63Sopenharmony_ci    X509* sigCert = PKCS7_cert_from_signer_info(pkcs7, signerInfo);
47454aa6d63Sopenharmony_ci    int j = 0;
47554aa6d63Sopenharmony_ci    /* Trace back through the subject information and validate the signature value of each certificate */
47654aa6d63Sopenharmony_ci    if (!X509NameCompare(sigCert, sk_X509_value(certs, 0))) {
47754aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("entity name compare not equal, verify failed");
47854aa6d63Sopenharmony_ci        return VERIFY_ERROR;
47954aa6d63Sopenharmony_ci    }
48054aa6d63Sopenharmony_ci    /* verify entity certificate signature value */
48154aa6d63Sopenharmony_ci    if (!VerifyCertOpensslUtils::CertVerify(sigCert, sk_X509_value(certs, 0))) {
48254aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("entity cert signature verify failed");
48354aa6d63Sopenharmony_ci        return VERIFY_ERROR;
48454aa6d63Sopenharmony_ci    }
48554aa6d63Sopenharmony_ci    for (; j + 1 < sk_X509_num(certs); j++) {
48654aa6d63Sopenharmony_ci        if (!X509NameCompare(sk_X509_value(certs, j), sk_X509_value(certs, j + 1))) {
48754aa6d63Sopenharmony_ci            SIGNATURE_TOOLS_LOGE("sub cert name compare not equal, verify failed");
48854aa6d63Sopenharmony_ci            return VERIFY_ERROR;
48954aa6d63Sopenharmony_ci        }
49054aa6d63Sopenharmony_ci        /* Verify the signature value of the intermediate certificate */
49154aa6d63Sopenharmony_ci        if (!VerifyCertOpensslUtils::CertVerify(sk_X509_value(certs, j), sk_X509_value(certs, j + 1))) {
49254aa6d63Sopenharmony_ci            SIGNATURE_TOOLS_LOGE("sub cert signature verify failed");
49354aa6d63Sopenharmony_ci            return VERIFY_ERROR;
49454aa6d63Sopenharmony_ci        }
49554aa6d63Sopenharmony_ci    }
49654aa6d63Sopenharmony_ci    if (!X509NameCompare(sk_X509_value(certs, j), sk_X509_value(certs, j))) {
49754aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("root cert name compare not equal, verify failed");
49854aa6d63Sopenharmony_ci        return VERIFY_ERROR;
49954aa6d63Sopenharmony_ci    }
50054aa6d63Sopenharmony_ci    /* Verify the signature value of the root certificate */
50154aa6d63Sopenharmony_ci    if (!VerifyCertOpensslUtils::CertVerify(sk_X509_value(certs, j), sk_X509_value(certs, j))) {
50254aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("root cert signature verify failed");
50354aa6d63Sopenharmony_ci        return VERIFY_ERROR;
50454aa6d63Sopenharmony_ci    }
50554aa6d63Sopenharmony_ci    /* Verify that the signature time in the signature information is within the validity period of
50654aa6d63Sopenharmony_ci    the certificate chain (entity certificate will be verified in PKCS7_verify) */
50754aa6d63Sopenharmony_ci    if (CheckSginerInfoSignTimeInCertChainValidPeriod(signerInfo, certChain) < 0) {
50854aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("sign time is invalid,verify failed");
50954aa6d63Sopenharmony_ci        return VERIFY_ERROR;
51054aa6d63Sopenharmony_ci    }
51154aa6d63Sopenharmony_ci    return RET_OK;
51254aa6d63Sopenharmony_ci}
51354aa6d63Sopenharmony_ci
51454aa6d63Sopenharmony_ciint PKCS7Data::Pkcs7SignAttr(PKCS7_SIGNER_INFO* info)
51554aa6d63Sopenharmony_ci{
51654aa6d63Sopenharmony_ci    unsigned char* attrBuf = NULL;
51754aa6d63Sopenharmony_ci    int attrLen;
51854aa6d63Sopenharmony_ci
51954aa6d63Sopenharmony_ci    std::string data;
52054aa6d63Sopenharmony_ci    std::string signature;
52154aa6d63Sopenharmony_ci    unsigned char* sigRet = NULL;
52254aa6d63Sopenharmony_ci    int sigLen = 0;
52354aa6d63Sopenharmony_ci
52454aa6d63Sopenharmony_ci    attrLen = ASN1_item_i2d((ASN1_VALUE*)info->auth_attr, &attrBuf,
52554aa6d63Sopenharmony_ci                            ASN1_ITEM_rptr(PKCS7_ATTR_SIGN));
52654aa6d63Sopenharmony_ci    if (!attrBuf) {
52754aa6d63Sopenharmony_ci        OPENSSL_free(attrBuf);
52854aa6d63Sopenharmony_ci        return 0;
52954aa6d63Sopenharmony_ci    }
53054aa6d63Sopenharmony_ci
53154aa6d63Sopenharmony_ci    data.assign(reinterpret_cast<const char*>(attrBuf), attrLen);
53254aa6d63Sopenharmony_ci    signature = m_signer->GetSignature(data, m_sigAlg);
53354aa6d63Sopenharmony_ci    if (signature.empty()) {
53454aa6d63Sopenharmony_ci        OPENSSL_free(attrBuf);
53554aa6d63Sopenharmony_ci        return 0;
53654aa6d63Sopenharmony_ci    }
53754aa6d63Sopenharmony_ci    sigLen = signature.size();
53854aa6d63Sopenharmony_ci    sigRet = reinterpret_cast<unsigned char*>(OPENSSL_malloc(sigLen));
53954aa6d63Sopenharmony_ci    if (sigRet == NULL) {
54054aa6d63Sopenharmony_ci        OPENSSL_free(attrBuf);
54154aa6d63Sopenharmony_ci        return 0;
54254aa6d63Sopenharmony_ci    }
54354aa6d63Sopenharmony_ci    std::copy(&signature[0], &signature[0] + signature.size(), sigRet);
54454aa6d63Sopenharmony_ci    ASN1_STRING_set0(info->enc_digest, sigRet, sigLen);
54554aa6d63Sopenharmony_ci    OPENSSL_free(attrBuf);
54654aa6d63Sopenharmony_ci    return 1;
54754aa6d63Sopenharmony_ci}
54854aa6d63Sopenharmony_ci
54954aa6d63Sopenharmony_cistatic ASN1_OCTET_STRING* PKCS7GetASN1Content(PKCS7* pkcs7)
55054aa6d63Sopenharmony_ci{
55154aa6d63Sopenharmony_ci    if (PKCS7_type_is_data(pkcs7)) {
55254aa6d63Sopenharmony_ci        return pkcs7->d.data;
55354aa6d63Sopenharmony_ci    }
55454aa6d63Sopenharmony_ci    return NULL;
55554aa6d63Sopenharmony_ci}
55654aa6d63Sopenharmony_ci
55754aa6d63Sopenharmony_ciint PKCS7Data::Pkcs7AddTimeDigestAndSignAttr(PKCS7_SIGNER_INFO* info, EVP_MD_CTX* hashCtx)
55854aa6d63Sopenharmony_ci{
55954aa6d63Sopenharmony_ci    unsigned char hashData[EVP_MAX_MD_SIZE];
56054aa6d63Sopenharmony_ci    unsigned int hashLen;
56154aa6d63Sopenharmony_ci
56254aa6d63Sopenharmony_ci    /* add signing time */
56354aa6d63Sopenharmony_ci    if (!PKCS7_get_signed_attribute(info, NID_pkcs9_signingTime)) {
56454aa6d63Sopenharmony_ci        if (!PKCS7_add0_attrib_signing_time(info, NULL)) {
56554aa6d63Sopenharmony_ci            return 0;
56654aa6d63Sopenharmony_ci        }
56754aa6d63Sopenharmony_ci    }
56854aa6d63Sopenharmony_ci
56954aa6d63Sopenharmony_ci    /* add digest */
57054aa6d63Sopenharmony_ci    if (!EVP_DigestFinal_ex(hashCtx, hashData, &hashLen)) {
57154aa6d63Sopenharmony_ci        return 0;
57254aa6d63Sopenharmony_ci    }
57354aa6d63Sopenharmony_ci    if (!PKCS7_add1_attrib_digest(info, hashData, hashLen)) {
57454aa6d63Sopenharmony_ci        return 0;
57554aa6d63Sopenharmony_ci    }
57654aa6d63Sopenharmony_ci
57754aa6d63Sopenharmony_ci    /* sign the attributes */
57854aa6d63Sopenharmony_ci    if (!Pkcs7SignAttr(info)) {
57954aa6d63Sopenharmony_ci        return 0;
58054aa6d63Sopenharmony_ci    }
58154aa6d63Sopenharmony_ci
58254aa6d63Sopenharmony_ci    return 1;
58354aa6d63Sopenharmony_ci}
58454aa6d63Sopenharmony_ci
58554aa6d63Sopenharmony_cistatic BIO* PKCS7SearchDigest(EVP_MD_CTX** pHash, BIO* io, int numberID)
58654aa6d63Sopenharmony_ci{
58754aa6d63Sopenharmony_ci    while ((io = BIO_find_type(io, BIO_TYPE_MD))) {
58854aa6d63Sopenharmony_ci        BIO_get_md_ctx(io, pHash);
58954aa6d63Sopenharmony_ci        if (*pHash == NULL) {
59054aa6d63Sopenharmony_ci            return NULL;
59154aa6d63Sopenharmony_ci        }
59254aa6d63Sopenharmony_ci        if (EVP_MD_CTX_type(*pHash) == numberID) {
59354aa6d63Sopenharmony_ci            return io;
59454aa6d63Sopenharmony_ci        }
59554aa6d63Sopenharmony_ci        io = BIO_next(io);
59654aa6d63Sopenharmony_ci    }
59754aa6d63Sopenharmony_ci    return NULL;
59854aa6d63Sopenharmony_ci}
59954aa6d63Sopenharmony_ci
60054aa6d63Sopenharmony_cistatic int PKCS7DataFinalCheck(PKCS7* pkcs7, BIO* bio,
60154aa6d63Sopenharmony_ci                               STACK_OF(PKCS7_SIGNER_INFO)** psk, ASN1_OCTET_STRING** pos)
60254aa6d63Sopenharmony_ci{
60354aa6d63Sopenharmony_ci    int id = 0;
60454aa6d63Sopenharmony_ci
60554aa6d63Sopenharmony_ci    if (pkcs7 == NULL || pkcs7->d.ptr == NULL) {
60654aa6d63Sopenharmony_ci        return 0;
60754aa6d63Sopenharmony_ci    }
60854aa6d63Sopenharmony_ci
60954aa6d63Sopenharmony_ci    id = OBJ_obj2nid(pkcs7->type);
61054aa6d63Sopenharmony_ci    pkcs7->state = PKCS7_S_HEADER;
61154aa6d63Sopenharmony_ci
61254aa6d63Sopenharmony_ci    if (id == NID_pkcs7_signed) {
61354aa6d63Sopenharmony_ci        *psk = pkcs7->d.sign->signer_info;
61454aa6d63Sopenharmony_ci        *pos = PKCS7GetASN1Content(pkcs7->d.sign->contents);
61554aa6d63Sopenharmony_ci        if (PKCS7_type_is_data(pkcs7->d.sign->contents) && pkcs7->detached) {
61654aa6d63Sopenharmony_ci            ASN1_OCTET_STRING_free(*pos);
61754aa6d63Sopenharmony_ci            *pos = NULL;
61854aa6d63Sopenharmony_ci            pkcs7->d.sign->contents->d.data = NULL;
61954aa6d63Sopenharmony_ci        }
62054aa6d63Sopenharmony_ci        return 1;
62154aa6d63Sopenharmony_ci    }
62254aa6d63Sopenharmony_ci    return 0;
62354aa6d63Sopenharmony_ci}
62454aa6d63Sopenharmony_ci
62554aa6d63Sopenharmony_ciint PKCS7Data::Pkcs7DataFinalSignAttr(STACK_OF(PKCS7_SIGNER_INFO)* infoStack, BIO* bio)
62654aa6d63Sopenharmony_ci{
62754aa6d63Sopenharmony_ci    EVP_MD_CTX* hashCtx = NULL;
62854aa6d63Sopenharmony_ci    STACK_OF(X509_ATTRIBUTE)* attrStack = NULL;
62954aa6d63Sopenharmony_ci    BIO* ioTmp = NULL;
63054aa6d63Sopenharmony_ci    int result = 0;
63154aa6d63Sopenharmony_ci    EVP_MD_CTX* ctxTmp = EVP_MD_CTX_new();
63254aa6d63Sopenharmony_ci    if (ctxTmp == NULL) {
63354aa6d63Sopenharmony_ci        return 0;
63454aa6d63Sopenharmony_ci    }
63554aa6d63Sopenharmony_ci
63654aa6d63Sopenharmony_ci    if (infoStack == NULL) {
63754aa6d63Sopenharmony_ci        goto err;
63854aa6d63Sopenharmony_ci    }
63954aa6d63Sopenharmony_ci    for (int i = 0; i < sk_PKCS7_SIGNER_INFO_num(infoStack); i++) {
64054aa6d63Sopenharmony_ci        PKCS7_SIGNER_INFO* info = sk_PKCS7_SIGNER_INFO_value(infoStack, i);
64154aa6d63Sopenharmony_ci
64254aa6d63Sopenharmony_ci        int numberID = OBJ_obj2nid(info->digest_alg->algorithm);
64354aa6d63Sopenharmony_ci
64454aa6d63Sopenharmony_ci        ioTmp = bio;
64554aa6d63Sopenharmony_ci
64654aa6d63Sopenharmony_ci        ioTmp = PKCS7SearchDigest(&hashCtx, ioTmp, numberID);
64754aa6d63Sopenharmony_ci
64854aa6d63Sopenharmony_ci        if (ioTmp == NULL || !EVP_MD_CTX_copy_ex(ctxTmp, hashCtx)) {
64954aa6d63Sopenharmony_ci            goto err;
65054aa6d63Sopenharmony_ci        }
65154aa6d63Sopenharmony_ci
65254aa6d63Sopenharmony_ci        attrStack = info->auth_attr;
65354aa6d63Sopenharmony_ci
65454aa6d63Sopenharmony_ci        if (sk_X509_ATTRIBUTE_num(attrStack) > 0) {
65554aa6d63Sopenharmony_ci            if (!Pkcs7AddTimeDigestAndSignAttr(info, ctxTmp)) {
65654aa6d63Sopenharmony_ci                goto err;
65754aa6d63Sopenharmony_ci            }
65854aa6d63Sopenharmony_ci        } else {
65954aa6d63Sopenharmony_ci            goto err;
66054aa6d63Sopenharmony_ci        }
66154aa6d63Sopenharmony_ci    }
66254aa6d63Sopenharmony_ci    result = 1;
66354aa6d63Sopenharmony_cierr:
66454aa6d63Sopenharmony_ci    EVP_MD_CTX_free(ctxTmp);
66554aa6d63Sopenharmony_ci    return result;
66654aa6d63Sopenharmony_ci}
66754aa6d63Sopenharmony_ci
66854aa6d63Sopenharmony_cistatic int PKCS7DataFinalSetContent(PKCS7* pkcs7, ASN1_OCTET_STRING* asn1Str, BIO* io)
66954aa6d63Sopenharmony_ci{
67054aa6d63Sopenharmony_ci    BIO* ioTmp = NULL;
67154aa6d63Sopenharmony_ci    if (!PKCS7_is_detached(pkcs7)) {
67254aa6d63Sopenharmony_ci        if (asn1Str == NULL) {
67354aa6d63Sopenharmony_ci            return 0;
67454aa6d63Sopenharmony_ci        }
67554aa6d63Sopenharmony_ci        if (!(asn1Str->flags & ASN1_STRING_FLAG_NDEF)) {
67654aa6d63Sopenharmony_ci            char* contentData;
67754aa6d63Sopenharmony_ci            long contentLen;
67854aa6d63Sopenharmony_ci            ioTmp = BIO_find_type(io, BIO_TYPE_MEM);
67954aa6d63Sopenharmony_ci            if (ioTmp == NULL) {
68054aa6d63Sopenharmony_ci                return 0;
68154aa6d63Sopenharmony_ci            }
68254aa6d63Sopenharmony_ci            contentLen = BIO_get_mem_data(ioTmp, &contentData);
68354aa6d63Sopenharmony_ci
68454aa6d63Sopenharmony_ci            BIO_set_flags(ioTmp, BIO_FLAGS_MEM_RDONLY);
68554aa6d63Sopenharmony_ci            BIO_set_mem_eof_return(ioTmp, 0);
68654aa6d63Sopenharmony_ci            ASN1_STRING_set0(asn1Str, (unsigned char*)contentData, contentLen);
68754aa6d63Sopenharmony_ci        }
68854aa6d63Sopenharmony_ci    }
68954aa6d63Sopenharmony_ci    return 1;
69054aa6d63Sopenharmony_ci}
69154aa6d63Sopenharmony_ciint PKCS7Data::Pkcs7DataFinal(PKCS7* pkcs7, BIO* io)
69254aa6d63Sopenharmony_ci{
69354aa6d63Sopenharmony_ci    STACK_OF(PKCS7_SIGNER_INFO)* infoStack = NULL;
69454aa6d63Sopenharmony_ci    ASN1_OCTET_STRING* os = NULL;
69554aa6d63Sopenharmony_ci
69654aa6d63Sopenharmony_ci    if (!PKCS7DataFinalCheck(pkcs7, io, &infoStack, &os) ||
69754aa6d63Sopenharmony_ci        !Pkcs7DataFinalSignAttr(infoStack, io) ||
69854aa6d63Sopenharmony_ci        !PKCS7DataFinalSetContent(pkcs7, os, io)) {
69954aa6d63Sopenharmony_ci        return 0;
70054aa6d63Sopenharmony_ci    }
70154aa6d63Sopenharmony_ci    return 1;
70254aa6d63Sopenharmony_ci}
70354aa6d63Sopenharmony_ci
70454aa6d63Sopenharmony_ciint PKCS7Data::Pkcs7Final(PKCS7* pkcs7, const std::string& content, int flags)
70554aa6d63Sopenharmony_ci{
70654aa6d63Sopenharmony_ci    BIO* p7bio;
70754aa6d63Sopenharmony_ci    int result = 0;
70854aa6d63Sopenharmony_ci
70954aa6d63Sopenharmony_ci    if ((p7bio = PKCS7_dataInit(pkcs7, NULL)) == NULL) {
71054aa6d63Sopenharmony_ci        return 0;
71154aa6d63Sopenharmony_ci    }
71254aa6d63Sopenharmony_ci
71354aa6d63Sopenharmony_ci    if (BIO_write(p7bio, content.c_str(), static_cast<int>(content.size())) <= 0) {
71454aa6d63Sopenharmony_ci        SIGNATURE_TOOLS_LOGE("add json data to pkcs7 failed");
71554aa6d63Sopenharmony_ci        goto err;
71654aa6d63Sopenharmony_ci    }
71754aa6d63Sopenharmony_ci
71854aa6d63Sopenharmony_ci    (void)BIO_flush(p7bio);
71954aa6d63Sopenharmony_ci
72054aa6d63Sopenharmony_ci    if (!Pkcs7DataFinal(pkcs7, p7bio)) {
72154aa6d63Sopenharmony_ci        goto err;
72254aa6d63Sopenharmony_ci    }
72354aa6d63Sopenharmony_ci    /* Verify the signature value */
72454aa6d63Sopenharmony_ci    if (VerifySignature(pkcs7, p7bio) < 0) {
72554aa6d63Sopenharmony_ci        goto err;
72654aa6d63Sopenharmony_ci    }
72754aa6d63Sopenharmony_ci    result = 1;
72854aa6d63Sopenharmony_ci
72954aa6d63Sopenharmony_cierr:
73054aa6d63Sopenharmony_ci    BIO_free_all(p7bio);
73154aa6d63Sopenharmony_ci    return result;
73254aa6d63Sopenharmony_ci}
73354aa6d63Sopenharmony_ci
73454aa6d63Sopenharmony_cistatic int Pkcs7SetSignerInfo(PKCS7_SIGNER_INFO* info, X509* cert, const EVP_MD* hash)
73554aa6d63Sopenharmony_ci{
73654aa6d63Sopenharmony_ci    if (!ASN1_INTEGER_set(info->version, 1) ||
73754aa6d63Sopenharmony_ci        !X509_NAME_set(&info->issuer_and_serial->issuer, X509_get_issuer_name(cert))) {
73854aa6d63Sopenharmony_ci        return 0;
73954aa6d63Sopenharmony_ci    }
74054aa6d63Sopenharmony_ci
74154aa6d63Sopenharmony_ci    ASN1_INTEGER_free(info->issuer_and_serial->serial);
74254aa6d63Sopenharmony_ci    if (!(info->issuer_and_serial->serial =
74354aa6d63Sopenharmony_ci          ASN1_INTEGER_dup(X509_get_serialNumber(cert)))) {
74454aa6d63Sopenharmony_ci        return 0;
74554aa6d63Sopenharmony_ci    }
74654aa6d63Sopenharmony_ci
74754aa6d63Sopenharmony_ci    X509_ALGOR_set0(info->digest_alg, OBJ_nid2obj(EVP_MD_type(hash)),
74854aa6d63Sopenharmony_ci                    V_ASN1_NULL, NULL);
74954aa6d63Sopenharmony_ci
75054aa6d63Sopenharmony_ci    if (!SetSignerInfoSignAlgor(info)) {
75154aa6d63Sopenharmony_ci        return 0;
75254aa6d63Sopenharmony_ci    }
75354aa6d63Sopenharmony_ci    return 1;
75454aa6d63Sopenharmony_ci}
75554aa6d63Sopenharmony_ci
75654aa6d63Sopenharmony_cistatic PKCS7_SIGNER_INFO* Pkcs7AddSignature(PKCS7* pkcs7, X509* cert, const EVP_MD* hash)
75754aa6d63Sopenharmony_ci{
75854aa6d63Sopenharmony_ci    PKCS7_SIGNER_INFO* info = NULL;
75954aa6d63Sopenharmony_ci
76054aa6d63Sopenharmony_ci    if (!(info = PKCS7_SIGNER_INFO_new()) ||
76154aa6d63Sopenharmony_ci        !Pkcs7SetSignerInfo(info, cert, hash) ||
76254aa6d63Sopenharmony_ci        !PKCS7_add_signer(pkcs7, info)) {
76354aa6d63Sopenharmony_ci        goto err;
76454aa6d63Sopenharmony_ci    }
76554aa6d63Sopenharmony_ci    return info;
76654aa6d63Sopenharmony_cierr:
76754aa6d63Sopenharmony_ci    PKCS7_SIGNER_INFO_free(info);
76854aa6d63Sopenharmony_ci    return NULL;
76954aa6d63Sopenharmony_ci}
77054aa6d63Sopenharmony_ci
77154aa6d63Sopenharmony_ci
77254aa6d63Sopenharmony_cistatic PKCS7_SIGNER_INFO* Pkcs7AddSignerInfo(PKCS7* pkcs7, X509* entityCert, const EVP_MD* hash, int flags)
77354aa6d63Sopenharmony_ci{
77454aa6d63Sopenharmony_ci    PKCS7_SIGNER_INFO* info = NULL;
77554aa6d63Sopenharmony_ci    if ((info = Pkcs7AddSignature(pkcs7, entityCert, hash)) == NULL) {
77654aa6d63Sopenharmony_ci        return NULL;
77754aa6d63Sopenharmony_ci    }
77854aa6d63Sopenharmony_ci    if (!PKCS7_add_certificate(pkcs7, entityCert)) {
77954aa6d63Sopenharmony_ci        return NULL;
78054aa6d63Sopenharmony_ci    }
78154aa6d63Sopenharmony_ci    if (!PKCS7_add_attrib_content_type(info, NULL)) {
78254aa6d63Sopenharmony_ci        return NULL;
78354aa6d63Sopenharmony_ci    }
78454aa6d63Sopenharmony_ci    return info;
78554aa6d63Sopenharmony_ci}
78654aa6d63Sopenharmony_ci
78754aa6d63Sopenharmony_ciPKCS7* PKCS7Data::Pkcs7Sign(X509* entityCert, STACK_OF(X509)* certs, const EVP_MD* hash,
78854aa6d63Sopenharmony_ci                            const std::string& content, int flags, const std::vector<PKCS7Attr>& attrs)
78954aa6d63Sopenharmony_ci{
79054aa6d63Sopenharmony_ci    PKCS7* pkcs7;
79154aa6d63Sopenharmony_ci
79254aa6d63Sopenharmony_ci    if (!(pkcs7 = PKCS7_new()) ||
79354aa6d63Sopenharmony_ci        !PKCS7_set_type(pkcs7, NID_pkcs7_signed) ||
79454aa6d63Sopenharmony_ci        !PKCS7_content_new(pkcs7, NID_pkcs7_data) ||
79554aa6d63Sopenharmony_ci        !Pkcs7AddSignerInfo(pkcs7, entityCert, hash, flags) ||
79654aa6d63Sopenharmony_ci        (PKCS7AddAttribute(pkcs7, attrs) < 0)) {
79754aa6d63Sopenharmony_ci        PKCS7_free(pkcs7);
79854aa6d63Sopenharmony_ci        return NULL;
79954aa6d63Sopenharmony_ci    }
80054aa6d63Sopenharmony_ci
80154aa6d63Sopenharmony_ci    if (!(flags & PKCS7_NOCERTS)) {
80254aa6d63Sopenharmony_ci        for (int i = 0; i < sk_X509_num(certs); i++) {
80354aa6d63Sopenharmony_ci            if (!PKCS7_add_certificate(pkcs7, sk_X509_value(certs, i))) {
80454aa6d63Sopenharmony_ci                PKCS7_free(pkcs7);
80554aa6d63Sopenharmony_ci                return NULL;
80654aa6d63Sopenharmony_ci            }
80754aa6d63Sopenharmony_ci        }
80854aa6d63Sopenharmony_ci    }
80954aa6d63Sopenharmony_ci
81054aa6d63Sopenharmony_ci    if (flags & PKCS7_DETACHED) {
81154aa6d63Sopenharmony_ci        PKCS7_set_detached(pkcs7, 1);
81254aa6d63Sopenharmony_ci    }
81354aa6d63Sopenharmony_ci
81454aa6d63Sopenharmony_ci    if (Pkcs7Final(pkcs7, content, flags)) {
81554aa6d63Sopenharmony_ci        return pkcs7;
81654aa6d63Sopenharmony_ci    }
81754aa6d63Sopenharmony_ci    PKCS7_free(pkcs7);
81854aa6d63Sopenharmony_ci    return NULL;
81954aa6d63Sopenharmony_ci}
82054aa6d63Sopenharmony_ci} // namespace SignatureTools
82154aa6d63Sopenharmony_ci} // namespace OHOS