• 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 #ifndef SIGNATRUETOOLS_PKCS7DATA_H
16 #define SIGNATRUETOOLS_PKCS7DATA_H
17 
18 #include <fstream>
19 #include <string>
20 #include <vector>
21 #include <memory>
22 #include <algorithm>
23 #include <unordered_set>
24 #include <algorithm>
25 #include <list>
26 
27 #include "openssl/pem.h"
28 #include "openssl/ecdsa.h"
29 #include "openssl/evp.h"
30 #include "openssl/ec.h"
31 #include "openssl/asn1t.h"
32 #include "openssl/pkcs7.h"
33 #include "signer.h"
34 #include "verify_cert_openssl_utils.h"
35 
36  /* compare cert is equal in std::unordered_set<X509*> for SortX509Stack */
37 template<>
38 struct std::equal_to<X509*> {
39     bool operator() (X509* cert1, X509* cert2) const
40     {
41         ASN1_INTEGER* serial1 = X509_get_serialNumber(cert1);
42         ASN1_INTEGER* serial2 = X509_get_serialNumber(cert2);
43         bool serialEqual = ASN1_INTEGER_cmp(serial1, serial2) == 0;
44         bool nameEqual = X509_NAME_cmp(X509_get_subject_name(cert1), X509_get_subject_name(cert2)) == 0;
45         return serialEqual && nameEqual;
46     }
47 };
48 
49 /* all cert is put into one bottle */
50 template<>
51 struct std::hash<X509*> {
52     size_t operator()(const X509* cert) const
53     {
54         return 0;
55     }
56 };
57 
58 namespace OHOS {
59 namespace SignatureTools {
60 #define  PKCS7_NODETACHED_FLAGS  (PKCS7_BINARY | PKCS7_NOVERIFY)
61 #define  PKCS7_DETACHED_FLAGS    (PKCS7_BINARY | PKCS7_NOVERIFY | PKCS7_DETACHED)
62 struct PKCS7Attr {
63     int nid;
64     int atrtype;
65     void* value;
66 };
67 
68 class PKCS7Data {
69 public:
70     PKCS7Data(int flags = PKCS7_NODETACHED_FLAGS);
71     PKCS7Data(const PKCS7Data& pkcs7) = delete;
72     const PKCS7Data& operator=(const PKCS7Data& pkcs7) = delete;
73     ~PKCS7Data();
74     /*
75     * @param content The data to be signed
76     * @param signer  signer
77     * @param sigAlg  Signature algorithm SHA256withECDSA/SHA384withECDSA
78     * @param ret     The returned signature result is pkcs7
79     * @param attrs   It is only used when you need to add an ownerID, and you don't need to process it by default
80     * @return        0 :success <0 :error
81     */
82     int Sign(const std::string& content, const std::shared_ptr<Signer>& signer, const std::string& sigAlg,
83              std::string& ret, std::vector<PKCS7Attr> attrs = std::vector<PKCS7Attr>());
84     /* d2i deserialize */
85     int Parse(const std::string& p7bBytes);
86     int Parse(const std::vector<int8_t>& p7bBytes);
87     /* When verifying the signature, you don't need to enter content by default, if the data is separated
88      * (content is not in pkcs7, you need to pass in the original data for verification)
89      */
90     int Verify(const std::string& content = "")const;
91     /* get original raw content*/
92     int GetContent(std::string& content) const;
93 
94     /* In C++, the certificate chain order is forward, and Java is reversed,
95     which is historically the result of correcting the certificate chain order */
96     static int SortX509Stack(STACK_OF(X509)* certs);
97     /* Subject information for printing the certificate chain */
98     static void PrintCertChainSub(const STACK_OF(X509)* certs);
99     static std::string GetASN1Time(const ASN1_TIME* tm);
100     /* Compare the two, first certificate issuers with the second certificate subject info */
101     static bool X509NameCompare(const X509* cert, const X509* issuerCert);
102     /* check pkcs7 sign time in certchain valid period */
103     static int CheckSignTimeInValidPeriod(const ASN1_TYPE* signTime,
104                                           const ASN1_TIME* notBefore, const ASN1_TIME* notAfter);
105 
106 private:
107     int Parse(const unsigned char** in, long len);
108     int InitPkcs7(const std::string& content, const std::shared_ptr<Signer>& signer,
109                   const std::string& sigAlg, std::vector<PKCS7Attr> attrs);
110     /* Verify Signature Value The certificate chain is not verified here */
111     int VerifySign(const std::string& content)const;
112     int VerifyCertChain()const;
113     /* Verify the validity of the time */
114     int CheckSginerInfoSignTimeInCertChainValidPeriod(PKCS7_SIGNER_INFO* signerInfo, STACK_OF(X509)* certs)const;
115     /* @param cert Entity Certificate
116      * @param certs Certificate chain (without Entity certificates)
117      * @param certChain Certificate chain (with Entity certificates)
118      * @retrun 0 success <0 error
119      */
120     int VerifySignerInfoCertchain(PKCS7* p7,
121                                   PKCS7_SIGNER_INFO* signerInfo,
122                                   STACK_OF(X509)* certs,
123                                   STACK_OF(X509)* certChain)const;
124 
125 private:
126     /* For ease of reading, the following interface will be as consistent as possible with the OpenSSL
127     library interface style, and the return value is 1 success and 0 failure */
128     int Pkcs7SignAttr(PKCS7_SIGNER_INFO* si);
129 
130     int Pkcs7AddTimeDigestAndSignAttr(PKCS7_SIGNER_INFO* si, EVP_MD_CTX* mctx);
131 
132     int Pkcs7DataFinalSignAttr(STACK_OF(PKCS7_SIGNER_INFO)* si_sk, BIO* bio);
133 
134     int Pkcs7DataFinal(PKCS7* p7, BIO* bio);
135 
136     int Pkcs7Final(PKCS7* p7, const std::string& content, int flags);
137 
138     PKCS7* Pkcs7Sign(X509* signcert, STACK_OF(X509)* certs, const EVP_MD* md,
139                      const std::string& content, int flags, const std::vector<PKCS7Attr>& attrs);
140 
141 private:
142     PKCS7* m_p7 = NULL;
143     int m_flags;
144     std::shared_ptr<Signer> m_signer; // tmp
145     std::string m_sigAlg; // tmp
146 };
147 } // namespace SignatureTools
148 } // namespace OHOS
149 #endif // SIGNATRUETOOLS_PKCS7DATA_H