• 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         return ret;
60     }
61 
62     ret = Verify();
63     if (ret != 0) {
64         PKG_LOGE("verify pkcs7 data fail");
65         return ret;
66     }
67     hash.assign(digest_.begin(), digest_.end());
68 
69     return 0;
70 }
71 
ParsePkcs7Data(const uint8_t * srcData,const size_t dataLen)72 int32_t Pkcs7SignedData::ParsePkcs7Data(const uint8_t *srcData, const size_t dataLen)
73 {
74     if (srcData == nullptr || dataLen == 0) {
75         return -1;
76     }
77     if (Init(srcData, dataLen) != 0) {
78         PKG_LOGE("init pkcs7 data fail");
79         return -1;
80     }
81 
82     return DoParse();
83 }
84 
Verify() const85 int32_t Pkcs7SignedData::Verify() const
86 {
87     if (digest_.empty()) {
88         return -1;
89     }
90     int32_t ret = -1;
91     for (auto &signerInfo : signerInfos_) {
92         ret = Pkcs7SignleSignerVerify(signerInfo);
93         if (ret == 0) {
94             PKG_LOGI("p7sourceData check success");
95             break;
96         }
97         PKG_LOGI("p7sourceData continue");
98     }
99 
100     return ret;
101 }
102 
Init(const uint8_t * sourceData,const uint32_t sourceDataLen)103 int32_t Pkcs7SignedData::Init(const uint8_t *sourceData, const uint32_t sourceDataLen)
104 {
105     BIO *p7Bio = BIO_new(BIO_s_mem());
106     if (p7Bio == nullptr) {
107         PKG_LOGE("BIO_new error!");
108         return -1;
109     }
110     if (static_cast<uint32_t>(BIO_write(p7Bio, sourceData, sourceDataLen)) != sourceDataLen) {
111         PKG_LOGE("BIO_write error!");
112         BIO_free(p7Bio);
113         return -1;
114     }
115 
116     pkcs7_ = d2i_PKCS7_bio(p7Bio, nullptr);
117     if (pkcs7_ == nullptr) {
118         PKG_LOGE("d2i_PKCS7_bio failed!");
119         BIO_free(p7Bio);
120         return -1;
121     }
122 
123     int32_t type = OBJ_obj2nid(pkcs7_->type);
124     if (type != NID_pkcs7_signed) {
125         PKG_LOGE("Invalid pkcs7 data type %d", type);
126         BIO_free(p7Bio);
127         return -1;
128     }
129 
130     BIO_free(p7Bio);
131     return 0;
132 }
133 
134 /*
135  * tools.ietf.org/html/rfc2315#section-9.1
136  * SignedData ::= SEQUENCE(0x30) {
137  *     INTEGER(0x02)            version Version,
138  *     SET(0x31)                digestAlgorithms DigestAlgorithmIdentifiers,
139  *     SEQUENCE(0x30)           contentInfo ContentInfo,
140  *     CONTET_SPECIFIC[0](0xA0) certificates [0] IMPLICIT ExtendedCertificatesAndCertificates OPTIONAL,
141  *     CONTET_SPECIFIC[1](0xA1) crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
142  *     SET(0x31)                signerInfos SignerInfos }
143  */
DoParse()144 int32_t Pkcs7SignedData::DoParse()
145 {
146     std::vector<uint8_t> contentInfo;
147     int32_t ret = ParseContentInfo(contentInfo);
148     if (ret != 0) {
149         PKG_LOGE("parse pkcs7 contentInfo fail");
150         return -1;
151     }
152 
153     ret = GetDigestFromContentInfo(contentInfo);
154     if (ret != 0) {
155         PKG_LOGE("invalid pkcs7 contentInfo fail");
156         return -1;
157     }
158 
159     return SignerInfosParse();
160 }
161 
162 /*
163  * tools.ietf.org/html/rfc2315#section-7
164  * ContentInfo ::= SEQUENCE(0x30) {
165  *     OBJECT_IDENTIFIER(0x06)  contentType ContentType,
166  *     CONTET_SPECIFIC[0](0xA0) content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
167  *
168  * tools.ietf.org/html/rfc2315#section-8
169  *     Data ::= OCTET STRING
170  */
ParseContentInfo(std::vector<uint8_t> & digestBlock) const171 int32_t Pkcs7SignedData::ParseContentInfo(std::vector<uint8_t> &digestBlock) const
172 {
173     PKCS7_SIGNED *signData = pkcs7_->d.sign;
174     if (signData == nullptr) {
175         PKG_LOGE("invalid pkcs7 signed data!");
176         return -1;
177     }
178 
179     PKCS7 *contentInfo = signData->contents;
180     if (contentInfo == nullptr) {
181         PKG_LOGE("pkcs7 content is nullptr!");
182         return -1;
183     }
184     if (OBJ_obj2nid(contentInfo->type) != NID_pkcs7_data) {
185         PKG_LOGE("invalid pkcs7 signed data type");
186         return -1;
187     }
188 
189     if (GetASN1OctetStringData(contentInfo->d.data, digestBlock) != 0) {
190         PKG_LOGE("get pkcs7 contentInfo fail");
191         return -1;
192     }
193 
194     return 0;
195 }
196 
GetDigestFromContentInfo(std::vector<uint8_t> & digestBlock)197 int32_t Pkcs7SignedData::GetDigestFromContentInfo(std::vector<uint8_t> &digestBlock)
198 {
199     if (digestBlock.size() <= sizeof(uint32_t)) {
200         PKG_LOGE("invalid digest block info.");
201         return -1;
202     }
203 
204     size_t offset = 0;
205     size_t algoId = static_cast<size_t>(ReadLE16(digestBlock.data() + offset));
206     offset += static_cast<size_t>(sizeof(uint16_t));
207     size_t digestLen = static_cast<size_t>(ReadLE16(digestBlock.data() + offset));
208     offset += static_cast<size_t>(sizeof(uint16_t));
209     if ((GetDigestLength(algoId) != digestLen) || ((digestLen + offset) != digestBlock.size())) {
210         PKG_LOGE("invalid digestLen[%zu] and digestBlock len[%zu]", digestLen, digestBlock.size());
211         return -1;
212     }
213     digest_.assign(digestBlock.begin() + offset, digestBlock.end());
214 
215     return 0;
216 }
217 
218 /*
219  * tools.ietf.org/html/rfc2315#section-9.2
220  * SignerInfo ::= SEQUENCE(0x30) {
221  *     INTEGER(0x02)             version Version,
222  *     SEQUENCE(0x30)            issuerAndSerialNumber IssuerAndSerialNumber,
223  *     SEQUENCE(0x30)            digestAlgorithm DigestAlgorithmIdentifier,
224  *     CONTET_SPECIFIC[0](0xA0)  authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL,
225  *     SEQUENCE(0x30)            digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
226  *     OCTET_STRING(0x30)        encryptedDigest EncryptedDigest,
227  *     CONTET_SPECIFIC[1](0xA1)  unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL }
228  */
SignerInfosParse()229 int32_t Pkcs7SignedData::SignerInfosParse()
230 {
231     STACK_OF(PKCS7_SIGNER_INFO) *p7SignerInfos = PKCS7_get_signer_info(pkcs7_);
232     if (p7SignerInfos == nullptr) {
233         PKG_LOGE("get pkcs7 signers info failed!");
234         return -1;
235     }
236 
237     int signerInfoNum = sk_PKCS7_SIGNER_INFO_num(p7SignerInfos);
238     if (signerInfoNum <= 0) {
239         PKG_LOGE("invalid signers info num %d!", signerInfoNum);
240         return -1;
241     }
242 
243     for (int i = 0; i < signerInfoNum; i++) {
244         PKCS7_SIGNER_INFO *p7SiTmp = sk_PKCS7_SIGNER_INFO_value(p7SignerInfos, i);
245         Pkcs7SignerInfo signer;
246         int32_t ret = SignerInfoParse(p7SiTmp, signer);
247         if (ret != 0) {
248             PKG_LOGE("SignerInfoParse failed!");
249             continue;
250         }
251         signerInfos_.push_back(std::move(signer));
252     }
253 
254     return 0;
255 }
256 
SignerInfoParse(PKCS7_SIGNER_INFO * p7SignerInfo,Pkcs7SignerInfo & signerInfo)257 int32_t Pkcs7SignedData::SignerInfoParse(PKCS7_SIGNER_INFO *p7SignerInfo, Pkcs7SignerInfo &signerInfo)
258 {
259     if (p7SignerInfo == nullptr) {
260         return -1;
261     }
262     PKCS7_ISSUER_AND_SERIAL *p7IssuerAndSerial = p7SignerInfo->issuer_and_serial;
263     if (p7IssuerAndSerial == nullptr) {
264         PKG_LOGE("signer cert info is nullptr!");
265         UPDATER_LAST_WORD(-1);
266         return -1;
267     }
268     signerInfo.issuerName = p7IssuerAndSerial->issuer;
269     signerInfo.serialNumber = p7IssuerAndSerial->serial;
270 
271     int32_t ret = GetX509AlgorithmNid(p7SignerInfo->digest_alg, signerInfo.digestNid);
272     if (ret != 0) {
273         PKG_LOGE("Parse signer info digest_alg failed!");
274         return ret;
275     }
276     ret = GetX509AlgorithmNid(p7SignerInfo->digest_enc_alg, signerInfo.digestEncryptNid);
277     if (ret != 0) {
278         PKG_LOGE("Parse signer info digest_enc_alg failed!");
279         return ret;
280     }
281 
282     ret = GetASN1OctetStringData(p7SignerInfo->enc_digest, signerInfo.digestEncryptData);
283     if (ret != 0) {
284         PKG_LOGE("parse signer info enc_digest failed!");
285         return ret;
286     }
287 
288     return 0;
289 }
290 
Pkcs7SignleSignerVerify(const Pkcs7SignerInfo & signerInfo) const291 int32_t Pkcs7SignedData::Pkcs7SignleSignerVerify(const Pkcs7SignerInfo &signerInfo) const
292 {
293     if (pkcs7_ == nullptr) {
294         UPDATER_LAST_WORD(-1);
295         return -1;
296     }
297     STACK_OF(X509) *certStack = pkcs7_->d.sign->cert;
298     if (certStack == nullptr) {
299         PKG_LOGE("certStack is empty!");
300         return -1;
301     }
302 
303     X509 *cert = X509_find_by_issuer_and_serial(certStack, signerInfo.issuerName, signerInfo.serialNumber);
304     if (cert == nullptr) {
305         PKG_LOGE("cert is empty");
306         return -1;
307     }
308 
309     if (CertVerify::GetInstance().CheckCertChain(certStack, cert) != 0) {
310         PKG_LOGE("public cert check fail");
311         return -1;
312     }
313 
314     return VerifyDigest(cert, signerInfo);
315 }
316 
VerifyDigest(X509 * cert,const Pkcs7SignerInfo & signer) const317 int32_t Pkcs7SignedData::VerifyDigest(X509 *cert, const Pkcs7SignerInfo &signer) const
318 {
319     if (cert == nullptr) {
320         return -1;
321     }
322 
323     size_t digestLen = GetDigestLength(signer.digestNid);
324     if (digestLen == 0 || digest_.size() != digestLen) {
325         PKG_LOGE("invalid digest length %zu", digestLen);
326         UPDATER_LAST_WORD(-1, digestLen);
327         return -1;
328     }
329 
330     EVP_PKEY *pubKey = X509_get_pubkey(cert);
331     if (pubKey == nullptr) {
332         PKG_LOGE("get pubkey from cert fail");
333         UPDATER_LAST_WORD(-1);
334         return -1;
335     }
336 
337     return VerifyDigestByPubKey(pubKey, signer.digestNid, digest_, signer.digestEncryptData);
338 }
339 } // namespace Hpackage
340