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 "cms_utils.h"
17#include "bc_signeddata_generator.h"
18#include "constant.h"
19
20namespace OHOS {
21namespace SignatureTools {
22
23bool CmsUtils::VerifySignDataWithUnsignedDataDigest(const std::vector<int8_t>& unsignedDataDigest,
24    const std::vector<int8_t>& signedData)
25{
26    int ret = 0;
27    std::string unsignedDataDigest_(unsignedDataDigest.begin(), unsignedDataDigest.end());
28    PKCS7Data p7Data(PKCS7_DETACHED_FLAGS);
29    ret = p7Data.Parse(signedData);
30    if (ret < 0) {
31        SIGNATURE_TOOLS_LOGE("verify pkcs7 signed data block bytes failed");
32        return false;
33    }
34    ret = p7Data.Verify(unsignedDataDigest_);
35    if (ret < 0) {
36        SIGNATURE_TOOLS_LOGE("verify pkcs7 signed datablock failed");
37        return false;
38    }
39    return true;
40}
41
42bool CmsUtils::CheckOwnerID(const std::string& signature, const std::string& profileOwnerID,
43    const std::string& profileType)
44{
45    std::string ownerID = profileOwnerID;
46    if (DEBUG_STR == profileType) ownerID = DEBUG_LIB_ID;
47    int nid = CreateNIDFromOID(OWNERID_OID, OWNERID_OID_SHORT_NAME, OWNERID_OID_LONG_NAME);
48    const unsigned char* data = reinterpret_cast<const unsigned char*>(signature.c_str());
49    PKCS7* p7 = d2i_PKCS7(NULL, &data, static_cast<long>(signature.size()));
50    if (p7 == nullptr) {
51        PrintErrorNumberMsg("PARSE_ERROR", PARSE_ERROR, "invalid data, parse pkcs7 failed");
52        return false;
53    }
54    STACK_OF(PKCS7_SIGNER_INFO)* signerInfosk = PKCS7_get_signer_info(p7);
55    if (signerInfosk == nullptr) {
56        PKCS7_free(p7);
57        PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR, "can't get signerinfo from pkcs7");
58        return true;
59    }
60    for (int i = 0; i < sk_PKCS7_SIGNER_INFO_num(signerInfosk); i++) {
61        PKCS7_SIGNER_INFO* signerInfo = sk_PKCS7_SIGNER_INFO_value(signerInfosk, i);
62        ASN1_TYPE* asn1Type = PKCS7_get_signed_attribute(signerInfo, nid);
63        if (asn1Type == nullptr) {
64            if (DEBUG_STR == profileType)
65                continue;
66            if (ownerID.empty()) {
67                continue;
68            } else {
69                PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, "app-identifier is not in the signature");
70                PKCS7_free(p7);
71                return false;
72            }
73        }
74        if (ownerID.empty()) {
75            PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, "app-identifier in profile is null,in signature exist");
76            PKCS7_free(p7);
77            return false;
78        }
79        if (asn1Type->type == V_ASN1_UTF8STRING) {
80            ASN1_STRING* result = asn1Type->value.asn1_string;
81            std::string result_ownerID;
82            result_ownerID.assign(reinterpret_cast<const char*>(ASN1_STRING_get0_data(result)),
83                ASN1_STRING_length(result));
84            if (ownerID != result_ownerID) {
85                PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, "app-identifier in signature is invalid");
86                PKCS7_free(p7);
87                return false;
88            }
89        }
90    }
91    PKCS7_free(p7);
92    return true;
93}
94
95int CmsUtils::CreateNIDFromOID(const std::string& oid, const std::string& shortName,
96    const std::string& longName)
97{
98    int nid = OBJ_txt2nid(oid.c_str());
99    if (nid == NID_undef) {
100        nid = OBJ_create(oid.c_str(), shortName.c_str(), longName.c_str());
101    }
102    return nid;
103}
104
105} // namespace SignatureTools
106} // namespace OHOS