1 /*
2 * Copyright (c) 2022 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_signed_data.h"
17 #include <openssl/asn1.h>
18 #include <openssl/bio.h>
19 #include <openssl/pkcs7.h>
20 #include <openssl/rsa.h>
21 #include <openssl/sha.h>
22 #include <openssl/x509.h>
23 #include "cert_verify.h"
24 #include "dump.h"
25 #include "openssl_util.h"
26 #include "pkg_utils.h"
27
28 namespace Hpackage {
29 namespace {
30 constexpr size_t g_digestAlgoLength[][2] = {
31 {NID_sha256, SHA256_DIGEST_LENGTH},
32 };
33
GetDigestLength(const size_t digestNid)34 size_t GetDigestLength(const size_t digestNid)
35 {
36 for (size_t i = 0; i < sizeof(g_digestAlgoLength) / sizeof(g_digestAlgoLength[0]); i++) {
37 if (digestNid == g_digestAlgoLength[i][0]) {
38 return g_digestAlgoLength[i][1];
39 }
40 }
41 return 0;
42 }
43 }
44
~Pkcs7SignedData()45 Pkcs7SignedData::~Pkcs7SignedData()
46 {
47 if (pkcs7_ != nullptr) {
48 PKCS7_free(pkcs7_);
49 pkcs7_ = nullptr;
50 }
51 }
52
GetHashFromSignBlock(const uint8_t * srcData,const size_t dataLen,std::vector<uint8_t> & hash)53 int32_t Pkcs7SignedData::GetHashFromSignBlock(const uint8_t *srcData, const size_t dataLen,
54 std::vector<uint8_t> &hash)
55 {
56 Updater::UPDATER_INIT_RECORD;
57 int32_t ret = ParsePkcs7Data(srcData, dataLen);
58 if (ret != 0) {
59 PKG_LOGE("parse pkcs7 data fail");
60 UPDATER_LAST_WORD(ret, "parse pkcs7 data fail");
61 return ret;
62 }
63
64 ret = Verify();
65 if (ret != 0) {
66 PKG_LOGE("verify pkcs7 data fail");
67 UPDATER_LAST_WORD(ret, "verify pkcs7 data fail");
68 return ret;
69 }
70 hash.assign(digest_.begin(), digest_.end());
71
72 return 0;
73 }
74
ParsePkcs7Data(const uint8_t * srcData,const size_t dataLen)75 int32_t Pkcs7SignedData::ParsePkcs7Data(const uint8_t *srcData, const size_t dataLen)
76 {
77 Updater::UPDATER_INIT_RECORD;
78 if (srcData == nullptr || dataLen == 0) {
79 UPDATER_LAST_WORD(-1, "srcData or dataLen is invalid");
80 return -1;
81 }
82 if (Init(srcData, dataLen) != 0) {
83 PKG_LOGE("init pkcs7 data fail");
84 UPDATER_LAST_WORD(-1, "init pkcs7 data fail");
85 return -1;
86 }
87
88 return DoParse();
89 }
90
Verify() const91 int32_t Pkcs7SignedData::Verify() const
92 {
93 std::vector<uint8_t> digestForEVP;
94 for (unsigned int i = 0; i < signatureInfo.overall.length; i++) {
95 digestForEVP.push_back(static_cast<uint8_t>(signatureInfo.overall.buffer[i]));
96 }
97 if (Verify(digestForEVP, {}, true) == 0) {
98 return 0;
99 }
100 return Verify(digest_, {}, true);
101 }
102
Verify(const std::vector<uint8_t> & hash,const std::vector<uint8_t> & sig,bool sigInSignerInfo) const103 int32_t Pkcs7SignedData::Verify(const std::vector<uint8_t> &hash, const std::vector<uint8_t> &sig,
104 bool sigInSignerInfo) const
105 {
106 if (hash.empty()) {
107 return -1;
108 }
109 int32_t ret = -1;
110 for (auto &signerInfo : signerInfos_) {
111 ret = Pkcs7SignleSignerVerify(signerInfo, hash, sigInSignerInfo ? signerInfo.digestEncryptData : sig);
112 if (ret == 0) {
113 PKG_LOGI("p7sourceData check success");
114 break;
115 }
116 PKG_LOGI("p7sourceData continue");
117 }
118
119 return ret;
120 }
121
Init(const uint8_t * sourceData,const uint32_t sourceDataLen)122 int32_t Pkcs7SignedData::Init(const uint8_t *sourceData, const uint32_t sourceDataLen)
123 {
124 Updater::UPDATER_INIT_RECORD;
125 BIO *p7Bio = BIO_new(BIO_s_mem());
126 if (p7Bio == nullptr) {
127 PKG_LOGE("BIO_new error!");
128 UPDATER_LAST_WORD(-1, "BIO_new error!");
129 return -1;
130 }
131 if (static_cast<uint32_t>(BIO_write(p7Bio, sourceData, sourceDataLen)) != sourceDataLen) {
132 PKG_LOGE("BIO_write error!");
133 UPDATER_LAST_WORD(-1, "BIO_write error!");
134 BIO_free(p7Bio);
135 return -1;
136 }
137
138 if (pkcs7_ != nullptr) {
139 PKCS7_free(pkcs7_);
140 pkcs7_ = nullptr;
141 }
142 pkcs7_ = d2i_PKCS7_bio(p7Bio, nullptr);
143 if (pkcs7_ == nullptr) {
144 PKG_LOGE("d2i_PKCS7_bio failed!");
145 BIO_free(p7Bio);
146 UPDATER_LAST_WORD(-1, "d2i_PKCS7_bio failed!");
147 return -1;
148 }
149
150 int32_t type = OBJ_obj2nid(pkcs7_->type);
151 if (type != NID_pkcs7_signed) {
152 PKG_LOGE("Invalid pkcs7 data type %d", type);
153 BIO_free(p7Bio);
154 UPDATER_LAST_WORD(type, "Invalid pkcs7 data type");
155 return -1;
156 }
157
158 BIO_free(p7Bio);
159 if (CertVerify::GetInstance().Init() != 0) {
160 PKG_LOGE("init cert verify fail");
161 UPDATER_LAST_WORD(-1, "init cert verify fail");
162 return -1;
163 }
164 return 0;
165 }
166
167 /*
168 * tools.ietf.org/html/rfc2315#section-9.1
169 * SignedData ::= SEQUENCE(0x30) {
170 * INTEGER(0x02) version Version,
171 * SET(0x31) digestAlgorithms DigestAlgorithmIdentifiers,
172 * SEQUENCE(0x30) contentInfo ContentInfo,
173 * CONTET_SPECIFIC[0](0xA0) certificates [0] IMPLICIT ExtendedCertificatesAndCertificates OPTIONAL,
174 * CONTET_SPECIFIC[1](0xA1) crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
175 * SET(0x31) signerInfos SignerInfos }
176 */
DoParse()177 int32_t Pkcs7SignedData::DoParse()
178 {
179 Updater::UPDATER_INIT_RECORD;
180 std::vector<uint8_t> contentInfo;
181 int32_t ret = ParseContentInfo(contentInfo);
182 if (ret != 0) {
183 PKG_LOGE("parse pkcs7 contentInfo fail");
184 UPDATER_LAST_WORD(-1, "parse pkcs7 contentInfo fail");
185 return -1;
186 }
187
188 if (GetInstance().GetDigest(contentInfo, signatureInfo, digest_) != 0) {
189 ret = GetDigestFromContentInfo(contentInfo);
190 if (ret != 0) {
191 PKG_LOGE("invalid pkcs7 contentInfo fail");
192 UPDATER_LAST_WORD(-1, "invalid pkcs7 contentInfo fail");
193 return -1;
194 }
195 }
196
197 return SignerInfosParse();
198 }
199
200 /*
201 * tools.ietf.org/html/rfc2315#section-7
202 * ContentInfo ::= SEQUENCE(0x30) {
203 * OBJECT_IDENTIFIER(0x06) contentType ContentType,
204 * CONTET_SPECIFIC[0](0xA0) content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
205 *
206 * tools.ietf.org/html/rfc2315#section-8
207 * Data ::= OCTET STRING
208 */
ParseContentInfo(std::vector<uint8_t> & digestBlock) const209 int32_t Pkcs7SignedData::ParseContentInfo(std::vector<uint8_t> &digestBlock) const
210 {
211 Updater::UPDATER_INIT_RECORD;
212 PKCS7_SIGNED *signData = pkcs7_->d.sign;
213 if (signData == nullptr) {
214 PKG_LOGE("invalid pkcs7 signed data!");
215 UPDATER_LAST_WORD(-1, "invalid pkcs7 signed data!");
216 return -1;
217 }
218
219 PKCS7 *contentInfo = signData->contents;
220 if (contentInfo == nullptr) {
221 PKG_LOGE("pkcs7 content is nullptr!");
222 UPDATER_LAST_WORD(-1, "pkcs7 content is nullptr!");
223 return -1;
224 }
225 if (OBJ_obj2nid(contentInfo->type) != NID_pkcs7_data) {
226 PKG_LOGE("invalid pkcs7 signed data type");
227 UPDATER_LAST_WORD(-1, "invalid pkcs7 signed data type");
228 return -1;
229 }
230
231 if (GetASN1OctetStringData(contentInfo->d.data, digestBlock) != 0) {
232 PKG_LOGE("get pkcs7 contentInfo fail");
233 UPDATER_LAST_WORD(-1, "get pkcs7 contentInfo fail");
234 return -1;
235 }
236
237 return 0;
238 }
239
GetDigestFromContentInfo(std::vector<uint8_t> & digestBlock)240 int32_t Pkcs7SignedData::GetDigestFromContentInfo(std::vector<uint8_t> &digestBlock)
241 {
242 Updater::UPDATER_INIT_RECORD;
243 if (digestBlock.size() <= sizeof(uint32_t)) {
244 PKG_LOGE("invalid digest block info.");
245 UPDATER_LAST_WORD(-1, "invalid digest block info.");
246 return -1;
247 }
248
249 size_t offset = 0;
250 size_t algoId = static_cast<size_t>(ReadLE16(digestBlock.data() + offset));
251 offset += static_cast<size_t>(sizeof(uint16_t));
252 size_t digestLen = static_cast<size_t>(ReadLE16(digestBlock.data() + offset));
253 offset += static_cast<size_t>(sizeof(uint16_t));
254 if ((GetDigestLength(algoId) != digestLen) || ((digestLen + offset) != digestBlock.size())) {
255 PKG_LOGE("invalid digestLen[%zu] and digestBlock len[%zu]", digestLen, digestBlock.size());
256 UPDATER_LAST_WORD(-1, "invalid digestLen[%zu] and digestBlock len[%zu]", digestLen, digestBlock.size());
257 return -1;
258 }
259 digest_.assign(digestBlock.begin() + offset, digestBlock.end());
260 return 0;
261 }
262
GetInstance()263 Pkcs7SignedData &Pkcs7SignedData::GetInstance()
264 {
265 static Pkcs7SignedData checkPackagesInfo;
266 return checkPackagesInfo;
267 }
268
RegisterVerifyHelper(void)269 extern "C" __attribute__((constructor)) void RegisterVerifyHelper(void)
270 {
271 Pkcs7SignedData::GetInstance().RegisterVerifyHelper(std::make_unique<Pkcs7VerifyHelper>());
272 }
273
RegisterVerifyHelper(std::unique_ptr<VerifyHelper> ptr)274 void Pkcs7SignedData::RegisterVerifyHelper(std::unique_ptr<VerifyHelper> ptr)
275 {
276 helper_ = std::move(ptr);
277 }
278
~Pkcs7VerifyHelper()279 Pkcs7VerifyHelper::~Pkcs7VerifyHelper()
280 {
281 return;
282 }
283
GetDigestFromSubBlocks(std::vector<uint8_t> & digestBlock,SignatureInfo & signatureInfo,std::vector<uint8_t> & digest)284 int32_t Pkcs7VerifyHelper::GetDigestFromSubBlocks(
285 std::vector<uint8_t> &digestBlock, SignatureInfo &signatureInfo, std::vector<uint8_t> &digest)
286 {
287 PKG_LOGE("Pkcs7VerifyHelper in");
288 return -1;
289 }
290
GetDigest(std::vector<uint8_t> & digestBlock,SignatureInfo & signatureInfo,std::vector<uint8_t> & digest)291 int32_t Pkcs7SignedData::GetDigest(
292 std::vector<uint8_t> &digestBlock, SignatureInfo &signatureInfo, std::vector<uint8_t> &digest)
293 {
294 if (helper_ == nullptr) {
295 PKG_LOGE("helper_ null error");
296 return -1;
297 }
298 return helper_->GetDigestFromSubBlocks(digestBlock, signatureInfo, digest);
299 }
300
301 /*
302 * tools.ietf.org/html/rfc2315#section-9.2
303 * SignerInfo ::= SEQUENCE(0x30) {
304 * INTEGER(0x02) version Version,
305 * SEQUENCE(0x30) issuerAndSerialNumber IssuerAndSerialNumber,
306 * SEQUENCE(0x30) digestAlgorithm DigestAlgorithmIdentifier,
307 * CONTET_SPECIFIC[0](0xA0) authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL,
308 * SEQUENCE(0x30) digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
309 * OCTET_STRING(0x30) encryptedDigest EncryptedDigest,
310 * CONTET_SPECIFIC[1](0xA1) unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL }
311 */
ReadSig(const uint8_t * sourceData,const uint32_t sourceDataLen,std::vector<std::vector<uint8_t>> & sigs)312 int32_t Pkcs7SignedData::ReadSig(const uint8_t *sourceData, const uint32_t sourceDataLen,
313 std::vector<std::vector<uint8_t>> &sigs)
314 {
315 Updater::UPDATER_INIT_RECORD;
316 if (sourceData == nullptr || sourceDataLen == 0) {
317 UPDATER_LAST_WORD(PKCS7_INVALID_PARAM_ERR, "sourceData is nullptr or sourceDataLen is 0");
318 return PKCS7_INVALID_PARAM_ERR;
319 }
320 if (Init(sourceData, sourceDataLen) != 0) {
321 PKG_LOGE("init pkcs7 data fail");
322 UPDATER_LAST_WORD(PKCS7_INIT_ERR, "init pkcs7 data fail");
323 return PKCS7_INIT_ERR;
324 }
325 STACK_OF(PKCS7_SIGNER_INFO) *p7SignerInfos = PKCS7_get_signer_info(pkcs7_);
326 if (p7SignerInfos == nullptr) {
327 PKG_LOGE("get pkcs7 signers failed!");
328 UPDATER_LAST_WORD(PKCS7_INVALID_VALUE_ERR, "get pkcs7 signers failed!");
329 return PKCS7_INVALID_VALUE_ERR;
330 }
331 int signerInfoNum = sk_PKCS7_SIGNER_INFO_num(p7SignerInfos);
332 if (signerInfoNum <= 0) {
333 PKG_LOGE("invalid signers info num %d!", signerInfoNum);
334 UPDATER_LAST_WORD(PKCS7_INVALID_VALUE_ERR, "invalid signers info num %d!", signerInfoNum);
335 return PKCS7_INVALID_VALUE_ERR;
336 }
337 for (int i = 0; i < signerInfoNum; i++) {
338 PKCS7_SIGNER_INFO *p7SiTmp = sk_PKCS7_SIGNER_INFO_value(p7SignerInfos, i);
339 Pkcs7SignerInfo signer;
340 int32_t ret = SignerInfoParse(p7SiTmp, signer);
341 if (ret != 0) {
342 PKG_LOGE("SignerInfo Parse failed!");
343 continue;
344 }
345 sigs.push_back(signer.digestEncryptData);
346 }
347 if (sigs.size() == 0) {
348 PKG_LOGE("no valid sigs!");
349 UPDATER_LAST_WORD(PKCS7_HAS_NO_VALID_SIG_ERR, "no valid sigs!");
350 return PKCS7_HAS_NO_VALID_SIG_ERR;
351 }
352 return PKCS7_SUCCESS;
353 }
354
SignerInfosParse()355 int32_t Pkcs7SignedData::SignerInfosParse()
356 {
357 Updater::UPDATER_INIT_RECORD;
358 STACK_OF(PKCS7_SIGNER_INFO) *p7SignerInfos = PKCS7_get_signer_info(pkcs7_);
359 if (p7SignerInfos == nullptr) {
360 PKG_LOGE("get pkcs7 signers info failed!");
361 UPDATER_LAST_WORD(-1, "get pkcs7 signers info failed!");
362 return -1;
363 }
364
365 int signerInfoNum = sk_PKCS7_SIGNER_INFO_num(p7SignerInfos);
366 if (signerInfoNum <= 0) {
367 PKG_LOGE("invalid signers info num %d!", signerInfoNum);
368 UPDATER_LAST_WORD(-1, "invalid signers info num %d!", signerInfoNum);
369 return -1;
370 }
371
372 for (int i = 0; i < signerInfoNum; i++) {
373 PKCS7_SIGNER_INFO *p7SiTmp = sk_PKCS7_SIGNER_INFO_value(p7SignerInfos, i);
374 Pkcs7SignerInfo signer;
375 int32_t ret = SignerInfoParse(p7SiTmp, signer);
376 if (ret != 0) {
377 PKG_LOGE("SignerInfoParse failed!");
378 continue;
379 }
380 signerInfos_.push_back(std::move(signer));
381 }
382
383 return 0;
384 }
385
SignerInfoParse(PKCS7_SIGNER_INFO * p7SignerInfo,Pkcs7SignerInfo & signerInfo)386 int32_t Pkcs7SignedData::SignerInfoParse(PKCS7_SIGNER_INFO *p7SignerInfo, Pkcs7SignerInfo &signerInfo)
387 {
388 Updater::UPDATER_INIT_RECORD;
389 if (p7SignerInfo == nullptr) {
390 return -1;
391 }
392 PKCS7_ISSUER_AND_SERIAL *p7IssuerAndSerial = p7SignerInfo->issuer_and_serial;
393 if (p7IssuerAndSerial == nullptr) {
394 PKG_LOGE("signer cert info is nullptr!");
395 UPDATER_LAST_WORD(-1, "signer cert info is nullptr!");
396 return -1;
397 }
398 signerInfo.issuerName = p7IssuerAndSerial->issuer;
399 signerInfo.serialNumber = p7IssuerAndSerial->serial;
400
401 int32_t ret = GetX509AlgorithmNid(p7SignerInfo->digest_alg, signerInfo.digestNid);
402 if (ret != 0) {
403 PKG_LOGE("Parse signer info digest_alg failed!");
404 return ret;
405 }
406 ret = GetX509AlgorithmNid(p7SignerInfo->digest_enc_alg, signerInfo.digestEncryptNid);
407 if (ret != 0) {
408 PKG_LOGE("Parse signer info digest_enc_alg failed!");
409 return ret;
410 }
411
412 ret = GetASN1OctetStringData(p7SignerInfo->enc_digest, signerInfo.digestEncryptData);
413 if (ret != 0) {
414 PKG_LOGE("parse signer info enc_digest failed!");
415 return ret;
416 }
417
418 return 0;
419 }
420
Pkcs7SignleSignerVerify(const Pkcs7SignerInfo & signerInfo,const std::vector<uint8_t> & hash,const std::vector<uint8_t> & sig) const421 int32_t Pkcs7SignedData::Pkcs7SignleSignerVerify(const Pkcs7SignerInfo &signerInfo, const std::vector<uint8_t> &hash,
422 const std::vector<uint8_t> &sig) const
423 {
424 Updater::UPDATER_INIT_RECORD;
425 if (pkcs7_ == nullptr) {
426 UPDATER_LAST_WORD(-1, "pkcs7_ is nullptr");
427 return -1;
428 }
429 STACK_OF(X509) *certStack = pkcs7_->d.sign->cert;
430 if (certStack == nullptr) {
431 PKG_LOGE("certStack is empty!");
432 UPDATER_LAST_WORD(-1, "certStack is empty!");
433 return -1;
434 }
435
436 X509 *cert = X509_find_by_issuer_and_serial(certStack, signerInfo.issuerName, signerInfo.serialNumber);
437 if (cert == nullptr) {
438 PKG_LOGE("cert is empty");
439 UPDATER_LAST_WORD(-1, "cert is empty");
440 return -1;
441 }
442
443 if (CertVerify::GetInstance().CheckCertChain(certStack, cert) != 0) {
444 PKG_LOGE("public cert check fail");
445 UPDATER_LAST_WORD(-1, "public cert check fail");
446 return -1;
447 }
448
449 return VerifyDigest(cert, signerInfo, hash, sig);
450 }
451
VerifyDigest(X509 * cert,const Pkcs7SignerInfo & signer,const std::vector<uint8_t> & hash,const std::vector<uint8_t> & sig) const452 int32_t Pkcs7SignedData::VerifyDigest(X509 *cert, const Pkcs7SignerInfo &signer, const std::vector<uint8_t> &hash,
453 const std::vector<uint8_t> &sig) const
454 {
455 Updater::UPDATER_INIT_RECORD;
456 if (cert == nullptr) {
457 UPDATER_LAST_WORD(-1, "cert is null");
458 return -1;
459 }
460
461 EVP_PKEY *pubKey = X509_get_pubkey(cert);
462 if (pubKey == nullptr) {
463 PKG_LOGE("get pubkey from cert fail");
464 UPDATER_LAST_WORD(-1, "get pubkey from cert fail");
465 return -1;
466 }
467
468 auto ret = VerifyDigestByPubKey(pubKey, signer.digestNid, hash, sig);
469 EVP_PKEY_free(pubKey);
470 return ret;
471 }
472 } // namespace Hpackage
473