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 */ 37template<> 38struct 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 */ 50template<> 51struct std::hash<X509*> { 52 size_t operator()(const X509* cert) const 53 { 54 return 0; 55 } 56}; 57 58namespace OHOS { 59namespace SignatureTools { 60#define PKCS7_NODETACHED_FLAGS (PKCS7_BINARY | PKCS7_NOVERIFY) 61#define PKCS7_DETACHED_FLAGS (PKCS7_BINARY | PKCS7_NOVERIFY | PKCS7_DETACHED) 62struct PKCS7Attr { 63 int nid; 64 int atrtype; 65 void* value; 66}; 67 68class PKCS7Data { 69public: 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 106private: 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 125private: 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 141private: 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