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