• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024-2024 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 "signature_tools_log.h"
17 #include "signature_tools_errno.h"
18 #include "verify_hap_openssl_utils.h"
19 #include "signer.h"
20 #include "securec.h"
21 #include "constant.h"
22 #include "pkcs7_data.h"
23 
24 namespace OHOS {
25 namespace SignatureTools {
26 
27 static constexpr int BUFFER_SIZE = 4096;
28 
PKCS7AddAttribute(PKCS7 * p7,const std::vector<PKCS7Attr> & attrs)29 static int PKCS7AddAttribute(PKCS7* p7, const std::vector<PKCS7Attr>& attrs)
30 {
31     STACK_OF(PKCS7_SIGNER_INFO)* signerInfos = PKCS7_get_signer_info(p7);
32     if (signerInfos == NULL || sk_PKCS7_SIGNER_INFO_num(signerInfos) != 1) {
33         PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR,
34                             "signer info count not equal 1,pkcs7 add customize attribute failed");
35         return INVALIDPARAM_ERROR;
36     }
37     PKCS7_SIGNER_INFO* signerInfo = sk_PKCS7_SIGNER_INFO_value(signerInfos, 0);
38     for (PKCS7Attr attr : attrs) {
39         if (PKCS7_add_signed_attribute(signerInfo, attr.nid, attr.atrtype, attr.value) != 1) {
40             if (attr.atrtype == V_ASN1_UTF8STRING)
41                 ASN1_STRING_free(reinterpret_cast<ASN1_STRING*>(attr.value));
42             PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR,
43                                 "pkcs7 add customize attribute failed");
44             return RET_FAILED;
45         }
46     }
47     return RET_OK;
48 }
49 
I2dPkcs7Str(PKCS7 * p7,std::string & ret)50 static int I2dPkcs7Str(PKCS7* p7, std::string& ret)
51 {
52     /* raw data exported in pkcs7 */
53     unsigned char* out = NULL;
54     int outSize = 0;
55     /* Deserialize to obtain the p7b byte stream */
56     outSize = i2d_PKCS7(p7, &out);
57     if (out == NULL || outSize <= 0) {
58         PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR,
59                             "pkcs7 is invalid");
60         return INVALIDPARAM_ERROR;
61     }
62     ret.clear();
63     ret.resize(outSize);
64     std::copy(out, out + outSize, &ret[0]);
65     OPENSSL_free(out);
66     return RET_OK;
67 }
68 
SetSignerInfoSignAlgor(PKCS7_SIGNER_INFO * info)69 static int SetSignerInfoSignAlgor(PKCS7_SIGNER_INFO* info)
70 {
71     int signNid = 0;
72     int hashNid = 0;
73     X509_ALGOR* dig;
74     X509_ALGOR* sig;
75     PKCS7_SIGNER_INFO_get0_algs(info, NULL, &dig, &sig);
76     if (dig == NULL || dig->algorithm == NULL ||
77         (hashNid = OBJ_obj2nid(dig->algorithm)) == NID_undef ||
78         !OBJ_find_sigid_by_algs(&signNid, hashNid, NID_X9_62_id_ecPublicKey) ||
79         X509_ALGOR_set0(sig, OBJ_nid2obj(signNid), V_ASN1_UNDEF, 0) != 1) {
80         return 0;
81     }
82     return 1;
83 }
84 
VerifySignature(PKCS7 * pkcs7,BIO * p7bio)85 static int VerifySignature(PKCS7* pkcs7, BIO* p7bio)
86 {
87     /* signature information */
88     STACK_OF(PKCS7_SIGNER_INFO)* skSignerInfo = NULL;
89     /* signature count */
90     int signerCount = 0;
91     /* verify signature value */
92     skSignerInfo = PKCS7_get_signer_info(pkcs7);
93     signerCount = sk_PKCS7_SIGNER_INFO_num(skSignerInfo);
94     for (int i = 0; i < signerCount; i++) {
95         PKCS7_SIGNER_INFO* signerInfo = sk_PKCS7_SIGNER_INFO_value(skSignerInfo, i);
96         X509* sigCert = PKCS7_cert_from_signer_info(pkcs7, signerInfo);
97         if (PKCS7_signatureVerify(p7bio, pkcs7, signerInfo, sigCert) != 1) {
98             PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, "signature value verify failed");
99             return VERIFY_ERROR;
100         }
101     }
102     return RET_OK;
103 }
104 
PKCS7Data(int flags)105 PKCS7Data::PKCS7Data(int flags) : m_p7(nullptr), m_flags(flags)
106 {
107 }
108 
~PKCS7Data()109 PKCS7Data::~PKCS7Data()
110 {
111     PKCS7_free(m_p7);
112     m_p7 = NULL;
113 }
114 
Sign(const std::string & content,const std::shared_ptr<Signer> & signer,const std::string & sigAlg,std::string & ret,std::vector<PKCS7Attr> attrs)115 int PKCS7Data::Sign(const std::string& content, const std::shared_ptr<Signer>& signer,
116                     const std::string& sigAlg, std::string& ret, std::vector<PKCS7Attr> attrs)
117 {
118     int result = RET_OK;
119     if ((result = InitPkcs7(content, signer, sigAlg, attrs)) < 0) {
120         goto err;
121     }
122 
123     /* serialization */
124     if ((result = I2dPkcs7Str(m_p7, ret)) < 0) {
125         goto err;
126     }
127     /* release resources */
128 err:
129     if (result < 0) {
130         SIGNATURE_TOOLS_LOGE("sign failed");
131     }
132     return result;
133 }
134 
Parse(const std::string & p7bBytes)135 int PKCS7Data::Parse(const std::string& p7bBytes)
136 {
137     const unsigned char* data = reinterpret_cast<const unsigned char*>(&p7bBytes[0]);
138     return Parse(&data, static_cast<long>(p7bBytes.size()));
139 }
Parse(const std::vector<int8_t> & p7bBytes)140 int PKCS7Data::Parse(const std::vector<int8_t>& p7bBytes)
141 {
142     const unsigned char* data = reinterpret_cast<const unsigned char*>(&p7bBytes[0]);
143     return Parse(&data, static_cast<long>(p7bBytes.size()));
144 }
Parse(const unsigned char ** in,long len)145 int PKCS7Data::Parse(const unsigned char** in, long len)
146 {
147     /* If p7 has been initialized, it will be released */
148     if (m_p7) {
149         PKCS7_free(m_p7);
150         m_p7 = NULL;
151     }
152     /* Deserialize */
153     m_p7 = d2i_PKCS7(NULL, in, len);
154     if (m_p7 == NULL) {
155         PrintErrorNumberMsg("PARSE_ERROR", PARSE_ERROR, "invalid p7b data, parse failed");
156         return PARSE_ERROR;
157     }
158     return RET_OK;
159 }
160 
Verify(const std::string & content) const161 int PKCS7Data::Verify(const std::string& content) const
162 {
163     if (m_p7 == nullptr || !PKCS7_type_is_signed(m_p7) || m_p7->d.sign == nullptr) {
164         PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, "pkcs7 block is invalid.");
165         return VERIFY_ERROR;
166     }
167 
168     if (VerifySign(content) < 0) {
169         PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, "signature verify failed");
170         return VERIFY_ERROR;
171     }
172 
173     if (VerifyCertChain() < 0) {
174         SIGNATURE_TOOLS_LOGE("Cert Chain verify failed.");
175         PrintCertChainSub(m_p7->d.sign->cert);
176         return VERIFY_ERROR;
177     }
178     return RET_OK;
179 }
180 
GetContent(std::string & originalRawData) const181 int PKCS7Data::GetContent(std::string& originalRawData) const
182 {
183     BIO* oriBio = PKCS7_dataDecode(m_p7, NULL, NULL, NULL);
184     if (oriBio == NULL) {
185         PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR, "pkcs7 get content data failed!");
186         return INVALIDPARAM_ERROR;
187     }
188     char buf[BUFFER_SIZE]{0};
189     size_t readBytes = 0;
190     while (BIO_read_ex(oriBio, buf, sizeof(buf), &readBytes) == 1) {
191         originalRawData.append(buf, readBytes);
192     }
193     BIO_free_all(oriBio);
194     return RET_OK;
195 }
196 
PKCS7AddCrls(PKCS7 * p7,STACK_OF (X509_CRL)* crls)197 static void PKCS7AddCrls(PKCS7* p7, STACK_OF(X509_CRL)* crls)
198 {
199     if (crls == nullptr) {
200         return;
201     }
202 
203     for (int i = 0; i < sk_X509_CRL_num(crls); i++) {
204         PKCS7_add_crl(p7, sk_X509_CRL_value(crls, i));
205     }
206 
207     sk_X509_CRL_free(crls);
208 }
209 
InitPkcs7(const std::string & content,const std::shared_ptr<Signer> & signer,const std::string & sigAlg,std::vector<PKCS7Attr> attrs)210 int PKCS7Data::InitPkcs7(const std::string& content, const std::shared_ptr<Signer>& signer,
211                          const std::string& sigAlg, std::vector<PKCS7Attr> attrs)
212 {
213     /* hash algorithm */
214     const EVP_MD* md = NULL;
215     /* entity certificate */
216     X509* cert = NULL;
217     int result = RET_OK;
218     if (signer == NULL) {
219         PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR, "signer is NULL , sign failed");
220         return INVALIDPARAM_ERROR;
221     }
222     m_signer = signer;
223     m_sigAlg = sigAlg;
224     STACK_OF(X509)* certs = signer->GetCertificates();
225     if (certs == nullptr) {
226         PrintErrorNumberMsg("CERTIFICATE_ERROR", CERTIFICATE_ERROR, "certs is NULL, sign failed.");
227         return CERTIFICATE_ERROR;
228     }
229 
230     if (sigAlg == SIGN_ALG_SHA384) {
231         md = EVP_sha384();
232     } else if (sigAlg == SIGN_ALG_SHA256) {
233         md = EVP_sha256();
234     } else {
235         PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR,
236                             sigAlg + "is invalid sigAlg, please use SHA256withECDSA/SHA384withECDSA, sign failed");
237         result = INVALIDPARAM_ERROR;
238         goto err;
239     }
240     /* Extract the entity certificate from the certificate chain */
241     cert = sk_X509_delete(certs, 0);
242     m_p7 = Pkcs7Sign(cert, certs, md, content, m_flags, attrs);
243     if (m_p7 == NULL) {
244         PrintErrorNumberMsg("INVALIDPARAM_ERROR", SIGN_ERROR, "p7 is NULL, pkcs7 sign failed");
245         result = SIGN_ERROR;
246         goto err;
247     }
248     PKCS7AddCrls(m_p7, signer->GetCrls());
249 
250 err:
251     sk_X509_pop_free(certs, X509_free);
252     X509_free(cert);
253     return result;
254 }
255 
PrintCertChainSub(const STACK_OF (X509)* certs)256 void PKCS7Data::PrintCertChainSub(const STACK_OF(X509)* certs)
257 {
258     if (certs == NULL)
259         return;
260     SIGNATURE_TOOLS_LOGI("certChainSubject:");
261     int certNum = sk_X509_num(certs);
262     SIGNATURE_TOOLS_LOGI("certNum%s", std::to_string(certNum).c_str());
263     for (int i = 0; i < certNum; i++) {
264         SIGNATURE_TOOLS_LOGI("certificate %s", std::to_string(i).c_str());
265         std::string sub;
266         VerifyCertOpensslUtils::GetSubjectFromX509(sk_X509_value(certs, i), sub);
267         SIGNATURE_TOOLS_LOGI("%s", sub.c_str());
268     }
269 }
270 
GetASN1Time(const ASN1_TIME * tm)271 std::string PKCS7Data::GetASN1Time(const ASN1_TIME* tm)
272 {
273     if (tm == NULL) {
274         return "";
275     }
276     /* Convert the ASN1_TIME structure to a standard tm structure. */
277     struct tm time;
278     ASN1_TIME_to_tm(tm, &time);
279     /* Convert to local time(considering the time zone) */
280     time_t t = mktime(&time);
281     if (t < 0) {
282         return "";
283     }
284     struct tm* localTime = localtime(&t);
285     if (localTime == nullptr) {
286         return "";
287     }
288     /* Print local time */
289     char buf[128] = {0};
290     if (sprintf_s(buf, sizeof(buf), "%04d-%02d-%02d %02d:%02d:%02d",
291                   localTime->tm_year + YEAR1900, localTime->tm_mon + 1, localTime->tm_mday,
292                   localTime->tm_hour, localTime->tm_min, localTime->tm_sec) == -1) {
293         return "";
294     }
295     return std::string(buf, strlen(buf));
296 }
297 
X509NameCompare(const X509 * cert,const X509 * issuerCert)298 bool PKCS7Data::X509NameCompare(const X509* cert, const X509* issuerCert)
299 {
300     if (cert == nullptr || issuerCert == nullptr) {
301         PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR,
302                             "input cert is NULL");
303         return false;
304     }
305     X509_NAME* aName = X509_get_issuer_name(cert);
306     X509_NAME* bName = X509_get_subject_name(issuerCert);
307     if (X509_NAME_cmp(aName, bName) != 0) {
308         PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR,
309                             "cert issuer name is not equal to its issuer\'s  name");
310         return false;
311     }
312     return true;
313 }
314 
CheckSignTimeInValidPeriod(const ASN1_TYPE * signTime,const ASN1_TIME * notBefore,const ASN1_TIME * notAfter)315 int PKCS7Data::CheckSignTimeInValidPeriod(const ASN1_TYPE* signTime,
316                                           const ASN1_TIME* notBefore, const ASN1_TIME* notAfter)
317 {
318     if (notBefore == nullptr || notBefore->data == nullptr || notAfter == nullptr || notAfter->data == nullptr) {
319         PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR,
320                             "invalid period, check signtime failed please use valid period to to check signtime");
321         return INVALIDPARAM_ERROR;
322     }
323     if (signTime == nullptr || signTime->value.asn1_string == nullptr ||
324         signTime->value.asn1_string->data == nullptr) {
325         PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR, "signtime is NULL");
326         return INVALIDPARAM_ERROR;
327     }
328     ASN1_TIME* tm = ASN1_TIME_new();
329     ASN1_TIME_set_string(tm, (reinterpret_cast<const char*>(signTime->value.asn1_string->data)));
330     if (ASN1_TIME_compare(notBefore, signTime->value.asn1_string) > 0) {
331         PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR,
332             "The system time of the device running sign tool is inaccurate! The signTime is " + GetASN1Time(tm) +
333             " and earlier than notBefore which is " + GetASN1Time(notBefore));
334         ASN1_TIME_free(tm);
335         return VERIFY_ERROR;
336     }
337     if (ASN1_TIME_compare(notAfter, signTime->value.asn1_string) < 0) {
338         PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR,
339             "The certificate has expired! NotAfter: " + GetASN1Time(notAfter));
340         ASN1_TIME_free(tm);
341         return VERIFY_ERROR;
342     }
343     ASN1_TIME_free(tm);
344     return RET_OK;
345 }
346 
FindSubCertThenEraseItFromSets(X509 * cert,std::unordered_set<X509 * > & x509Sets)347 static X509* FindSubCertThenEraseItFromSets(X509* cert, std::unordered_set<X509*>& x509Sets)
348 {
349     X509* ret = NULL;
350     for (X509* c : x509Sets) {
351         X509_NAME* name1 = X509_get_subject_name(cert);
352         X509_NAME* name2 = X509_get_issuer_name(c);
353         if (X509_NAME_cmp(name1, name2) == 0) {
354             x509Sets.erase(c);
355             ret = c;
356             break;
357         }
358     }
359     return ret;
360 }
361 
SortX509Stack(STACK_OF (X509)* certs)362 int PKCS7Data::SortX509Stack(STACK_OF(X509)* certs)
363 {
364     std::unordered_set<X509*> x509Sets;
365     std::list<X509*>certChain;
366     X509* tmp = NULL;
367     int result = RET_FAILED;
368 
369     if (sk_X509_num(certs) < MIN_CERTS_NUM) {
370         PrintErrorNumberMsg("CERTIFICATE_ERROR", CERTIFICATE_ERROR, "cert of certchain count less than two!");
371         goto err;
372     }
373     for (int i = 0; i < sk_X509_num(certs); i++) {
374         x509Sets.insert(sk_X509_value(certs, i));
375     }
376     if (sk_X509_num(certs) != static_cast<int>(x509Sets.size())) {
377         PrintErrorNumberMsg("CERTIFICATE_ERROR", CERTIFICATE_ERROR, "sort x509 certchain failed!");
378         goto err;
379     }
380     for (X509* cert : x509Sets) {
381         if (X509_name_cmp(X509_get_subject_name(cert), X509_get_issuer_name(cert)) == 0) {
382             tmp = cert;
383             x509Sets.erase(cert);
384             break;
385         }
386     }
387     if (tmp == NULL) {
388         PrintErrorNumberMsg("CERTIFICATE_ERROR", CERTIFICATE_ERROR,
389                             "can't find root cert from certchain ,sort x509 certchain failed!");
390         goto err;
391     }
392     certChain.push_front(tmp);
393     while ((tmp = FindSubCertThenEraseItFromSets(tmp, x509Sets))) {
394         certChain.push_front(tmp);
395     }
396     if (x509Sets.size() != 0) {
397         PrintErrorNumberMsg("CERTIFICATE_ERROR", CERTIFICATE_ERROR,
398                             "certchain contain invalid cert, sort x509 certchain failed!");
399         goto err;
400     }
401     while (sk_X509_num(certs)) {
402         sk_X509_pop(certs);
403     }
404     for (X509* cert : certChain) {
405         sk_X509_push(certs, cert);
406     }
407     result = RET_OK;
408 err:
409     return result;
410 }
411 
VerifySign(const std::string & content) const412 int PKCS7Data::VerifySign(const std::string& content)const
413 {
414     BIO* inBio = NULL;
415     if ((m_flags & PKCS7_DETACHED)) {
416         inBio = BIO_new_mem_buf(reinterpret_cast<const void*>(content.c_str()),
417                                 static_cast<int>(content.size()));
418         if (inBio == NULL) {
419             PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR,
420                                 "new mem buf error!,pkcs7 verify signature failed");
421             return VERIFY_ERROR;
422         }
423     }
424     if (PKCS7_verify(m_p7, NULL, NULL, inBio, NULL, m_flags) != 1) {
425         PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, "pkcs7 verify signature failed");
426         BIO_free(inBio);
427         return VERIFY_ERROR;
428     }
429     BIO_free(inBio);
430     return RET_OK;
431 }
432 
VerifyCertChain() const433 int PKCS7Data::VerifyCertChain() const
434 {
435     /* Validate the certificate chain */
436     STACK_OF(PKCS7_SIGNER_INFO)* skSignerInfo = PKCS7_get_signer_info(m_p7);
437     int signerCount = sk_PKCS7_SIGNER_INFO_num(skSignerInfo);
438     STACK_OF(X509)* certs = m_p7->d.sign->cert;
439 
440     for (int i = 0; i < signerCount; i++) {
441         PKCS7_SIGNER_INFO* signerInfo = sk_PKCS7_SIGNER_INFO_value(skSignerInfo, i);
442         int result = VerifySignerInfoCertChain(m_p7, signerInfo, certs);
443         if (result != RET_OK) {
444             SIGNATURE_TOOLS_LOGE("verify certchain failed");
445             return result;
446         }
447     }
448 
449     return RET_OK;
450 }
451 
CheckSignerInfoSignTimeInCertChainValidPeriod(PKCS7_SIGNER_INFO * signerInfo,const std::vector<X509 * > & certs) const452 int PKCS7Data::CheckSignerInfoSignTimeInCertChainValidPeriod(PKCS7_SIGNER_INFO* signerInfo,
453                                                              const std::vector<X509*>& certs) const
454 {
455     if (signerInfo == NULL) {
456         PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR, "input is NULL, check signtime invalid");
457         return INVALIDPARAM_ERROR;
458     }
459     ASN1_TYPE* signTime = PKCS7_get_signed_attribute(signerInfo, NID_pkcs9_signingTime);
460     for (int i = 0; i < static_cast<int>(certs.size()); i++) {
461         X509* cert = certs[i];
462         const ASN1_TIME* notBefore = X509_get0_notBefore(cert);
463         const ASN1_TIME* notAfter = X509_get0_notAfter(cert);
464         if (CheckSignTimeInValidPeriod(signTime, notBefore, notAfter) < 0) {
465             SIGNATURE_TOOLS_LOGE("pkcs7 sign time check failed");
466             return INVALIDPARAM_ERROR;
467         }
468     }
469     return RET_OK;
470 }
471 
VerifySignerInfoCertChain(PKCS7 * pkcs7,PKCS7_SIGNER_INFO * signerInfo,STACK_OF (X509)* certs) const472 int PKCS7Data::VerifySignerInfoCertChain(PKCS7* pkcs7, PKCS7_SIGNER_INFO* signerInfo,
473                                          STACK_OF(X509)* certs) const
474 {
475     X509* sigCert = PKCS7_cert_from_signer_info(pkcs7, signerInfo);
476     if (sigCert == nullptr) {
477         PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, "Get sign cert from signInfo failed");
478         return VERIFY_ERROR;
479     }
480 
481     CertSign certVisitFlag;
482     VerifyCertOpensslUtils::GenerateCertSignFromCertStack(certs, certVisitFlag);
483     std::vector<X509*> certChain;
484     certChain.emplace_back(X509_dup(sigCert));
485     if (!VerifyCertOpensslUtils::GetCertsChain(certChain, certVisitFlag)) {
486         PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, "Get cert chain for signInfo failed");
487         ClearCertChain(certChain);
488         return VERIFY_ERROR;
489     }
490     if (certChain.size() < MIN_CERTS_NUM) {
491         PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, "GetCertsChain less than two!");
492         ClearCertChain(certChain);
493         return VERIFY_ERROR;
494     }
495 
496     /* Verify that the signature time in the signature information is within the validity period of
497     the certificate chain (entity certificate will be verified in PKCS7_verify) */
498     if (CheckSignerInfoSignTimeInCertChainValidPeriod(signerInfo, certChain) < 0) {
499         SIGNATURE_TOOLS_LOGE("sign time is invalid, verify failed");
500         ClearCertChain(certChain);
501         return VERIFY_ERROR;
502     }
503     ClearCertChain(certChain);
504     return RET_OK;
505 }
506 
ClearCertChain(std::vector<X509 * > & certChain) const507 void PKCS7Data::ClearCertChain(std::vector<X509*>& certChain) const
508 {
509     for (auto cert : certChain) {
510         X509_free(cert);
511     }
512     certChain.clear();
513 }
514 
Pkcs7SignAttr(PKCS7_SIGNER_INFO * info)515 int PKCS7Data::Pkcs7SignAttr(PKCS7_SIGNER_INFO* info)
516 {
517     unsigned char* attrBuf = NULL;
518     int attrLen;
519 
520     std::string data;
521     std::string signature;
522     unsigned char* sigRet = NULL;
523     int sigLen = 0;
524 
525     attrLen = ASN1_item_i2d(reinterpret_cast<ASN1_VALUE*>(info->auth_attr), &attrBuf,
526                             ASN1_ITEM_rptr(PKCS7_ATTR_SIGN));
527     if (!attrBuf) {
528         OPENSSL_free(attrBuf);
529         return 0;
530     }
531 
532     data.assign(reinterpret_cast<const char*>(attrBuf), attrLen);
533     signature = m_signer->GetSignature(data, m_sigAlg);
534     if (signature.empty()) {
535         OPENSSL_free(attrBuf);
536         return 0;
537     }
538     sigLen = signature.size();
539     sigRet = reinterpret_cast<unsigned char*>(OPENSSL_malloc(sigLen));
540     if (sigRet == NULL) {
541         OPENSSL_free(attrBuf);
542         return 0;
543     }
544     std::copy(&signature[0], &signature[0] + signature.size(), sigRet);
545     ASN1_STRING_set0(info->enc_digest, sigRet, sigLen);
546     OPENSSL_free(attrBuf);
547     return 1;
548 }
549 
PKCS7GetASN1Content(PKCS7 * pkcs7)550 static ASN1_OCTET_STRING* PKCS7GetASN1Content(PKCS7* pkcs7)
551 {
552     if (PKCS7_type_is_data(pkcs7)) {
553         return pkcs7->d.data;
554     }
555     return NULL;
556 }
557 
Pkcs7AddTimeDigestAndSignAttr(PKCS7_SIGNER_INFO * info,EVP_MD_CTX * hashCtx)558 int PKCS7Data::Pkcs7AddTimeDigestAndSignAttr(PKCS7_SIGNER_INFO* info, EVP_MD_CTX* hashCtx)
559 {
560     unsigned char hashData[EVP_MAX_MD_SIZE];
561     unsigned int hashLen;
562 
563     /* add signing time */
564     if (!PKCS7_get_signed_attribute(info, NID_pkcs9_signingTime)) {
565         if (!PKCS7_add0_attrib_signing_time(info, NULL)) {
566             return 0;
567         }
568     }
569 
570     /* add digest */
571     if (!EVP_DigestFinal_ex(hashCtx, hashData, &hashLen)) {
572         return 0;
573     }
574     if (!PKCS7_add1_attrib_digest(info, hashData, hashLen)) {
575         return 0;
576     }
577 
578     /* sign the attributes */
579     if (!Pkcs7SignAttr(info)) {
580         return 0;
581     }
582 
583     return 1;
584 }
585 
PKCS7SearchDigest(EVP_MD_CTX ** pHash,BIO * io,int numberID)586 static BIO* PKCS7SearchDigest(EVP_MD_CTX** pHash, BIO* io, int numberID)
587 {
588     while ((io = BIO_find_type(io, BIO_TYPE_MD))) {
589         BIO_get_md_ctx(io, pHash);
590         if (*pHash == NULL) {
591             return NULL;
592         }
593         if (EVP_MD_CTX_type(*pHash) == numberID) {
594             return io;
595         }
596         io = BIO_next(io);
597     }
598     return NULL;
599 }
600 
PKCS7DataFinalCheck(PKCS7 * pkcs7,BIO * bio,STACK_OF (PKCS7_SIGNER_INFO)** psk,ASN1_OCTET_STRING ** pos)601 static int PKCS7DataFinalCheck(PKCS7* pkcs7, BIO* bio,
602                                STACK_OF(PKCS7_SIGNER_INFO)** psk, ASN1_OCTET_STRING** pos)
603 {
604     int id = 0;
605 
606     if (pkcs7 == NULL || pkcs7->d.ptr == NULL) {
607         return 0;
608     }
609 
610     id = OBJ_obj2nid(pkcs7->type);
611     pkcs7->state = PKCS7_S_HEADER;
612 
613     if (id == NID_pkcs7_signed) {
614         *psk = pkcs7->d.sign->signer_info;
615         *pos = PKCS7GetASN1Content(pkcs7->d.sign->contents);
616         if (PKCS7_type_is_data(pkcs7->d.sign->contents) && pkcs7->detached) {
617             ASN1_OCTET_STRING_free(*pos);
618             *pos = NULL;
619             pkcs7->d.sign->contents->d.data = NULL;
620         }
621         return 1;
622     }
623     return 0;
624 }
625 
Pkcs7DataFinalSignAttr(STACK_OF (PKCS7_SIGNER_INFO)* infoStack,BIO * bio)626 int PKCS7Data::Pkcs7DataFinalSignAttr(STACK_OF(PKCS7_SIGNER_INFO)* infoStack, BIO* bio)
627 {
628     EVP_MD_CTX* hashCtx = NULL;
629     STACK_OF(X509_ATTRIBUTE)* attrStack = NULL;
630     BIO* ioTmp = NULL;
631     int result = 0;
632     EVP_MD_CTX* ctxTmp = EVP_MD_CTX_new();
633     if (ctxTmp == NULL) {
634         return 0;
635     }
636 
637     if (infoStack == NULL) {
638         goto err;
639     }
640     for (int i = 0; i < sk_PKCS7_SIGNER_INFO_num(infoStack); i++) {
641         PKCS7_SIGNER_INFO* info = sk_PKCS7_SIGNER_INFO_value(infoStack, i);
642 
643         int numberID = OBJ_obj2nid(info->digest_alg->algorithm);
644 
645         ioTmp = bio;
646 
647         ioTmp = PKCS7SearchDigest(&hashCtx, ioTmp, numberID);
648 
649         if (ioTmp == NULL || !EVP_MD_CTX_copy_ex(ctxTmp, hashCtx)) {
650             goto err;
651         }
652 
653         attrStack = info->auth_attr;
654 
655         if (sk_X509_ATTRIBUTE_num(attrStack) > 0) {
656             if (!Pkcs7AddTimeDigestAndSignAttr(info, ctxTmp)) {
657                 goto err;
658             }
659         } else {
660             goto err;
661         }
662     }
663     result = 1;
664 err:
665     EVP_MD_CTX_free(ctxTmp);
666     return result;
667 }
668 
PKCS7DataFinalSetContent(PKCS7 * pkcs7,ASN1_OCTET_STRING * asn1Str,BIO * io)669 static int PKCS7DataFinalSetContent(PKCS7* pkcs7, ASN1_OCTET_STRING* asn1Str, BIO* io)
670 {
671     BIO* ioTmp = NULL;
672     if (!PKCS7_is_detached(pkcs7)) {
673         if (asn1Str == NULL) {
674             return 0;
675         }
676         if (!(asn1Str->flags & ASN1_STRING_FLAG_NDEF)) {
677             char* contentData;
678             long contentLen;
679             ioTmp = BIO_find_type(io, BIO_TYPE_MEM);
680             if (ioTmp == NULL) {
681                 return 0;
682             }
683             contentLen = BIO_get_mem_data(ioTmp, &contentData);
684 
685             BIO_set_flags(ioTmp, BIO_FLAGS_MEM_RDONLY);
686             BIO_set_mem_eof_return(ioTmp, 0);
687             ASN1_STRING_set0(asn1Str, reinterpret_cast<unsigned char*>(contentData), contentLen);
688         }
689     }
690     return 1;
691 }
Pkcs7DataFinal(PKCS7 * pkcs7,BIO * io)692 int PKCS7Data::Pkcs7DataFinal(PKCS7* pkcs7, BIO* io)
693 {
694     STACK_OF(PKCS7_SIGNER_INFO)* infoStack = NULL;
695     ASN1_OCTET_STRING* os = NULL;
696 
697     if (!PKCS7DataFinalCheck(pkcs7, io, &infoStack, &os) ||
698         !Pkcs7DataFinalSignAttr(infoStack, io) ||
699         !PKCS7DataFinalSetContent(pkcs7, os, io)) {
700         return 0;
701     }
702     return 1;
703 }
704 
Pkcs7Final(PKCS7 * pkcs7,const std::string & content,int flags)705 int PKCS7Data::Pkcs7Final(PKCS7* pkcs7, const std::string& content, int flags)
706 {
707     BIO* p7bio;
708     int result = 0;
709 
710     if ((p7bio = PKCS7_dataInit(pkcs7, NULL)) == NULL) {
711         return 0;
712     }
713 
714     if (BIO_write(p7bio, content.c_str(), static_cast<int>(content.size())) <= 0) {
715         SIGNATURE_TOOLS_LOGE("add json data to pkcs7 failed");
716         goto err;
717     }
718 
719     (void)BIO_flush(p7bio);
720 
721     if (!Pkcs7DataFinal(pkcs7, p7bio)) {
722         goto err;
723     }
724     /* Verify the signature value */
725     if (VerifySignature(pkcs7, p7bio) < 0) {
726         goto err;
727     }
728     result = 1;
729 
730 err:
731     BIO_free_all(p7bio);
732     return result;
733 }
734 
Pkcs7SetSignerInfo(PKCS7_SIGNER_INFO * info,X509 * cert,const EVP_MD * hash)735 static int Pkcs7SetSignerInfo(PKCS7_SIGNER_INFO* info, X509* cert, const EVP_MD* hash)
736 {
737     if (!ASN1_INTEGER_set(info->version, 1) ||
738         !X509_NAME_set(&info->issuer_and_serial->issuer, X509_get_issuer_name(cert))) {
739         return 0;
740     }
741 
742     ASN1_INTEGER_free(info->issuer_and_serial->serial);
743     if (!(info->issuer_and_serial->serial =
744           ASN1_INTEGER_dup(X509_get_serialNumber(cert)))) {
745         return 0;
746     }
747 
748     X509_ALGOR_set0(info->digest_alg, OBJ_nid2obj(EVP_MD_type(hash)),
749                     V_ASN1_NULL, NULL);
750 
751     if (!SetSignerInfoSignAlgor(info)) {
752         return 0;
753     }
754     return 1;
755 }
756 
Pkcs7AddSignature(PKCS7 * pkcs7,X509 * cert,const EVP_MD * hash)757 static PKCS7_SIGNER_INFO* Pkcs7AddSignature(PKCS7* pkcs7, X509* cert, const EVP_MD* hash)
758 {
759     PKCS7_SIGNER_INFO* info = NULL;
760 
761     if (!(info = PKCS7_SIGNER_INFO_new()) ||
762         !Pkcs7SetSignerInfo(info, cert, hash) ||
763         !PKCS7_add_signer(pkcs7, info)) {
764         goto err;
765     }
766     return info;
767 err:
768     PKCS7_SIGNER_INFO_free(info);
769     return NULL;
770 }
771 
772 
Pkcs7AddSignerInfo(PKCS7 * pkcs7,X509 * entityCert,const EVP_MD * hash,int flags)773 static PKCS7_SIGNER_INFO* Pkcs7AddSignerInfo(PKCS7* pkcs7, X509* entityCert, const EVP_MD* hash, int flags)
774 {
775     PKCS7_SIGNER_INFO* info = NULL;
776     if ((info = Pkcs7AddSignature(pkcs7, entityCert, hash)) == NULL) {
777         return NULL;
778     }
779     if (!PKCS7_add_certificate(pkcs7, entityCert)) {
780         return NULL;
781     }
782     if (!PKCS7_add_attrib_content_type(info, NULL)) {
783         return NULL;
784     }
785     return info;
786 }
787 
Pkcs7Sign(X509 * entityCert,STACK_OF (X509)* certs,const EVP_MD * hash,const std::string & content,int flags,const std::vector<PKCS7Attr> & attrs)788 PKCS7* PKCS7Data::Pkcs7Sign(X509* entityCert, STACK_OF(X509)* certs, const EVP_MD* hash,
789                             const std::string& content, int flags, const std::vector<PKCS7Attr>& attrs)
790 {
791     PKCS7* pkcs7;
792 
793     if (!(pkcs7 = PKCS7_new()) ||
794         !PKCS7_set_type(pkcs7, NID_pkcs7_signed) ||
795         !PKCS7_content_new(pkcs7, NID_pkcs7_data) ||
796         !Pkcs7AddSignerInfo(pkcs7, entityCert, hash, flags) ||
797         (PKCS7AddAttribute(pkcs7, attrs) < 0)) {
798         PKCS7_free(pkcs7);
799         return NULL;
800     }
801 
802     if (!(flags & PKCS7_NOCERTS)) {
803         for (int i = 0; i < sk_X509_num(certs); i++) {
804             if (!PKCS7_add_certificate(pkcs7, sk_X509_value(certs, i))) {
805                 PKCS7_free(pkcs7);
806                 return NULL;
807             }
808         }
809     }
810 
811     if (flags & PKCS7_DETACHED) {
812         PKCS7_set_detached(pkcs7, 1);
813     }
814 
815     if (Pkcs7Final(pkcs7, content, flags)) {
816         return pkcs7;
817     }
818     PKCS7_free(pkcs7);
819     return NULL;
820 }
821 } // namespace SignatureTools
822 } // namespace OHOS