Botan 3.0.0-alpha0
Crypto and TLS for C&
Public Member Functions | List of all members
Botan::OCSP::Response Class Referencefinal

#include <ocsp.h>

Public Member Functions

const std::vector< X509_Certificate > & certificates () const
 
Certificate_Status_Code check_signature (const std::vector< Certificate_Store * > &trust_roots, const std::vector< X509_Certificate > &cert_path={}) const
 
const X509_Timeproduced_at () const
 
const std::vector< uint8_t > & raw_bits () const
 
 Response ()=default
 
 Response (Certificate_Status_Code status)
 
 Response (const std::vector< uint8_t > &response_bits)
 
 Response (const uint8_t response_bits[], size_t response_bits_len)
 
const std::vector< uint8_t > & signer_key_hash () const
 
const X509_DNsigner_name () const
 
Response_Status_Code status () const
 
Certificate_Status_Code status_for (const X509_Certificate &issuer, const X509_Certificate &subject, std::chrono::system_clock::time_point ref_time=std::chrono::system_clock::now(), std::chrono::seconds max_age=std::chrono::seconds::zero()) const
 
Certificate_Status_Code verify_signature (const X509_Certificate &issuer) const
 

Detailed Description

OCSP response.

Note this class is only usable as an OCSP client

Definition at line 131 of file ocsp.h.

Constructor & Destructor Documentation

◆ Response() [1/4]

Botan::OCSP::Response::Response ( )
default

Creates an empty OCSP response.

◆ Response() [2/4]

Botan::OCSP::Response::Response ( Certificate_Status_Code  status)

Create a fake OCSP response from a given status code.

Parameters
statusthe status code the check functions will return

Definition at line 91 of file ocsp.cpp.

92 {
94 m_dummy_response_status = status;
95 }
Response_Status_Code status() const
Definition: ocsp.h:183

References status(), and Botan::OCSP::Successful.

◆ Response() [3/4]

Botan::OCSP::Response::Response ( const std::vector< uint8_t > &  response_bits)
inline

Parses an OCSP response.

Parameters
response_bitsresponse bits received

Definition at line 149 of file ocsp.h.

149 :
150 Response(response_bits.data(), response_bits.size())
151 {}

◆ Response() [4/4]

Botan::OCSP::Response::Response ( const uint8_t  response_bits[],
size_t  response_bits_len 
)

Parses an OCSP response.

Parameters
response_bitsresponse bits received
response_bits_lenlength of response in bytes

Definition at line 97 of file ocsp.cpp.

