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 #include "verify_hap_openssl_utils.h"
16 #include "signature_tools_log.h"
17 #include "openssl/asn1.h"
18 #include "openssl/bio.h"
19 #include "openssl/crypto.h"
20 #include "openssl/err.h"
21 #include "openssl/obj_mac.h"
22 #include "openssl/objects.h"
23 #include "openssl/rsa.h"
24 #include "openssl/x509.h"
25 #include "openssl/pem.h"
26 #include "constant.h"
27 #include "signature_info.h"
28
29 namespace OHOS {
30 namespace SignatureTools {
31 using Pkcs7SignerInfoStack = STACK_OF(PKCS7_SIGNER_INFO);
32 using X509AttributeStack = STACK_OF(X509_ATTRIBUTE);
33 const int32_t VerifyHapOpensslUtils::OPENSSL_PKCS7_VERIFY_SUCCESS = 1;
34 const int32_t VerifyHapOpensslUtils::OPENSSL_ERR_MESSAGE_MAX_LEN = 1024;
35 /*
36 * OPENSSL_READ_DATA_MAX_TIME * OPENSSL_READ_DATA_LEN_EACH_TIME < 2GBytes.
37 * make the maximum size of data that can be read each time be 1 KBytes,
38 * so the maximum times of read data is 1024 * 1024 * 2 = 2097152;
39 */
40 const int32_t VerifyHapOpensslUtils::OPENSSL_READ_DATA_MAX_TIME = 2097152;
41 const int32_t VerifyHapOpensslUtils::OPENSSL_READ_DATA_LEN_EACH_TIME = 1024;
42 /* Signature algorithm OID for extended PKCS7 */
43 const std::string VerifyHapOpensslUtils::PKCS7_EXT_SHAWITHRSA_PSS = PKCS7_EXT_SIGNATURE_OID;
44 const int32_t VerifyHapOpensslUtils::MAX_OID_LENGTH = 128;
45
ParsePkcs7Package(const unsigned char packageData[], uint32_t packageLen, Pkcs7Context& pkcs7Context)46 bool VerifyHapOpensslUtils::ParsePkcs7Package(const unsigned char packageData[],
47 uint32_t packageLen, Pkcs7Context& pkcs7Context)
48 {
49 if (packageData == nullptr || packageLen == 0) {
50 SIGNATURE_TOOLS_LOGE("invalid input");
51 return false;
52 }
53 pkcs7Context.p7 = d2i_PKCS7(nullptr, &packageData, packageLen);
54 if (!CheckPkcs7SignedDataIsValid(pkcs7Context.p7)) {
55 GetOpensslErrorMessage();
56 SIGNATURE_TOOLS_LOGE("p7 is invalid");
57 return false;
58 }
59 if (!GetContentInfo(pkcs7Context.p7->d.sign->contents, pkcs7Context.content)) {
60 SIGNATURE_TOOLS_LOGE("Get content from pkcs7 failed");
61 return false;
62 }
63 return true;
64 }
65
GetCertChains(PKCS7* p7, Pkcs7Context& pkcs7Context)66 bool VerifyHapOpensslUtils::GetCertChains(PKCS7* p7, Pkcs7Context& pkcs7Context)
67 {
68 if (!CheckPkcs7SignedDataIsValid(p7)) {
69 SIGNATURE_TOOLS_LOGE("p7 is invalid");
70 return false;
71 }
72 CertSign certVisitSign;
73 VerifyCertOpensslUtils::GenerateCertSignFromCertStack(p7->d.sign->cert, certVisitSign);
74 Pkcs7SignerInfoStack* signerInfoStack = PKCS7_get_signer_info(p7);
75 if (signerInfoStack == nullptr) {
76 SIGNATURE_TOOLS_LOGE("get signerInfoStack error");
77 GetOpensslErrorMessage();
78 return false;
79 }
80 int32_t signCount = sk_PKCS7_SIGNER_INFO_num(signerInfoStack);
81 if (signCount <= 0) {
82 SIGNATURE_TOOLS_LOGE("can not find signinfo");
83 return false;
84 }
85 for (int32_t i = 0; i < signCount; i++) {
86 /* get ith signInfo */
87 PKCS7_SIGNER_INFO* signInfo = sk_PKCS7_SIGNER_INFO_value(signerInfoStack, i);
88 if (signInfo == nullptr) {
89 SIGNATURE_TOOLS_LOGE("signInfo %dst is nullptr", i);
90 return false;
91 }
92 /* GET X509 certificate */
93 X509* cert = PKCS7_cert_from_signer_info(p7, signInfo);
94 if (cert == nullptr) {
95 SIGNATURE_TOOLS_LOGE("get cert for %dst signInfo failed", i);
96 return false;
97 }
98 CertChain certChain;
99 pkcs7Context.certChain.push_back(certChain);
100 pkcs7Context.certChain[i].push_back(X509_dup(cert));
101 VerifyCertOpensslUtils::ClearCertVisitSign(certVisitSign);
102 certVisitSign[cert] = true;
103 if (!VerifyCertChain(pkcs7Context.certChain[i], p7, signInfo, pkcs7Context, certVisitSign)) {
104 SIGNATURE_TOOLS_LOGE("verify %dst certchain failed", i);
105 return false;
106 }
107 }
108 return true;
109 }
110
VerifyCertChain(CertChain& certsChain, PKCS7* p7, PKCS7_SIGNER_INFO* signInfo, Pkcs7Context& pkcs7Context, CertSign& certVisitSign)111 bool VerifyHapOpensslUtils::VerifyCertChain(CertChain& certsChain, PKCS7* p7,
112 PKCS7_SIGNER_INFO* signInfo,
113 Pkcs7Context& pkcs7Context,
114 CertSign& certVisitSign)
115 {
116 if (!VerifyCertOpensslUtils::GetCertsChain(certsChain, certVisitSign)) {
117 SIGNATURE_TOOLS_LOGE("get cert chain for signInfo failed");
118 return false;
119 }
120 ASN1_TYPE* signTime = PKCS7_get_signed_attribute(signInfo, NID_pkcs9_signingTime);
121 if (!VerifyCertOpensslUtils::VerifyCertChainPeriodOfValidity(certsChain, signTime)) {
122 SIGNATURE_TOOLS_LOGE("VerifyCertChainPeriodOfValidity for signInfo failed");
123 return false;
124 }
125 return true;
126 }
127
CheckPkcs7SignedDataIsValid(const PKCS7* p7)128 bool VerifyHapOpensslUtils::CheckPkcs7SignedDataIsValid(const PKCS7* p7)
129 {
130 if (p7 == nullptr || !PKCS7_type_is_signed(p7) || p7->d.sign == nullptr) {
131 return false;
132 }
133 return true;
134 }
135
GetCrlStack(PKCS7* p7, STACK_OF(X509_CRL)* x509Crl)136 bool VerifyHapOpensslUtils::GetCrlStack(PKCS7* p7, STACK_OF(X509_CRL)* x509Crl)
137 {
138 if (!CheckPkcs7SignedDataIsValid(p7)) {
139 return false;
140 }
141 x509Crl = p7->d.sign->crl;
142 return true;
143 }
144
VerifyPkcs7(Pkcs7Context& pkcs7Context)145 bool VerifyHapOpensslUtils::VerifyPkcs7(Pkcs7Context& pkcs7Context)
146 {
147 if (!CheckPkcs7SignedDataIsValid(pkcs7Context.p7)) {
148 SIGNATURE_TOOLS_LOGE("p7 type is invalid signed_data_pkcs7");
149 return false;
150 }
151 if (!VerifyPkcs7SignedData(pkcs7Context)) {
152 SIGNATURE_TOOLS_LOGE("verify p7 error");
153 return false;
154 }
155 return true;
156 }
157
VerifyPkcs7SignedData(Pkcs7Context& pkcs7Context)158 bool VerifyHapOpensslUtils::VerifyPkcs7SignedData(Pkcs7Context& pkcs7Context)
159 {
160 /* get signed data which was used to be signed */
161 BIO* p7Bio = PKCS7_dataDecode(pkcs7Context.p7, nullptr, nullptr, nullptr);
162 if (p7Bio == nullptr) {
163 SIGNATURE_TOOLS_LOGE("get p7bio error");
164 GetOpensslErrorMessage();
165 return false;
166 }
167 char buf[OPENSSL_READ_DATA_LEN_EACH_TIME] = { 0 };
168 int32_t readLen = BIO_read(p7Bio, buf, sizeof(buf));
169 int32_t readTime = 0;
170 while ((readLen > 0) && (++readTime < OPENSSL_READ_DATA_MAX_TIME)) {
171 readLen = BIO_read(p7Bio, buf, sizeof(buf));
172 }
173 Pkcs7SignerInfoStack* signerInfoStack = PKCS7_get_signer_info(pkcs7Context.p7);
174 if (signerInfoStack == nullptr) {
175 SIGNATURE_TOOLS_LOGE("get signerInfoStack error");
176 BIO_free_all(p7Bio);
177 GetOpensslErrorMessage();
178 return false;
179 }
180 /* get the num of signInfo */
181 int32_t signCount = sk_PKCS7_SIGNER_INFO_num(signerInfoStack);
182 if (signCount <= 0) {
183 SIGNATURE_TOOLS_LOGE("can not find signinfo");
184 BIO_free_all(p7Bio);
185 return false;
186 }
187 for (int32_t i = 0; i < signCount; i++) {
188 if (!VerifySignInfo(signerInfoStack, p7Bio, i, pkcs7Context)) {
189 SIGNATURE_TOOLS_LOGE("Verify %dst signInfo failed", i);
190 BIO_free_all(p7Bio);
191 return false;
192 }
193 }
194 BIO_free_all(p7Bio);
195 return true;
196 }
197
198 bool VerifyHapOpensslUtils::VerifySignInfo(STACK_OF(PKCS7_SIGNER_INFO)* signerInfoStack,
199 BIO* p7Bio, int32_t signInfoNum, Pkcs7Context& pkcs7Context)
200 {
201 if (signerInfoStack == nullptr || p7Bio == nullptr) {
202 SIGNATURE_TOOLS_LOGE("invalid input");
203 return false;
204 }
205 /* get signInfo */
206 PKCS7_SIGNER_INFO* signInfo = sk_PKCS7_SIGNER_INFO_value(signerInfoStack, signInfoNum);
207 if (signInfo == nullptr) {
208 SIGNATURE_TOOLS_LOGE("signInfo %dst is nullptr", signInfoNum);
209 return false;
210 }
211 /* GET X509 certificate */
212 X509* cert = pkcs7Context.certChain[signInfoNum][0];
213
214 if (PKCS7_signatureVerify(p7Bio, pkcs7Context.p7, signInfo, cert) <= 0) {
215 SIGNATURE_TOOLS_LOGE("PKCS7_signatureVerify %dst signInfo failed", signInfoNum);
216 GetOpensslErrorMessage();
217 return false;
218 }
219
220 return true;
221 }
222
GetContentInfo(const PKCS7* p7ContentInfo, ByteBuffer& content)223 bool VerifyHapOpensslUtils::GetContentInfo(const PKCS7* p7ContentInfo, ByteBuffer& content)
224 {
225 if ((p7ContentInfo == nullptr) || !PKCS7_type_is_data(p7ContentInfo)) {
226 SIGNATURE_TOOLS_LOGE("p7ContentInfo is invalid");
227 return false;
228 }
229 ASN1_OCTET_STRING* strContentInfo = p7ContentInfo->d.data;
230 if (strContentInfo == nullptr) {
231 SIGNATURE_TOOLS_LOGE("strContentInfo is invalid");
232 return false;
233 }
234 int32_t strContentInfoLen = strContentInfo->length;
235 unsigned char* strContentInfoData = strContentInfo->data;
236 if (strContentInfoData == nullptr || strContentInfoLen <= 0) {
237 SIGNATURE_TOOLS_LOGE("ASN1_OCTET_STRING is invalid");
238 return false;
239 }
240 content.SetCapacity(strContentInfoLen);
241 content.PutData(0, reinterpret_cast<char*>(strContentInfoData), strContentInfoLen);
242 SIGNATURE_TOOLS_LOGD("strContentInfoLen: %d", strContentInfoLen);
243 return true;
244 }
245
GetOpensslErrorMessage()246 void VerifyHapOpensslUtils::GetOpensslErrorMessage()
247 {
248 unsigned long retOpenssl;
249 char errOpenssl[OPENSSL_ERR_MESSAGE_MAX_LEN];
250 while ((retOpenssl = ERR_get_error()) != 0) {
251 ERR_error_string(retOpenssl, errOpenssl);
252 SIGNATURE_TOOLS_LOGE("openssl err: %lu, message: %s", retOpenssl, errOpenssl);
253 }
254 }
255 } // namespace SignatureTools
256 } // namespace OHOS