1/*
2 * Copyright (c) 2023-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 "pkcs7_generator.h"
17
18#include "errcode.h"
19#include "log.h"
20#include "openssl_utils.h"
21#include "pkcs7_data.h"
22#include "securec.h"
23
24namespace OHOS {
25namespace Security {
26namespace CodeSign {
27int32_t PKCS7Generator::GenerateSignature(const std::string &ownerID, SignKey &key, const char *hashAlg,
28                                          const ByteBuffer &contentData, ByteBuffer &out)
29{
30    LOG_INFO("GenerateSignature called.");
31    int32_t ret = CS_ERR_OPENSSL_PKCS7;
32    X509 *cert = nullptr;
33    do {
34        const ByteBuffer *certBuffer = key.GetSignCert();
35        if (certBuffer == nullptr) {
36            ret = CS_ERR_HUKS_OBTAIN_CERT;
37            break;
38        }
39        cert = LoadCertFromBuffer(certBuffer->GetBuffer(), certBuffer->GetSize());
40        if (cert == nullptr) {
41            ret = CS_ERR_OPENSSL_LOAD_CERT;
42            break;
43        }
44        const EVP_MD *md = EVP_get_digestbyname(hashAlg);
45        if (md == nullptr) {
46            break;
47        }
48        PKCS7Data pkcs7(md, cert);
49        if (!pkcs7.InitPKCS7Data(key.GetCarriedCerts())) {
50            break;
51        }
52        SignerInfo signerInfo;
53        if (!signerInfo.InitSignerInfo(ownerID, cert, md, contentData)) {
54            break;
55        }
56        if (!pkcs7.AddSignerInfo(signerInfo.GetSignerInfo())) {
57            break;
58        }
59        ret = SignData(key, signerInfo);
60        if (ret != CS_SUCCESS) {
61            break;
62        }
63        if (!pkcs7.GetPKCS7Data(out)) {
64            ret = CS_ERR_OPENSSL_PKCS7;
65            break;
66        }
67        ret = CS_SUCCESS;
68    } while (0);
69    X509_free(cert);
70    if (ret != CS_SUCCESS) {
71        LOG_ERROR("Generate signature failed, ret = %{public}d", ret);
72    }
73    return ret;
74}
75
76int32_t PKCS7Generator::SignData(SignKey &key, SignerInfo &signerInfo)
77{
78    uint32_t dataSize = 0;
79    uint8_t *data = signerInfo.GetDataToSign(dataSize);
80    if (data == nullptr) {
81        LOG_ERROR("GetDataToSign fail");
82        return CS_ERR_OPENSSL_PKCS7;
83    }
84    ByteBuffer unsignedData;
85    if (!unsignedData.CopyFrom(data, dataSize)) {
86        return CS_ERR_MEMORY;
87    }
88    ByteBuffer rawSignature;
89    if (!key.Sign(unsignedData, rawSignature)) {
90        return CS_ERR_HUKS_SIGN;
91    }
92    if (!signerInfo.AddSignatureInSignerInfo(rawSignature)) {
93        LOG_ERROR("AddSignatureInSignerInfo fail");
94        return CS_ERR_OPENSSL_PKCS7;
95    }
96    return CS_SUCCESS;
97}
98}
99}
100}