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 
24 namespace OHOS {
25 namespace Security {
26 namespace CodeSign {
GenerateSignature(const std::string & ownerID,SignKey & key,const char * hashAlg,const ByteBuffer & contentData,ByteBuffer & out)27 int32_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 
SignData(SignKey & key,SignerInfo & signerInfo)76 int32_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 }