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_data.h"
17 
18 #include <string>
19 #include <openssl/asn1.h>
20 #include <securec.h>
21 
22 #include "log.h"
23 #include "openssl_utils.h"
24 
25 
26 namespace OHOS {
27 namespace Security {
28 namespace CodeSign {
PKCS7Data(const EVP_MD * md,X509 * cert)29 PKCS7Data::PKCS7Data(const EVP_MD *md, X509 *cert)
30     : cert_(cert), md_(md)
31 {
32 }
33 
~PKCS7Data()34 PKCS7Data::~PKCS7Data()
35 {
36     cert_ = nullptr;
37     md_ = nullptr;
38     if (p7_ != nullptr) {
39         // signerinfo would be freed with p7
40         PKCS7_free(p7_);
41         p7_ = nullptr;
42     }
43 }
44 
InitPKCS7Data(const std::vector<ByteBuffer> & certChain)45 bool PKCS7Data::InitPKCS7Data(const std::vector<ByteBuffer> &certChain)
46 {
47     uint32_t flags = PKCS7_BINARY | PKCS7_DETACHED | PKCS7_NOATTR | PKCS7_PARTIAL;
48     STACK_OF(X509) *certs = nullptr;
49     if (certChain.empty()) {
50         flags = flags | PKCS7_NOCERTS;
51     } else {
52         certs = MakeStackOfCerts(certChain);
53     }
54     p7_ = PKCS7_sign(nullptr, nullptr, certs, nullptr, static_cast<int>(flags));
55     if (p7_ == nullptr) {
56         sk_X509_pop_free(certs, X509_free);
57         return false;
58     }
59     return true;
60 }
61 
GetPKCS7Data(ByteBuffer & pkcs7Data)62 bool PKCS7Data::GetPKCS7Data(ByteBuffer &pkcs7Data)
63 {
64     BIO *bio = BIO_new(BIO_s_mem());
65     bool ret = false;
66     do {
67         if (bio == nullptr) {
68             break;
69         }
70         if (!i2d_PKCS7_bio(bio, p7_)) {
71             ERR_LOG_WITH_OPEN_SSL_MSG("Encode pkcs7 data failed.");
72             break;
73         }
74         uint8_t *tmp = nullptr;
75         long tmpSize = BIO_get_mem_data(bio, &tmp);
76         if ((tmpSize < 0) || (tmpSize > UINT32_MAX)) {
77             break;
78         }
79         if (!pkcs7Data.CopyFrom(tmp, static_cast<uint32_t>(tmpSize))) {
80             break;
81         }
82         ret = true;
83     } while (0);
84     BIO_free(bio);
85     return ret;
86 }
87 
AddSignerInfo(PKCS7_SIGNER_INFO * p7i)88 bool PKCS7Data::AddSignerInfo(PKCS7_SIGNER_INFO *p7i)
89 {
90     if (!PKCS7_add_signer(p7_, p7i)) {
91         PKCS7_SIGNER_INFO_free(p7i);
92         LOG_ERROR("Add signer to pkcs7 failed");
93         return false;
94     }
95     return true;
96 }
97 }
98 }
99 }