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 (VerifySign(content) < 0) {
164         PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, "signature verify failed");
165         return VERIFY_ERROR;
166     }
167     if (VerifyCertChain() < 0) {
168         PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, "cert Chain verify failed");
169         PrintCertChainSub(m_p7->d.sign->cert);
170         return VERIFY_ERROR;
171     }
172     return RET_OK;
173 }
174 
GetContent(std::string& originalRawData) const175 int PKCS7Data::GetContent(std::string& originalRawData) const
176 {
177     BIO* oriBio = PKCS7_dataDecode(m_p7, NULL, NULL, NULL);
178     if (oriBio == NULL) {
179         PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR, "pkcs7 get content data failed!");
180         return INVALIDPARAM_ERROR;
181     }
182     char buf[BUFFER_SIZE]{0};
183     size_t readBytes = 0;
184     while (BIO_read_ex(oriBio, buf, sizeof(buf), &readBytes) == 1) {
185         originalRawData.append(buf, readBytes);
186     }
187     BIO_free_all(oriBio);
188     return RET_OK;
189 }
190 
PKCS7AddCrls(PKCS7* p7, STACK_OF(X509_CRL)* crls)191 static void PKCS7AddCrls(PKCS7* p7, STACK_OF(X509_CRL)* crls)
192 {
193     for (int i = 0; i < sk_X509_CRL_num(crls); i++) {
194         PKCS7_add_crl(p7, sk_X509_CRL_value(crls, i));
195     }
196 }
197 
InitPkcs7(const std::string& content, const std::shared_ptr<Signer>& signer, const std::string& sigAlg, std::vector<PKCS7Attr> attrs)198 int PKCS7Data::InitPkcs7(const std::string& content, const std::shared_ptr<Signer>& signer,
199                          const std::string& sigAlg, std::vector<PKCS7Attr> attrs)
200 {
201     STACK_OF(X509)* certs = NULL;
202     /* hash algorithm */
203     const EVP_MD* md = NULL;
204     /* entity certificate */
205     X509* cert = NULL;
206     int result = RET_OK;
207     if (signer == NULL) {
208         PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR, "signer is NULL , sign failed");
209         result = INVALIDPARAM_ERROR;
210         goto err;
211     }
212     m_signer = signer;
213     m_sigAlg = sigAlg;
214     certs = signer->GetCertificates();
215     if (SortX509Stack(certs) < 0) {
216         result = RET_FAILED;
217         goto err;
218     }
219     if (sigAlg == SIGN_ALG_SHA384) {
220         md = EVP_sha384();
221     } else if (sigAlg == SIGN_ALG_SHA256) {
222         md = EVP_sha256();
223     } else {
224         PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR,
225                             sigAlg + "is invalid sigAlg, please use SHA256withECDSA/SHA384withECDSA, sign failed");
226         result = INVALIDPARAM_ERROR;
227         goto err;
228     }
229     /* Extract the entity certificate from the certificate chain */
230     cert = sk_X509_delete(certs, 0);
231     m_p7 = Pkcs7Sign(cert, certs, md, content, m_flags, attrs);
232     if (m_p7 == NULL) {
233         PrintErrorNumberMsg("INVALIDPARAM_ERROR", SIGN_ERROR, "p7 is NULL, pkcs7 sign failed");
234         result = SIGN_ERROR;
235         goto err;
236     }
237     PKCS7AddCrls(m_p7, signer->GetCrls());
238 
239 err:
240     sk_X509_pop_free(certs, X509_free);
241     X509_free(cert);
242     return result;
243 }
244 
245 void PKCS7Data::PrintCertChainSub(const STACK_OF(X509)* certs)
246 {
247     if (certs == NULL)
248         return;
249     SIGNATURE_TOOLS_LOGI("certChainSubject:");
250     int certNum = sk_X509_num(certs);
251     SIGNATURE_TOOLS_LOGI("certNum%s", std::to_string(certNum).c_str());
252     for (int i = 0; i < certNum; i++) {
253         SIGNATURE_TOOLS_LOGI("certificate %s", std::to_string(i).c_str());
254         std::string sub;
255         VerifyCertOpensslUtils::GetSubjectFromX509(sk_X509_value(certs, i), sub);
256         SIGNATURE_TOOLS_LOGI("%s", sub.c_str());
257     }
258 }
259 
GetASN1Time(const ASN1_TIME* tm)260 std::string PKCS7Data::GetASN1Time(const ASN1_TIME* tm)
261 {
262     if (tm == NULL) {
263         return "";
264     }
265     /* Convert the ASN1_TIME structure to a standard tm structure. */
266     struct tm time;
267     ASN1_TIME_to_tm(tm, &time);
268     /* Convert to local time(considering the time zone) */
269     time_t t = mktime(&time);
270     if (t < 0) {
271         return "";
272     }
273     struct tm* localTime = localtime(&t);
274     if (localTime == nullptr) {
275         return "";
276     }
277     /* Print local time */
278     char buf[128] = {0};
279     if (sprintf_s(buf, sizeof(buf), "%04d-%02d-%02d %02d:%02d:%02d",
280                   localTime->tm_year + YEAR1900, localTime->tm_mon + 1, localTime->tm_mday,
281                   localTime->tm_hour, localTime->tm_min, localTime->tm_sec) == -1) {
282         return "";
283     }
284     return std::string(buf, strlen(buf));
285 }
286 
X509NameCompare(const X509* cert, const X509* issuerCert)287 bool PKCS7Data::X509NameCompare(const X509* cert, const X509* issuerCert)
288 {
289     if (cert == nullptr || issuerCert == nullptr) {
290         PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR,
291                             "input cert is NULL");
292         return false;
293     }
294     X509_NAME* aName = X509_get_issuer_name(cert);
295     X509_NAME* bName = X509_get_subject_name(issuerCert);
296     if (X509_NAME_cmp(aName, bName) != 0) {
297         PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR,
298                             "cert issuer name is not equal to its issuer\'s  name");
299         return false;
300     }
301     return true;
302 }
303 
CheckSignTimeInValidPeriod(const ASN1_TYPE* signTime, const ASN1_TIME* notBefore, const ASN1_TIME* notAfter)304 int PKCS7Data::CheckSignTimeInValidPeriod(const ASN1_TYPE* signTime,
305                                           const ASN1_TIME* notBefore, const ASN1_TIME* notAfter)
306 {
307     if (notBefore == nullptr || notBefore->data == nullptr || notAfter == nullptr || notAfter->data == nullptr) {
308         PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR,
309                             "invalid period, check signtime failed please use valid period to to check signtime");
310         return INVALIDPARAM_ERROR;
311     }
312     if (signTime == nullptr || signTime->value.asn1_string == nullptr ||
313         signTime->value.asn1_string->data == nullptr) {
314         PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR, "signtime is NULL");
315         return INVALIDPARAM_ERROR;
316     }
317     ASN1_TIME* tm = ASN1_TIME_new();
318     ASN1_TIME_set_string(tm, (reinterpret_cast<const char*>(signTime->value.asn1_string->data)));
319     if (ASN1_TIME_compare(notBefore, signTime->value.asn1_string) > 0 ||
320         ASN1_TIME_compare(notAfter, signTime->value.asn1_string) < 0) {
321         SIGNATURE_TOOLS_LOGE("sign time invalid, signTime: %s, notBefore: %s, "
322                              "notAfter: %s", GetASN1Time(tm).c_str(),
323                              GetASN1Time(notBefore).c_str(), GetASN1Time(notAfter).c_str());
324         ASN1_TIME_free(tm);
325         return RET_FAILED;
326     }
327     ASN1_TIME_free(tm);
328     return RET_OK;
329 }
330 
FindSubCertThenEraseItFromSets(X509* cert, std::unordered_set<X509*>& x509Sets)331 static X509* FindSubCertThenEraseItFromSets(X509* cert, std::unordered_set<X509*>& x509Sets)
332 {
333     X509* ret = NULL;
334     for (X509* c : x509Sets) {
335         X509_NAME* name1 = X509_get_subject_name(cert);
336         X509_NAME* name2 = X509_get_issuer_name(c);
337         if (X509_NAME_cmp(name1, name2) == 0) {
338             x509Sets.erase(c);
339             ret = c;
340             break;
341         }
342     }
343     return ret;
344 }
345 
346 int PKCS7Data::SortX509Stack(STACK_OF(X509)* certs)
347 {
348     std::unordered_set<X509*> x509Sets;
349     std::list<X509*>certChain;
350     X509* tmp = NULL;
351     int result = RET_FAILED;
352 
353     if (sk_X509_num(certs) < MIN_CERTS_NUM) {
354         PrintErrorNumberMsg("CERTIFICATE_ERROR", CERTIFICATE_ERROR, "cert of certchain count less than two!");
355         goto err;
356     }
357     for (int i = 0; i < sk_X509_num(certs); i++) {
358         x509Sets.insert(sk_X509_value(certs, i));
359     }
360     if (sk_X509_num(certs) != static_cast<int>(x509Sets.size())) {
361         PrintErrorNumberMsg("CERTIFICATE_ERROR", CERTIFICATE_ERROR, "sort x509 certchain failed!");
362         goto err;
363     }
364     for (X509* cert : x509Sets) {
365         if (X509_name_cmp(X509_get_subject_name(cert), X509_get_issuer_name(cert)) == 0) {
366             tmp = cert;
367             x509Sets.erase(cert);
368             break;
369         }
370     }
371     if (tmp == NULL) {
372         PrintErrorNumberMsg("CERTIFICATE_ERROR", CERTIFICATE_ERROR,
373                             "can't find root cert from certchain ,sort x509 certchain failed!");
374         goto err;
375     }
376     certChain.push_front(tmp);
377     while ((tmp = FindSubCertThenEraseItFromSets(tmp, x509Sets))) {
378         certChain.push_front(tmp);
379     }
380     if (x509Sets.size() != 0) {
381         PrintErrorNumberMsg("CERTIFICATE_ERROR", CERTIFICATE_ERROR,
382                             "certchain contain invalid cert, sort x509 certchain failed!");
383         goto err;
384     }
385     while (sk_X509_num(certs)) {
386         sk_X509_pop(certs);
387     }
388     for (X509* cert : certChain) {
389         sk_X509_push(certs, cert);
390     }
391     result = RET_OK;
392 err:
393     return result;
394 }
395 
VerifySign(const std::string& content) const396 int PKCS7Data::VerifySign(const std::string& content)const
397 {
398     BIO* inBio = NULL;
399     if ((m_flags & PKCS7_DETACHED)) {
400         inBio = BIO_new_mem_buf(reinterpret_cast<const void*>(content.c_str()),
401                                 static_cast<int>(content.size()));
402         if (inBio == NULL) {
403             PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR,
404                                 "new mem buf error!,pkcs7 verify signature failed");
405             return VERIFY_ERROR;
406         }
407     }
408     if (PKCS7_verify(m_p7, NULL, NULL, inBio, NULL, m_flags) != 1) {
409         PrintErrorNumberMsg("VERIFY_ERROR", VERIFY_ERROR, "pkcs7 verify signature failed");
410         BIO_free(inBio);
411         return VERIFY_ERROR;
412     }
413     BIO_free(inBio);
414     return RET_OK;
415 }
416 
VerifyCertChain() const417 int PKCS7Data::VerifyCertChain()const
418 {
419     /* Validate the certificate chain */
420     STACK_OF(PKCS7_SIGNER_INFO)* skSignerInfo = PKCS7_get_signer_info(m_p7);
421     int signerCount = sk_PKCS7_SIGNER_INFO_num(skSignerInfo);
422     int c = signerCount;
423     STACK_OF(X509)* certs = NULL;
424     int result = RET_FAILED;
425     /* Original certificate chain */
426     STACK_OF(X509)* certChain = m_p7->d.sign->cert;
427     /* Copy of the certificate chain, with the entity certificate removed later */
428     certs = sk_X509_dup(certChain);
429     if (SortX509Stack(certs) < 0) {
430         SIGNATURE_TOOLS_LOGE("sort x509 stack failed, verify certchain failed");
431         goto err;
432     }
433     /* Retrieve the certificate chain without the entity certificate */
434     while (c--) {
435         sk_X509_delete(certs, 0);
436     }
437     for (int i = 0; i < signerCount; i++) {
438         PKCS7_SIGNER_INFO* signerInfo = sk_PKCS7_SIGNER_INFO_value(skSignerInfo, i);
439         if ((result = VerifySignerInfoCertchain(m_p7, signerInfo, certs, certChain)) < 0) {
440             SIGNATURE_TOOLS_LOGE("verify certchain failed");
441             goto err;
442         }
443     }
444     result = RET_OK;
445 err:
446     sk_X509_free(certs);
447     return result;
448 }
449 
CheckSginerInfoSignTimeInCertChainValidPeriod(PKCS7_SIGNER_INFO* signerInfo, STACK_OF(X509)* certs) const450 int PKCS7Data::CheckSginerInfoSignTimeInCertChainValidPeriod(PKCS7_SIGNER_INFO* signerInfo,
451                                                              STACK_OF(X509)* certs) const
452 {
453     if (signerInfo == NULL || certs == NULL) {
454         PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR, "input is NULL, check signtime invalid");
455         return INVALIDPARAM_ERROR;
456     }
457     ASN1_TYPE* signTime = PKCS7_get_signed_attribute(signerInfo, NID_pkcs9_signingTime);
458     for (int i = 0; i < sk_X509_num(certs); i++) {
459         X509* cert = sk_X509_value(certs, i);
460         const ASN1_TIME* notBefore = X509_get0_notBefore(cert);
461         const ASN1_TIME* notAfter = X509_get0_notAfter(cert);
462         if (CheckSignTimeInValidPeriod(signTime, notBefore, notAfter) < 0) {
463             SIGNATURE_TOOLS_LOGE("pkcs7 sign time check failed");
464             return INVALIDPARAM_ERROR;
465         }
466     }
467     return RET_OK;
468 }
469 
VerifySignerInfoCertchain(PKCS7* pkcs7, PKCS7_SIGNER_INFO* signerInfo, STACK_OF(X509)* certs, STACK_OF(X509)* certChain) const470 int PKCS7Data::VerifySignerInfoCertchain(PKCS7* pkcs7, PKCS7_SIGNER_INFO* signerInfo,
471                                          STACK_OF(X509)* certs, STACK_OF(X509)* certChain)const
472 {
473     X509* sigCert = PKCS7_cert_from_signer_info(pkcs7, signerInfo);
474     int j = 0;
475     /* Trace back through the subject information and validate the signature value of each certificate */
476     if (!X509NameCompare(sigCert, sk_X509_value(certs, 0))) {
477         SIGNATURE_TOOLS_LOGE("entity name compare not equal, verify failed");
478         return VERIFY_ERROR;
479     }
480     /* verify entity certificate signature value */
481     if (!VerifyCertOpensslUtils::CertVerify(sigCert, sk_X509_value(certs, 0))) {
482         SIGNATURE_TOOLS_LOGE("entity cert signature verify failed");
483         return VERIFY_ERROR;
484     }
485     for (; j + 1 < sk_X509_num(certs); j++) {
486         if (!X509NameCompare(sk_X509_value(certs, j), sk_X509_value(certs, j + 1))) {
487             SIGNATURE_TOOLS_LOGE("sub cert name compare not equal, verify failed");
488             return VERIFY_ERROR;
489         }
490         /* Verify the signature value of the intermediate certificate */
491         if (!VerifyCertOpensslUtils::CertVerify(sk_X509_value(certs, j), sk_X509_value(certs, j + 1))) {
492             SIGNATURE_TOOLS_LOGE("sub cert signature verify failed");
493             return VERIFY_ERROR;
494         }
495     }
496     if (!X509NameCompare(sk_X509_value(certs, j), sk_X509_value(certs, j))) {
497         SIGNATURE_TOOLS_LOGE("root cert name compare not equal, verify failed");
498         return VERIFY_ERROR;
499     }
500     /* Verify the signature value of the root certificate */
501     if (!VerifyCertOpensslUtils::CertVerify(sk_X509_value(certs, j), sk_X509_value(certs, j))) {
502         SIGNATURE_TOOLS_LOGE("root cert signature verify failed");
503         return VERIFY_ERROR;
504     }
505     /* Verify that the signature time in the signature information is within the validity period of
506     the certificate chain (entity certificate will be verified in PKCS7_verify) */
507     if (CheckSginerInfoSignTimeInCertChainValidPeriod(signerInfo, certChain) < 0) {
508         SIGNATURE_TOOLS_LOGE("sign time is invalid,verify failed");
509         return VERIFY_ERROR;
510     }
511     return RET_OK;
512 }
513 
Pkcs7SignAttr(PKCS7_SIGNER_INFO* info)514 int PKCS7Data::Pkcs7SignAttr(PKCS7_SIGNER_INFO* info)
515 {
516     unsigned char* attrBuf = NULL;
517     int attrLen;
518 
519     std::string data;
520     std::string signature;
521     unsigned char* sigRet = NULL;
522     int sigLen = 0;
523 
524     attrLen = ASN1_item_i2d((ASN1_VALUE*)info->auth_attr, &attrBuf,
525                             ASN1_ITEM_rptr(PKCS7_ATTR_SIGN));
526     if (!attrBuf) {
527         OPENSSL_free(attrBuf);
528         return 0;
529     }
530 
531     data.assign(reinterpret_cast<const char*>(attrBuf), attrLen);
532     signature = m_signer->GetSignature(data, m_sigAlg);
533     if (signature.empty()) {
534         OPENSSL_free(attrBuf);
535         return 0;
536     }
537     sigLen = signature.size();
538     sigRet = reinterpret_cast<unsigned char*>(OPENSSL_malloc(sigLen));
539     if (sigRet == NULL) {
540         OPENSSL_free(attrBuf);
541         return 0;
542     }
543     std::copy(&signature[0], &signature[0] + signature.size(), sigRet);
544     ASN1_STRING_set0(info->enc_digest, sigRet, sigLen);
545     OPENSSL_free(attrBuf);
546     return 1;
547 }
548 
PKCS7GetASN1Content(PKCS7* pkcs7)549 static ASN1_OCTET_STRING* PKCS7GetASN1Content(PKCS7* pkcs7)
550 {
551     if (PKCS7_type_is_data(pkcs7)) {
552         return pkcs7->d.data;
553     }
554     return NULL;
555 }
556 
Pkcs7AddTimeDigestAndSignAttr(PKCS7_SIGNER_INFO* info, EVP_MD_CTX* hashCtx)557 int PKCS7Data::Pkcs7AddTimeDigestAndSignAttr(PKCS7_SIGNER_INFO* info, EVP_MD_CTX* hashCtx)
558 {
559     unsigned char hashData[EVP_MAX_MD_SIZE];
560     unsigned int hashLen;
561 
562     /* add signing time */
563     if (!PKCS7_get_signed_attribute(info, NID_pkcs9_signingTime)) {
564         if (!PKCS7_add0_attrib_signing_time(info, NULL)) {
565             return 0;
566         }
567     }
568 
569     /* add digest */
570     if (!EVP_DigestFinal_ex(hashCtx, hashData, &hashLen)) {
571         return 0;
572     }
573     if (!PKCS7_add1_attrib_digest(info, hashData, hashLen)) {
574         return 0;
575     }
576 
577     /* sign the attributes */
578     if (!Pkcs7SignAttr(info)) {
579         return 0;
580     }
581 
582     return 1;
583 }
584 
PKCS7SearchDigest(EVP_MD_CTX** pHash, BIO* io, int numberID)585 static BIO* PKCS7SearchDigest(EVP_MD_CTX** pHash, BIO* io, int numberID)
586 {
587     while ((io = BIO_find_type(io, BIO_TYPE_MD))) {
588         BIO_get_md_ctx(io, pHash);
589         if (*pHash == NULL) {
590             return NULL;
591         }
592         if (EVP_MD_CTX_type(*pHash) == numberID) {
593             return io;
594         }
595         io = BIO_next(io);
596     }
597     return NULL;
598 }
599 
PKCS7DataFinalCheck(PKCS7* pkcs7, BIO* bio, STACK_OF(PKCS7_SIGNER_INFO)** psk, ASN1_OCTET_STRING** pos)600 static int PKCS7DataFinalCheck(PKCS7* pkcs7, BIO* bio,
601                                STACK_OF(PKCS7_SIGNER_INFO)** psk, ASN1_OCTET_STRING** pos)
602 {
603     int id = 0;
604 
605     if (pkcs7 == NULL || pkcs7->d.ptr == NULL) {
606         return 0;
607     }
608 
609     id = OBJ_obj2nid(pkcs7->type);
610     pkcs7->state = PKCS7_S_HEADER;
611 
612     if (id == NID_pkcs7_signed) {
613         *psk = pkcs7->d.sign->signer_info;
614         *pos = PKCS7GetASN1Content(pkcs7->d.sign->contents);
615         if (PKCS7_type_is_data(pkcs7->d.sign->contents) && pkcs7->detached) {
616             ASN1_OCTET_STRING_free(*pos);
617             *pos = NULL;
618             pkcs7->d.sign->contents->d.data = NULL;
619         }
620         return 1;
621     }
622     return 0;
623 }
624 
625 int PKCS7Data::Pkcs7DataFinalSignAttr(STACK_OF(PKCS7_SIGNER_INFO)* infoStack, BIO* bio)
626 {
627     EVP_MD_CTX* hashCtx = NULL;
628     STACK_OF(X509_ATTRIBUTE)* attrStack = NULL;
629     BIO* ioTmp = NULL;
630     int result = 0;
631     EVP_MD_CTX* ctxTmp = EVP_MD_CTX_new();
632     if (ctxTmp == NULL) {
633         return 0;
634     }
635 
636     if (infoStack == NULL) {
637         goto err;
638     }
639     for (int i = 0; i < sk_PKCS7_SIGNER_INFO_num(infoStack); i++) {
640         PKCS7_SIGNER_INFO* info = sk_PKCS7_SIGNER_INFO_value(infoStack, i);
641 
642         int numberID = OBJ_obj2nid(info->digest_alg->algorithm);
643 
644         ioTmp = bio;
645 
646         ioTmp = PKCS7SearchDigest(&hashCtx, ioTmp, numberID);
647 
648         if (ioTmp == NULL || !EVP_MD_CTX_copy_ex(ctxTmp, hashCtx)) {
649             goto err;
650         }
651 
652         attrStack = info->auth_attr;
653 
654         if (sk_X509_ATTRIBUTE_num(attrStack) > 0) {
655             if (!Pkcs7AddTimeDigestAndSignAttr(info, ctxTmp)) {
656                 goto err;
657             }
658         } else {
659             goto err;
660         }
661     }
662     result = 1;
663 err:
664     EVP_MD_CTX_free(ctxTmp);
665     return result;
666 }
667 
PKCS7DataFinalSetContent(PKCS7* pkcs7, ASN1_OCTET_STRING* asn1Str, BIO* io)668 static int PKCS7DataFinalSetContent(PKCS7* pkcs7, ASN1_OCTET_STRING* asn1Str, BIO* io)
669 {
670     BIO* ioTmp = NULL;
671     if (!PKCS7_is_detached(pkcs7)) {
672         if (asn1Str == NULL) {
673             return 0;
674         }
675         if (!(asn1Str->flags & ASN1_STRING_FLAG_NDEF)) {
676             char* contentData;
677             long contentLen;
678             ioTmp = BIO_find_type(io, BIO_TYPE_MEM);
679             if (ioTmp == NULL) {
680                 return 0;
681             }
682             contentLen = BIO_get_mem_data(ioTmp, &contentData);
683 
684             BIO_set_flags(ioTmp, BIO_FLAGS_MEM_RDONLY);
685             BIO_set_mem_eof_return(ioTmp, 0);
686             ASN1_STRING_set0(asn1Str, (unsigned char*)contentData, contentLen);
687         }
688     }
689     return 1;
690 }
Pkcs7DataFinal(PKCS7* pkcs7, BIO* io)691 int PKCS7Data::Pkcs7DataFinal(PKCS7* pkcs7, BIO* io)
692 {
693     STACK_OF(PKCS7_SIGNER_INFO)* infoStack = NULL;
694     ASN1_OCTET_STRING* os = NULL;
695 
696     if (!PKCS7DataFinalCheck(pkcs7, io, &infoStack, &os) ||
697         !Pkcs7DataFinalSignAttr(infoStack, io) ||
698         !PKCS7DataFinalSetContent(pkcs7, os, io)) {
699         return 0;
700     }
701     return 1;
702 }
703 
Pkcs7Final(PKCS7* pkcs7, const std::string& content, int flags)704 int PKCS7Data::Pkcs7Final(PKCS7* pkcs7, const std::string& content, int flags)
705 {
706     BIO* p7bio;
707     int result = 0;
708 
709     if ((p7bio = PKCS7_dataInit(pkcs7, NULL)) == NULL) {
710         return 0;
711     }
712 
713     if (BIO_write(p7bio, content.c_str(), static_cast<int>(content.size())) <= 0) {
714         SIGNATURE_TOOLS_LOGE("add json data to pkcs7 failed");
715         goto err;
716     }
717 
718     (void)BIO_flush(p7bio);
719 
720     if (!Pkcs7DataFinal(pkcs7, p7bio)) {
721         goto err;
722     }
723     /* Verify the signature value */
724     if (VerifySignature(pkcs7, p7bio) < 0) {
725         goto err;
726     }
727     result = 1;
728 
729 err:
730     BIO_free_all(p7bio);
731     return result;
732 }
733 
Pkcs7SetSignerInfo(PKCS7_SIGNER_INFO* info, X509* cert, const EVP_MD* hash)734 static int Pkcs7SetSignerInfo(PKCS7_SIGNER_INFO* info, X509* cert, const EVP_MD* hash)
735 {
736     if (!ASN1_INTEGER_set(info->version, 1) ||
737         !X509_NAME_set(&info->issuer_and_serial->issuer, X509_get_issuer_name(cert))) {
738         return 0;
739     }
740 
741     ASN1_INTEGER_free(info->issuer_and_serial->serial);
742     if (!(info->issuer_and_serial->serial =
743           ASN1_INTEGER_dup(X509_get_serialNumber(cert)))) {
744         return 0;
745     }
746 
747     X509_ALGOR_set0(info->digest_alg, OBJ_nid2obj(EVP_MD_type(hash)),
748                     V_ASN1_NULL, NULL);
749 
750     if (!SetSignerInfoSignAlgor(info)) {
751         return 0;
752     }
753     return 1;
754 }
755 
Pkcs7AddSignature(PKCS7* pkcs7, X509* cert, const EVP_MD* hash)756 static PKCS7_SIGNER_INFO* Pkcs7AddSignature(PKCS7* pkcs7, X509* cert, const EVP_MD* hash)
757 {
758     PKCS7_SIGNER_INFO* info = NULL;
759 
760     if (!(info = PKCS7_SIGNER_INFO_new()) ||
761         !Pkcs7SetSignerInfo(info, cert, hash) ||
762         !PKCS7_add_signer(pkcs7, info)) {
763         goto err;
764     }
765     return info;
766 err:
767     PKCS7_SIGNER_INFO_free(info);
768     return NULL;
769 }
770 
771 
Pkcs7AddSignerInfo(PKCS7* pkcs7, X509* entityCert, const EVP_MD* hash, int flags)772 static PKCS7_SIGNER_INFO* Pkcs7AddSignerInfo(PKCS7* pkcs7, X509* entityCert, const EVP_MD* hash, int flags)
773 {
774     PKCS7_SIGNER_INFO* info = NULL;
775     if ((info = Pkcs7AddSignature(pkcs7, entityCert, hash)) == NULL) {
776         return NULL;
777     }
778     if (!PKCS7_add_certificate(pkcs7, entityCert)) {
779         return NULL;
780     }
781     if (!PKCS7_add_attrib_content_type(info, NULL)) {
782         return NULL;
783     }
784     return info;
785 }
786 
Pkcs7Sign(X509* entityCert, STACK_OF(X509)* certs, const EVP_MD* hash, const std::string& content, int flags, const std::vector<PKCS7Attr>& attrs)787 PKCS7* PKCS7Data::Pkcs7Sign(X509* entityCert, STACK_OF(X509)* certs, const EVP_MD* hash,
788                             const std::string& content, int flags, const std::vector<PKCS7Attr>& attrs)
789 {
790     PKCS7* pkcs7;
791 
792     if (!(pkcs7 = PKCS7_new()) ||
793         !PKCS7_set_type(pkcs7, NID_pkcs7_signed) ||
794         !PKCS7_content_new(pkcs7, NID_pkcs7_data) ||
795         !Pkcs7AddSignerInfo(pkcs7, entityCert, hash, flags) ||
796         (PKCS7AddAttribute(pkcs7, attrs) < 0)) {
797         PKCS7_free(pkcs7);
798         return NULL;
799     }
800 
801     if (!(flags & PKCS7_NOCERTS)) {
802         for (int i = 0; i < sk_X509_num(certs); i++) {
803             if (!PKCS7_add_certificate(pkcs7, sk_X509_value(certs, i))) {
804                 PKCS7_free(pkcs7);
805                 return NULL;
806             }
807         }
808     }
809 
810     if (flags & PKCS7_DETACHED) {
811         PKCS7_set_detached(pkcs7, 1);
812     }
813 
814     if (Pkcs7Final(pkcs7, content, flags)) {
815         return pkcs7;
816     }
817     PKCS7_free(pkcs7);
818     return NULL;
819 }
820 } // namespace SignatureTools
821 } // namespace OHOS