• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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