97 :
98 m_response_bits(response_bits, response_bits + response_bits_len)
99 {
100 m_dummy_response_status = Certificate_Status_Code::OCSP_RESPONSE_INVALID;
101
102 BER_Decoder response_outer = BER_Decoder(m_response_bits).start_sequence();
103
104 size_t resp_status = 0;
105
106 response_outer.decode(resp_status, ASN1_Type::Enumerated, ASN1_Class::Universal);
107
108 m_status = static_cast<Response_Status_Code>(resp_status);
109
111 { return; }
112
113 if(response_outer.more_items())
114 {
115 BER_Decoder response_bytes =
116 response_outer.start_context_specific(0).start_sequence();
117
118 response_bytes.decode_and_check(OID("1.3.6.1.5.5.7.48.1.1"),
119 "Unknown response type in OCSP response");
120
121 BER_Decoder basicresponse =
122 BER_Decoder(response_bytes.get_next_octet_string()).start_sequence();
123
124 basicresponse.start_sequence()
125 .raw_bytes(m_tbs_bits)
126 .end_cons()
127 .decode(m_sig_algo)
128 .decode(m_signature, ASN1_Type::BitString);
129 decode_optional_list(basicresponse, ASN1_Type(0), m_certs);
130
131 size_t responsedata_version = 0;
132 Extensions extensions;
133
134 BER_Decoder(m_tbs_bits)
135 .decode_optional(responsedata_version, ASN1_Type(0),
137
138 .decode_optional(m_signer_name, ASN1_Type(1),
140
141 .decode_optional_string(m_key_hash, ASN1_Type::OctetString, 2,
143
144 .decode(m_produced_at)
145
146 .decode_list(m_responses)
147
148 .decode_optional(extensions, ASN1_Type(1),
150 }
151
152 response_outer.end_cons();
153 }
Response_Status_Code
Definition: ocsp.h:117
ASN1_Type
Definition: asn1_obj.h:39

References Botan::BitString, Botan::Constructed, Botan::ContextSpecific, Botan::BER_Decoder::decode(), Botan::BER_Decoder::decode_and_check(), Botan::BER_Decoder::decode_list(), Botan::BER_Decoder::decode_optional(), Botan::BER_Decoder::decode_optional_string(), Botan::BER_Decoder::end_cons(), Botan::Enumerated, Botan::BER_Decoder::get_next_octet_string(), Botan::BER_Decoder::more_items(), Botan::OCSP_RESPONSE_INVALID, Botan::OctetString, Botan::BER_Decoder::raw_bytes(), Botan::BER_Decoder::start_context_specific(), Botan::BER_Decoder::start_sequence(), Botan::OCSP::Successful, and Botan::Universal.

Member Function Documentation

◆ certificates()

const std::vector< X509_Certificate > & Botan::OCSP::Response::certificates ( ) const
inline
Returns
the certificate chain, if provided in response

Definition at line 226 of file ocsp.h.

226{ return m_certs; }

◆ check_signature()

Certificate_Status_Code Botan::OCSP::Response::check_signature ( const std::vector< Certificate_Store * > &  trust_roots,
const std::vector< X509_Certificate > &  cert_path = {} 
) const

Check signature and return status The optional cert_path is the (already validated!) certificate path of the end entity which is being inquired about

Parameters
trust_rootslist of certstores containing trusted roots
cert_pathoptionally, the (already verified!) certificate path for the certificate this is an OCSP response for. This is necessary to find the correct intermediate CA in some cases.

Definition at line 186 of file ocsp.cpp.

188 {
189 if (m_responses.empty())
190 return m_dummy_response_status;
191
192 std::optional<X509_Certificate> signing_cert;
193
194 for(const auto& trusted_root : trusted_roots)
195 {
196 if(m_signer_name.empty() && m_key_hash.empty())
198
199 if(!m_signer_name.empty())
200 {
201 signing_cert = trusted_root->find_cert(m_signer_name, std::vector<uint8_t>());
202 if(signing_cert)
203 {
204 break;
205 }
206 }
207
208 if(!m_key_hash.empty())
209 {
210 signing_cert = trusted_root->find_cert_by_pubkey_sha1(m_key_hash);
211 if(signing_cert)
212 {
213 break;
214 }
215 }
216 }
217
218 if(!signing_cert && ee_cert_path.size() > 1)
219 {
220 // End entity cert is not allowed to sign their own OCSP request :)
221 for(size_t i = 1; i < ee_cert_path.size(); ++i)
222 {
223 // Check all CA certificates in the (assumed validated) EE cert path
224 if(!m_signer_name.empty() && ee_cert_path[i].subject_dn() == m_signer_name)
225 {
226 signing_cert = ee_cert_path[i];
227 break;
228 }
229
230 if(!m_key_hash.empty() && ee_cert_path[i].subject_public_key_bitstring_sha1() == m_key_hash)
231 {
232 signing_cert = ee_cert_path[i];
233 break;
234 }
235 }
236 }
237
238 if(!signing_cert && !m_certs.empty())
239 {
240 for(const auto& cert : m_certs)
241 {
242 // Check all CA certificates in the (assumed validated) EE cert path
243 if(!m_signer_name.empty() && cert.subject_dn() == m_signer_name)
244 {
245 signing_cert = cert;
246 break;
247 }
248
249 if(!m_key_hash.empty() && cert.subject_public_key_bitstring_sha1() == m_key_hash)
250 {
251 signing_cert = cert;
252 break;
253 }
254 }
255 }
256
257 if(!signing_cert)
259
260 if(!signing_cert->allowed_usage(CRL_SIGN) &&
261 !signing_cert->allowed_extended_usage("PKIX.OCSPSigning"))
262 {
264 }
265
266 return this->verify_signature(*signing_cert);
267 }
Certificate_Status_Code verify_signature(const X509_Certificate &issuer) const
Definition: ocsp.cpp:155
bool empty() const
Definition: pkix_types.h:71
@ CRL_SIGN
Definition: pkix_enums.h:110

References Botan::CRL_SIGN, Botan::X509_DN::empty(), Botan::OCSP_ISSUER_NOT_FOUND, Botan::OCSP_RESPONSE_INVALID, Botan::OCSP_RESPONSE_MISSING_KEYUSAGE, and verify_signature().

◆ produced_at()

const X509_Time & Botan::OCSP::Response::produced_at ( ) const
inline
Returns
the time this OCSP response was supposedly produced at

Definition at line 188 of file ocsp.h.

188{ return m_produced_at; }

◆ raw_bits()

const std::vector< uint8_t > & Botan::OCSP::Response::raw_bits ( ) const
inline

Definition at line 200 of file ocsp.h.

200{ return m_response_bits; }

◆ signer_key_hash()

const std::vector< uint8_t > & Botan::OCSP::Response::signer_key_hash ( ) const
inline
Returns
key hash, if provided in response (may be empty)

Definition at line 198 of file ocsp.h.

198{ return m_key_hash; }

◆ signer_name()

const X509_DN & Botan::OCSP::Response::signer_name ( ) const
inline
Returns
DN of signer, if provided in response (may be empty)

Definition at line 193 of file ocsp.h.

193{ return m_signer_name; }

◆ status()

Response_Status_Code Botan::OCSP::Response::status ( ) const
inline
Returns
the status of the response

Definition at line 183 of file ocsp.h.

183{ return m_status; }

Referenced by Response().

◆ status_for()

Certificate_Status_Code Botan::OCSP::Response::status_for ( const X509_Certificate issuer,
const X509_Certificate subject,
std::chrono::system_clock::time_point  ref_time = std::chrono::system_clock::now(),
std::chrono::seconds  max_age = std::chrono::seconds::zero() 
) const

Searches the OCSP response for issuer and subject certificate.

Parameters
issuerissuer certificate
subjectsubject certificate
ref_timethe reference time
max_agethe maximum age the response should be considered valid if next_update is not set
Returns
OCSP status code, possible values: CERT_IS_REVOKED, OCSP_NOT_YET_VALID, OCSP_HAS_EXPIRED, OCSP_IS_TOO_OLD, OCSP_RESPONSE_GOOD, OCSP_BAD_STATUS, OCSP_CERT_NOT_LISTED

Definition at line 269 of file ocsp.cpp.

273 {
274 if(m_responses.empty())
275 { return m_dummy_response_status; }
276
277 for(const auto& response : m_responses)
278 {
279 if(response.certid().is_id_for(issuer, subject))
280 {
281 X509_Time x509_ref_time(ref_time);
282
283 if(response.cert_status() == 1)
285
286 if(response.this_update() > x509_ref_time)
288
289 if(response.next_update().time_is_set())
290 {
291 if(x509_ref_time > response.next_update())
293 }
294 else if(max_age > std::chrono::seconds::zero() && ref_time - response.this_update().to_std_timepoint() > max_age)
296
297 if(response.cert_status() == 0)
299 else
301 }
302 }
303
305 }
ASN1_Time X509_Time
Definition: asn1_obj.h:389

References Botan::CERT_IS_REVOKED, Botan::OCSP_BAD_STATUS, Botan::OCSP_CERT_NOT_LISTED, Botan::OCSP_HAS_EXPIRED, Botan::OCSP_IS_TOO_OLD, Botan::OCSP_NOT_YET_VALID, and Botan::OCSP_RESPONSE_GOOD.

◆ verify_signature()

Certificate_Status_Code Botan::OCSP::Response::verify_signature ( const X509_Certificate issuer) const

Verify that issuer's key signed this response

Parameters
issuercertificate of issuer
Returns
if signature valid OCSP_SIGNATURE_OK else an error code

Definition at line 155 of file ocsp.cpp.

156 {
157 if (m_responses.empty())
158 return m_dummy_response_status;
159
160 try
161 {
162 std::unique_ptr<Public_Key> pub_key(issuer.subject_public_key());
163
164 const std::vector<std::string> sig_info =
165 split_on(m_sig_algo.get_oid().to_formatted_string(), '/');
166
167 if(sig_info.size() != 2 || sig_info[0] != pub_key->algo_name())
169
170 std::string padding = sig_info[1];
171 const Signature_Format format = pub_key->default_x509_signature_format();
172
173 PK_Verifier verifier(*pub_key, padding, format);
174
175 if(verifier.verify_message(ASN1::put_in_sequence(m_tbs_bits), m_signature))
177 else
179 }
180 catch(Exception&)
181 {
183 }
184 }
const OID & get_oid() const
Definition: asn1_obj.h:447
std::string to_formatted_string() const
Definition: asn1_oid.cpp:109
std::vector< uint8_t > put_in_sequence(const std::vector< uint8_t > &contents)
Definition: asn1_obj.cpp:191
std::vector< std::string > split_on(const std::string &str, char delim)
Definition: parsing.cpp:111
Signature_Format
Definition: pk_keys.h:23

References Botan::AlgorithmIdentifier::get_oid(), Botan::OCSP_RESPONSE_INVALID, Botan::OCSP_SIGNATURE_ERROR, Botan::OCSP_SIGNATURE_OK, Botan::ASN1::put_in_sequence(), Botan::split_on(), Botan::X509_Certificate::subject_public_key(), Botan::OID::to_formatted_string(), and Botan::PK_Verifier::verify_message().

Referenced by check_signature().


The documentation for this class was generated from the following files: