Coverage Report

Created: 2026-02-14 06:19

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/PcapPlusPlus/Packet++/src/PemCodec.cpp
Line
Count
Source
1
#include "PemCodec.h"
2
#include "GeneralUtils.h"
3
#include <sstream>
4
#include <iostream>
5
#include <algorithm>
6
7
namespace pcpp
8
{
9
  std::string PemCodec::encode(const std::vector<uint8_t>& data, const std::string& label)
10
0
  {
11
0
    if (label.empty())
12
0
    {
13
0
      throw std::invalid_argument("PEM label cannot be empty");
14
0
    }
15
16
0
    if (data.empty())
17
0
    {
18
0
      throw std::invalid_argument("PEM data cannot be empty");
19
0
    }
20
21
0
    auto base64Str = Base64::encode(data);
22
0
    std::ostringstream oss;
23
24
0
    oss << pemBegin << label << pemDelimiter << "\n";
25
26
0
    auto base64StrSize = base64Str.size();
27
0
    for (size_t i = 0; i < base64StrSize; i += lineLength)
28
0
    {
29
0
      auto len = base64StrSize - i < lineLength ? base64StrSize - i : lineLength;
30
0
      oss.write(&base64Str[i], len);
31
0
      oss.put('\n');
32
0
    }
33
34
0
    oss << pemEnd << label << pemDelimiter << "\n";
35
0
    return oss.str();
36
0
  }
37
38
  std::vector<uint8_t> PemCodec::decode(const std::string& pemData, const std::string& expectedLabel)
39
0
  {
40
0
    std::istringstream iss(pemData);
41
0
    std::string line;
42
0
    std::string base64Data;
43
0
    std::string beginLabel, endLabel;
44
0
    bool inBody = false;
45
46
0
    while (std::getline(iss, line))
47
0
    {
48
0
      line.erase(std::remove(line.begin(), line.end(), '\r'), line.end());
49
50
0
      if (line.find(pemBegin) == 0)
51
0
      {
52
0
        if (inBody)
53
0
        {
54
0
          throw std::invalid_argument("Unexpected BEGIN while already inside a PEM block");
55
0
        }
56
57
0
        beginLabel = line.substr(pemBeginLen, line.find(pemDelimiter, pemBeginLen) - pemBeginLen);
58
0
        if (beginLabel.empty())
59
0
        {
60
0
          throw std::invalid_argument("Invalid BEGIN label in PEM");
61
0
        }
62
63
0
        if (!expectedLabel.empty() && beginLabel != expectedLabel)
64
0
        {
65
0
          throw std::invalid_argument("Unexpected BEGIN label in PEM - expected '" + expectedLabel +
66
0
                                      "' but got '" + beginLabel + "'");
67
0
        }
68
69
0
        if (line.compare(line.size() - pemDelimiterLen, pemDelimiterLen, pemDelimiter) != 0)
70
0
        {
71
0
          throw std::invalid_argument("Invalid BEGIN suffix in PEM");
72
0
        }
73
74
0
        inBody = true;
75
0
        continue;
76
0
      }
77
78
0
      if (line.find(pemEnd) == 0)
79
0
      {
80
0
        if (!inBody)
81
0
        {
82
0
          throw std::invalid_argument("END found before BEGIN in PEM");
83
0
        }
84
85
0
        endLabel = line.substr(pemEndLen, line.find(pemDelimiter, pemEndLen) - pemEndLen);
86
0
        if (endLabel != beginLabel)
87
0
        {
88
0
          throw std::invalid_argument("BEGIN and END labels do not match in PEM");
89
0
        }
90
0
        break;
91
0
      }
92
93
0
      if (inBody && !line.empty())
94
0
      {
95
0
        base64Data += line;
96
0
      }
97
0
    }
98
99
0
    if (beginLabel.empty() || endLabel.empty())
100
0
    {
101
0
      throw std::invalid_argument("Missing BEGIN or END in PEM data");
102
0
    }
103
104
0
    if (base64Data.empty())
105
0
    {
106
0
      throw std::invalid_argument("No base64 content found in PEM data");
107
0
    }
108
109
0
    return Base64::decodeToByteVector(base64Data);
110
0
  }
111
}  // namespace pcpp