Coverage Report

Created: 2026-01-16 06:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/botan/src/lib/x509/crl_ent.cpp
Line
Count
Source
1
/*
2
* CRL Entry
3
* (C) 1999-2010 Jack Lloyd
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7
8
#include <botan/x509_crl.h>
9
10
#include <botan/asn1_obj.h>
11
#include <botan/ber_dec.h>
12
#include <botan/bigint.h>
13
#include <botan/der_enc.h>
14
#include <botan/x509_ext.h>
15
#include <botan/x509cert.h>
16
17
namespace Botan {
18
19
struct CRL_Entry_Data {
20
      std::vector<uint8_t> m_serial;
21
      X509_Time m_time;
22
      CRL_Code m_reason = CRL_Code::Unspecified;
23
      Extensions m_extensions;
24
};
25
26
/*
27
* Create a CRL_Entry
28
*/
29
0
CRL_Entry::CRL_Entry(const X509_Certificate& cert, CRL_Code why) {
30
0
   m_data = std::make_shared<CRL_Entry_Data>();
31
0
   m_data->m_serial = cert.serial_number();
32
0
   m_data->m_time = X509_Time(std::chrono::system_clock::now());
33
0
   m_data->m_reason = why;
34
35
0
   if(why != CRL_Code::Unspecified) {
36
0
      m_data->m_extensions.add(std::make_unique<Cert_Extension::CRL_ReasonCode>(why));
37
0
   }
38
0
}
39
40
/*
41
* Compare two CRL_Entry structs for equality
42
*/
43
0
bool operator==(const CRL_Entry& a1, const CRL_Entry& a2) {
44
0
   if(a1.serial_number() != a2.serial_number()) {
45
0
      return false;
46
0
   }
47
0
   if(a1.expire_time() != a2.expire_time()) {
48
0
      return false;
49
0
   }
50
0
   if(a1.reason_code() != a2.reason_code()) {
51
0
      return false;
52
0
   }
53
0
   return true;
54
0
}
55
56
/*
57
* Compare two CRL_Entry structs for inequality
58
*/
59
0
bool operator!=(const CRL_Entry& a1, const CRL_Entry& a2) {
60
0
   return !(a1 == a2);
61
0
}
62
63
/*
64
* DER encode a CRL_Entry
65
*/
66
0
void CRL_Entry::encode_into(DER_Encoder& der) const {
67
0
   der.start_sequence()
68
0
      .encode(BigInt::from_bytes(serial_number()))
69
0
      .encode(expire_time())
70
0
      .start_sequence()
71
0
      .encode(extensions())
72
0
      .end_cons()
73
0
      .end_cons();
74
0
}
75
76
namespace {
77
78
4.88k
std::vector<uint8_t> decode_serial_number(const BER_Object& obj) {
79
4.88k
   obj.assert_is_a(ASN1_Type::Integer, ASN1_Class::Universal);
80
81
4.88k
   if(!obj.data().empty() && obj.data()[0] == 0x00) {
82
336
      return std::vector<uint8_t>(obj.data().begin() + 1, obj.data().end());
83
4.55k
   } else if(!obj.data().empty() && ((obj.data()[0] & 0x80) == 0x80)) {
84
638
      std::vector<uint8_t> vec(obj.data().begin(), obj.data().end());
85
965
      for(size_t i = vec.size(); i > 0; --i) {
86
965
         const bool gt0 = vec[i - 1] > 0;
87
965
         vec[i - 1] -= 1;
88
965
         if(gt0) {
89
638
            break;
90
638
         }
91
965
      }
92
12.1k
      for(auto& b : vec) {
93
12.1k
         b = ~b;
94
12.1k
      }
95
96
638
      return vec;
97
3.91k
   } else {
98
3.91k
      return std::vector<uint8_t>(obj.data().begin(), obj.data().end());
99
3.91k
   }
100
4.88k
}
101
102
}  // namespace
103
104
/*
105
* Decode a BER encoded CRL_Entry
106
*/
107
5.06k
void CRL_Entry::decode_from(BER_Decoder& source) {
108
5.06k
   auto data = std::make_unique<CRL_Entry_Data>();
109
110
5.06k
   BER_Decoder entry = source.start_sequence();
111
112
5.06k
   data->m_serial = decode_serial_number(entry.get_next_object());
113
114
5.06k
   entry.decode(data->m_time);
115
116
5.06k
   if(entry.more_items()) {
117
3.98k
      entry.decode(data->m_extensions);
118
3.98k
      if(const auto* ext = data->m_extensions.get_extension_object_as<Cert_Extension::CRL_ReasonCode>()) {
119
90
         data->m_reason = ext->get_reason();
120
3.89k
      } else {
121
3.89k
         data->m_reason = CRL_Code::Unspecified;
122
3.89k
      }
123
3.98k
   }
124
125
5.06k
   entry.end_cons();
126
127
5.06k
   m_data = std::move(data);
128
5.06k
}
129
130
0
const CRL_Entry_Data& CRL_Entry::data() const {
131
0
   if(!m_data) {
132
0
      throw Invalid_State("CRL_Entry_Data uninitialized");
133
0
   }
134
135
0
   return *m_data;
136
0
}
137
138
0
const std::vector<uint8_t>& CRL_Entry::serial_number() const {
139
0
   return data().m_serial;
140
0
}
141
142
0
const X509_Time& CRL_Entry::expire_time() const {
143
0
   return data().m_time;
144
0
}
145
146
0
CRL_Code CRL_Entry::reason_code() const {
147
0
   return data().m_reason;
148
0
}
149
150
0
const Extensions& CRL_Entry::extensions() const {
151
0
   return data().m_extensions;
152
0
}
153
154
}  // namespace Botan