Botan  2.11.0
Crypto and TLS for C++11
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< std::shared_ptr< const 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
 
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 71 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 93 of file ocsp.cpp.

94  {
95  m_dummy_response_status = status;
96  }

◆ 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 89 of file ocsp.h.

89  :
90  Response(response_bits.data(), response_bits.size())
91  {}

◆ 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 98 of file ocsp.cpp.

References Botan::BIT_STRING, Botan::CONSTRUCTED, Botan::CONTEXT_SPECIFIC, 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::OCTET_STRING, Botan::BER_Decoder::raw_bytes(), Botan::SEQUENCE, Botan::BER_Decoder::start_cons(), Botan::ASN1::to_string(), and Botan::UNIVERSAL.

98  :
99  m_response_bits(response_bits, response_bits + response_bits_len)
100  {
101  m_dummy_response_status = Certificate_Status_Code::OCSP_RESPONSE_INVALID;
102 
103  BER_Decoder response_outer = BER_Decoder(m_response_bits).start_cons(SEQUENCE);
104 
105  size_t resp_status = 0;
106 
107  response_outer.decode(resp_status, ENUMERATED, UNIVERSAL);
108 
109  /*
110  * FIXME: properly decode error responses
111  */
112  if(resp_status != 0)
113  throw Decoding_Error("OCSP response status " + std::to_string(resp_status));
114 
115  if(response_outer.more_items())
116  {
117  BER_Decoder response_bytes =
118  response_outer.start_cons(ASN1_Tag(0), CONTEXT_SPECIFIC).start_cons(SEQUENCE);
119 
120  response_bytes.decode_and_check(OID("1.3.6.1.5.5.7.48.1.1"),
121  "Unknown response type in OCSP response");
122 
123  BER_Decoder basicresponse =
124  BER_Decoder(response_bytes.get_next_octet_string()).start_cons(SEQUENCE);
125 
126  basicresponse.start_cons(SEQUENCE)
127  .raw_bytes(m_tbs_bits)
128  .end_cons()
129  .decode(m_sig_algo)
130  .decode(m_signature, BIT_STRING);
131  decode_optional_list(basicresponse, ASN1_Tag(0), m_certs);
132 
133  size_t responsedata_version = 0;
134  Extensions extensions;
135 
136  BER_Decoder(m_tbs_bits)
137  .decode_optional(responsedata_version, ASN1_Tag(0),
139 
140  .decode_optional(m_signer_name, ASN1_Tag(1),
142 
143  .decode_optional_string(m_key_hash, OCTET_STRING, 2,
145 
146  .decode(m_produced_at)
147 
148  .decode_list(m_responses)
149 
150  .decode_optional(extensions, ASN1_Tag(1),
152  }
153 
154  response_outer.end_cons();
155  }
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:213
ASN1_Tag
Definition: asn1_obj.h:23

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 161 of file ocsp.h.

161 { return m_certs; }

◆ check_signature()

Certificate_Status_Code Botan::OCSP::Response::check_signature ( const std::vector< Certificate_Store *> &  trust_roots,
const std::vector< std::shared_ptr< const 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 188 of file ocsp.cpp.

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().

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

◆ 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 123 of file ocsp.h.

123 { return m_produced_at; }

◆ raw_bits()

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

Definition at line 135 of file ocsp.h.

135 { 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 133 of file ocsp.h.

133 { 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 128 of file ocsp.h.

128 { return m_signer_name; }

◆ 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 271 of file ocsp.cpp.

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.

275  {
276  if(m_responses.empty())
277  { return m_dummy_response_status; }
278 
279  for(const auto& response : m_responses)
280  {
281  if(response.certid().is_id_for(issuer, subject))
282  {
283  X509_Time x509_ref_time(ref_time);
284 
285  if(response.cert_status() == 1)
287 
288  if(response.this_update() > x509_ref_time)
290 
291  if(response.next_update().time_is_set())
292  {
293  if(x509_ref_time > response.next_update())
295  }
296  else if(max_age > std::chrono::seconds::zero() && ref_time - response.this_update().to_std_timepoint() > max_age)
298 
299  if(response.cert_status() == 0)
301  else
303  }
304  }
305 
307  }

◆ 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 157 of file ocsp.cpp.

References Botan::DER_SEQUENCE, Botan::AlgorithmIdentifier::get_oid(), Botan::IEEE_1363, Botan::OIDS::lookup(), 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(), and Botan::PK_Verifier::verify_message().

Referenced by check_signature().

158  {
159  if (m_responses.empty())
160  return m_dummy_response_status;
161 
162  try
163  {
164  std::unique_ptr<Public_Key> pub_key(issuer.subject_public_key());
165 
166  const std::vector<std::string> sig_info =
167  split_on(OIDS::lookup(m_sig_algo.get_oid()), '/');
168 
169  if(sig_info.size() != 2 || sig_info[0] != pub_key->algo_name())
171 
172  std::string padding = sig_info[1];
173  Signature_Format format = (pub_key->message_parts() >= 2) ? DER_SEQUENCE : IEEE_1363;
174 
175  PK_Verifier verifier(*pub_key, padding, format);
176 
177  if(verifier.verify_message(ASN1::put_in_sequence(m_tbs_bits), m_signature))
179  else
181  }
182  catch(Exception&)
183  {
185  }
186  }
std::vector< std::string > split_on(const std::string &str, char delim)
Definition: parsing.cpp:144
Signature_Format
Definition: pubkey.h:28
std::vector< uint8_t > put_in_sequence(const std::vector< uint8_t > &contents)
Definition: asn1_obj.cpp:195
const OID & get_oid() const
Definition: alg_id.h:37
std::string lookup(const OID &oid)
Definition: oids.cpp:113

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