Coverage Report

Created: 2025-04-11 06:34

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