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 */
ReadSig(const uint8_t * sourceData,const uint32_t sourceDataLen,std::vector<std::vector<uint8_t>> & sigs)309 int32_t Pkcs7SignedData::ReadSig(const uint8_t *sourceData, const uint32_t sourceDataLen,
310 std::vector<std::vector<uint8_t>> &sigs)
311 {
312 if (sourceData == nullptr || sourceDataLen == 0) {
313 UPDATER_LAST_WORD(PKCS7_INVALID_PARAM_ERR);
314 return PKCS7_INVALID_PARAM_ERR;
315 }
316 if (Init(sourceData, sourceDataLen) != 0) {
317 PKG_LOGE("init pkcs7 data fail");
318 UPDATER_LAST_WORD(PKCS7_INIT_ERR);
319 return PKCS7_INIT_ERR;
320 }
321 STACK_OF(PKCS7_SIGNER_INFO) *p7SignerInfos = PKCS7_get_signer_info(pkcs7_);
322 if (p7SignerInfos == nullptr) {
323 PKG_LOGE("get pkcs7 signers failed!");
324 UPDATER_LAST_WORD(PKCS7_INVALID_VALUE_ERR);
325 return PKCS7_INVALID_VALUE_ERR;
326 }
327 int signerInfoNum = sk_PKCS7_SIGNER_INFO_num(p7SignerInfos);
328 if (signerInfoNum <= 0) {
329 PKG_LOGE("invalid signers info num %d!", signerInfoNum);
330 UPDATER_LAST_WORD(PKCS7_INVALID_VALUE_ERR);
331 return PKCS7_INVALID_VALUE_ERR;
332 }
333 for (int i = 0; i < signerInfoNum; i++) {
334 PKCS7_SIGNER_INFO *p7SiTmp = sk_PKCS7_SIGNER_INFO_value(p7SignerInfos, i);
335 Pkcs7SignerInfo signer;
336 int32_t ret = SignerInfoParse(p7SiTmp, signer);
337 if (ret != 0) {
338 PKG_LOGE("SignerInfo Parse failed!");
339 continue;
340 }
341 sigs.push_back(signer.digestEncryptData);
342 }
343 if (sigs.size() == 0) {
344 PKG_LOGE("no valid sigs!");
345 UPDATER_LAST_WORD(PKCS7_HAS_NO_VALID_SIG_ERR);
346 return PKCS7_HAS_NO_VALID_SIG_ERR;
347 }
348 return PKCS7_SUCCESS;
349 }
350
SignerInfosParse()351 int32_t Pkcs7SignedData::SignerInfosParse()
352 {
353 Updater::UPDATER_INIT_RECORD;
354 STACK_OF(PKCS7_SIGNER_INFO) *p7SignerInfos = PKCS7_get_signer_info(pkcs7_);
355 if (p7SignerInfos == nullptr) {
356 PKG_LOGE("get pkcs7 signers info failed!");
357 UPDATER_LAST_WORD(-1);
358 return -1;
359 }
360
361 int signerInfoNum = sk_PKCS7_SIGNER_INFO_num(p7SignerInfos);
362 if (signerInfoNum <= 0) {
363 PKG_LOGE("invalid signers info num %d!", signerInfoNum);
364 UPDATER_LAST_WORD(-1);
365 return -1;
366 }
367
368 for (int i = 0; i < signerInfoNum; i++) {
369 PKCS7_SIGNER_INFO *p7SiTmp = sk_PKCS7_SIGNER_INFO_value(p7SignerInfos, i);
370 Pkcs7SignerInfo signer;
371 int32_t ret = SignerInfoParse(p7SiTmp, signer);
372 if (ret != 0) {
373 PKG_LOGE("SignerInfoParse failed!");
374 continue;
375 }
376 signerInfos_.push_back(std::move(signer));
377 }
378
379 return 0;
380 }
381
SignerInfoParse(PKCS7_SIGNER_INFO * p7SignerInfo,Pkcs7SignerInfo & signerInfo)382 int32_t Pkcs7SignedData::SignerInfoParse(PKCS7_SIGNER_INFO *p7SignerInfo, Pkcs7SignerInfo &signerInfo)
383 {
384 if (p7SignerInfo == nullptr) {
385 return -1;
386 }
387 PKCS7_ISSUER_AND_SERIAL *p7IssuerAndSerial = p7SignerInfo->issuer_and_serial;
388 if (p7IssuerAndSerial == nullptr) {
389 PKG_LOGE("signer cert info is nullptr!");
390 UPDATER_LAST_WORD(-1);
391 return -1;
392 }
393 signerInfo.issuerName = p7IssuerAndSerial->issuer;
394 signerInfo.serialNumber = p7IssuerAndSerial->serial;
395
396 int32_t ret = GetX509AlgorithmNid(p7SignerInfo->digest_alg, signerInfo.digestNid);
397 if (ret != 0) {
398 PKG_LOGE("Parse signer info digest_alg failed!");
399 return ret;
400 }
401 ret = GetX509AlgorithmNid(p7SignerInfo->digest_enc_alg, signerInfo.digestEncryptNid);
402 if (ret != 0) {
403 PKG_LOGE("Parse signer info digest_enc_alg failed!");
404 return ret;
405 }
406
407 ret = GetASN1OctetStringData(p7SignerInfo->enc_digest, signerInfo.digestEncryptData);
408 if (ret != 0) {
409 PKG_LOGE("parse signer info enc_digest failed!");
410 return ret;
411 }
412
413 return 0;
414 }
415
Pkcs7SignleSignerVerify(const Pkcs7SignerInfo & signerInfo,const std::vector<uint8_t> & hash,const std::vector<uint8_t> & sig) const416 int32_t Pkcs7SignedData::Pkcs7SignleSignerVerify(const Pkcs7SignerInfo &signerInfo, const std::vector<uint8_t> &hash,
417 const std::vector<uint8_t> &sig) const
418 {
419 if (pkcs7_ == nullptr) {
420 UPDATER_LAST_WORD(-1);
421 return -1;
422 }
423 STACK_OF(X509) *certStack = pkcs7_->d.sign->cert;
424 if (certStack == nullptr) {
425 PKG_LOGE("certStack is empty!");
426 UPDATER_LAST_WORD(-1);
427 return -1;
428 }
429
430 X509 *cert = X509_find_by_issuer_and_serial(certStack, signerInfo.issuerName, signerInfo.serialNumber);
431 if (cert == nullptr) {
432 PKG_LOGE("cert is empty");
433 UPDATER_LAST_WORD(-1);
434 return -1;
435 }
436
437 if (CertVerify::GetInstance().CheckCertChain(certStack, cert) != 0) {
438 PKG_LOGE("public cert check fail");
439 UPDATER_LAST_WORD(-1);
440 return -1;
441 }
442
443 return VerifyDigest(cert, signerInfo, hash, sig);
444 }
445
VerifyDigest(X509 * cert,const Pkcs7SignerInfo & signer,const std::vector<uint8_t> & hash,const std::vector<uint8_t> & sig) const446 int32_t Pkcs7SignedData::VerifyDigest(X509 *cert, const Pkcs7SignerInfo &signer, const std::vector<uint8_t> &hash,
447 const std::vector<uint8_t> &sig) const
448 {
449 Updater::UPDATER_INIT_RECORD;
450 if (cert == nullptr) {
451 UPDATER_LAST_WORD(-1);
452 return -1;
453 }
454
455 EVP_PKEY *pubKey = X509_get_pubkey(cert);
456 if (pubKey == nullptr) {
457 PKG_LOGE("get pubkey from cert fail");
458 UPDATER_LAST_WORD(-1);
459 return -1;
460 }
461
462 auto ret = VerifyDigestByPubKey(pubKey, signer.digestNid, hash, sig);
463 EVP_PKEY_free(pubKey);
464 return ret;
465 }
466 } // namespace Hpackage
467