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#ifndef PKCS7_SIGNED_DATA_H
17#define PKCS7_SIGNED_DATA_H
18
19#include <vector>
20#include <openssl/pkcs7.h>
21#include <openssl/x509.h>
22#include "pkg_manager.h"
23
24namespace Hpackage {
25using DataBuffer = struct {
26    std::vector<char> buffer;
27    size_t length;
28};
29
30using HwSigningSigntureInfo = struct {
31    DataBuffer overall;
32    DataBuffer hashResult;
33    int nid;
34};
35
36struct Pkcs7SignerInfo {
37    X509_NAME *issuerName = nullptr;
38    ASN1_INTEGER *serialNumber = nullptr;
39    int32_t digestNid {};
40    int32_t digestEncryptNid {};
41    std::vector<uint8_t> digestEncryptData;
42    const unsigned char *buffer;
43    size_t length;
44};
45
46enum {
47    PKCS7_SUCCESS = 0,
48    PKCS7_INIT_ERR = 200,
49    PKCS7_INVALID_PARAM_ERR,
50    PKCS7_INVALID_VALUE_ERR,
51    PKCS7_HAS_NO_VALID_SIG_ERR,
52    PKCS7_PARSING_ERR,
53    PKCS7_VERIFY_FAIL_ERR,
54};
55
56class VerifyHelper {
57public:
58    virtual int32_t GetDigestFromSubBlocks(std::vector<uint8_t> &digestBlock,
59        HwSigningSigntureInfo &signatureInfo, std::vector<uint8_t> &digest) = 0;
60
61    virtual ~VerifyHelper() {}
62};
63
64class Pkcs7SignedData {
65public:
66    Pkcs7SignedData() : pkcs7_(nullptr), digest_(), signerInfos_(), signatureInfo() {}
67
68    ~Pkcs7SignedData();
69
70    int32_t GetHashFromSignBlock(const uint8_t *srcData, const size_t dataLen,
71        std::vector<uint8_t> &hash);
72
73    int32_t ParsePkcs7Data(const uint8_t *srcData, const size_t dataLen);
74
75    int32_t Verify() const;
76
77    int32_t Verify(const std::vector<uint8_t> &hash, const std::vector<uint8_t> &sig, bool sigInSignerInfo) const;
78
79    void RegisterVerifyHelper(std::unique_ptr<VerifyHelper> ptr);
80
81    static Pkcs7SignedData &GetInstance();
82
83    int32_t GetDigest(std::vector<uint8_t> &digestBlock,
84        HwSigningSigntureInfo &signatureInfo, std::vector<uint8_t> &digest);
85
86    int32_t ReadSig(const uint8_t *sourceData, const uint32_t sourceDataLen, std::vector<std::vector<uint8_t>> &sigs);
87private:
88    int32_t Init(const uint8_t *sourceData, const uint32_t sourceDataLen);
89    int32_t DoParse();
90    int32_t ParseContentInfo(std::vector<uint8_t> &digestBlock) const;
91    int32_t GetDigestFromContentInfo(std::vector<uint8_t> &digestBlock);
92    int32_t DoUpdateVerify(std::vector<uint8_t> &digestBlock);
93    int32_t SignerInfosParse();
94    int32_t SignerInfoParse(PKCS7_SIGNER_INFO *p7SignerInfo, Pkcs7SignerInfo &signerInfo);
95    int32_t Pkcs7SignleSignerVerify(const Pkcs7SignerInfo &signerInfo, const std::vector<uint8_t> &hash,
96        const std::vector<uint8_t> &sig) const;
97    int32_t VerifyDigest(X509 *cert, const Pkcs7SignerInfo &signer, const std::vector<uint8_t> &hash,
98        const std::vector<uint8_t> &sig) const;
99private:
100    PKCS7 *pkcs7_;
101    std::vector<uint8_t> digest_;
102    std::vector<Pkcs7SignerInfo> signerInfos_;
103    HwSigningSigntureInfo signatureInfo;
104    std::unique_ptr<VerifyHelper> helper_ {};
105};
106
107class Pkcs7VerifyHelper : public VerifyHelper {
108public:
109    Pkcs7VerifyHelper() = default;
110
111    ~Pkcs7VerifyHelper() override;
112
113    int32_t GetDigestFromSubBlocks(std::vector<uint8_t> &digestBlock,
114        HwSigningSigntureInfo &signatureInfo, std::vector<uint8_t> &digest) override;
115};
116} // namespace Hpackage
117#endif
118