Coverage Report

Created: 2025-09-27 08:03

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/PcapPlusPlus/Packet++/header/CryptoDataReader.h
Line
Count
Source
1
#pragma once
2
3
/// @file
4
5
#include "GeneralUtils.h"
6
#include "PemCodec.h"
7
#include <string>
8
#include <memory>
9
#include <fstream>
10
11
/// @namespace pcpp
12
/// @brief The main namespace for the PcapPlusPlus lib
13
namespace pcpp
14
{
15
  namespace internal
16
  {
17
    /// @class CryptoDataReader
18
    /// @brief A template helper class for reading and decoding cryptographic data in different formats (DER/PEM)
19
    /// @tparam CryptoDecoder The decoder type that will be used to process the cryptographic data.
20
    /// Must be a class that can be constructed with a byte array and a length, or a unique pointer to a byte array
21
    /// and a length
22
    template <typename CryptoDecoder> class CryptoDataReader
23
    {
24
    public:
25
      /// Creates a decoder from DER-encoded data
26
      /// @param[in] derData Pointer to the DER-encoded data
27
      /// @param[in] derDataLen Length of the DER-encoded data
28
      /// @param[in] ownDerData If true, the decoder will take ownership of the data and free it when the
29
      /// decoder class is destructed
30
      /// @return A unique pointer to the created decoder
31
      /// @throws An exception if the data is not a valid ASN.1 record
32
      static std::unique_ptr<CryptoDecoder> fromDER(uint8_t* derData, size_t derDataLen, bool ownDerData = false)
33
0
      {
34
0
        return std::unique_ptr<CryptoDecoder>(new CryptoDecoder(derData, derDataLen, ownDerData));
35
0
      }
36
37
      /// Creates a decoder from a hex string containing DER-encoded data
38
      /// @param[in] derData Hex string containing DER-encoded data
39
      /// @return A unique pointer to the created decoder
40
      /// @throws An exception if the data is not a valid ASN.1 record
41
      static std::unique_ptr<CryptoDecoder> fromDER(const std::string& derData)
42
      {
43
        size_t derDataBufferLen = derData.length() / 2;
44
        auto derDataBuffer = std::make_unique<uint8_t[]>(derDataBufferLen);
45
        hexStringToByteArray(derData, derDataBuffer.get(), derDataBufferLen);
46
        return std::unique_ptr<CryptoDecoder>(new CryptoDecoder(std::move(derDataBuffer), derDataBufferLen));
47
      }
48
49
      /// Creates a decoder from a file containing DER-encoded data
50
      /// @param[in] derFileName Path to the file containing DER-encoded data
51
      /// @return A unique pointer to the created decoder
52
      /// @throws An exception if the file doesn't exist, cannot be read or contains invalid data
53
      static std::unique_ptr<CryptoDecoder> fromDERFile(const std::string& derFileName)
54
      {
55
        std::ifstream derFile(derFileName, std::ios::binary);
56
        if (!derFile.good())
57
        {
58
          throw std::runtime_error("DER file doesn't exist or cannot be opened");
59
        }
60
61
        derFile.seekg(0, std::ios::end);
62
        std::streamsize derDataLen = derFile.tellg();
63
        if (derDataLen < 0)
64
        {
65
          throw std::runtime_error("Failed to determine DER file size");
66
        }
67
        derFile.seekg(0, std::ios::beg);
68
69
        auto derData = std::make_unique<uint8_t[]>(derDataLen);
70
71
        if (!derFile.read(reinterpret_cast<char*>(derData.get()), derDataLen))
72
        {
73
          throw std::runtime_error("Failed to read DER file");
74
        }
75
        return std::unique_ptr<CryptoDecoder>(new CryptoDecoder(std::move(derData), derDataLen));
76
      }
77
78
      /// Creates a decoder from PEM-encoded data
79
      /// @param[in] pemData PEM-encoded data
80
      /// @return A unique pointer to the created decoder
81
      /// @throws std::invalid_argument exception if the data is not a valid PEM-encoded data
82
      static std::unique_ptr<CryptoDecoder> fromPEM(const std::string& pemData)
83
      {
84
        auto derData = PemCodec::decode(pemData, CryptoDecoder::pemLabel);
85
        auto derDataBuffer = std::make_unique<uint8_t[]>(derData.size());
86
        std::copy(derData.begin(), derData.end(), derDataBuffer.get());
87
        return std::unique_ptr<CryptoDecoder>(new CryptoDecoder(std::move(derDataBuffer), derData.size()));
88
      }
89
90
      /// Creates a decoder from a file containing PEM-encoded data
91
      /// @param[in] pemFileName Path to the file containing PEM-encoded data
92
      /// @return A unique pointer to the created decoder
93
      /// @throws std::runtime_error exception if the file doesn't exist or cannot be read
94
      /// @throws std::invalid_argument exception if the data is not a valid PEM-encoded data
95
      static std::unique_ptr<CryptoDecoder> fromPEMFile(const std::string& pemFileName)
96
      {
97
        std::ifstream pemFile(pemFileName, std::ios::in | std::ios::binary);
98
        if (!pemFile.good())
99
        {
100
          throw std::runtime_error("PEM file doesn't exist or cannot be opened");
101
        }
102
103
        pemFile.seekg(0, std::ios::end);
104
        std::streamsize pemContentLen = pemFile.tellg();
105
        if (pemContentLen < 0)
106
        {
107
          throw std::runtime_error("Failed to determine PEM file size");
108
        }
109
        pemFile.seekg(0, std::ios::beg);
110
111
        std::string pemContent;
112
        pemContent.resize(static_cast<std::size_t>(pemContentLen));
113
        if (!pemFile.read(&pemContent[0], pemContentLen))
114
        {
115
          throw std::runtime_error("Failed to read PEM file");
116
        }
117
118
        return fromPEM(pemContent);
119
      }
120
121
    protected:
122
      ~CryptoDataReader() = default;
123
    };
124
  }  // namespace internal
125
}  // namespace pcpp