Botan 3.12.0
Crypto and TLS for C&
x509_cert_cache.h
Go to the documentation of this file.
1/*
2* (C) 2026 Jack Lloyd
3*
4* Botan is released under the Simplified BSD License (see license.txt)
5*/
6
7#ifndef BOTAN_X509_CERT_CACHE_H_
8#define BOTAN_X509_CERT_CACHE_H_
9
10#include <botan/x509cert.h>
11
12#include <botan/mutex.h>
13#include <array>
14#include <cstring>
15#include <span>
16#include <unordered_map>
17
18namespace Botan {
19
20class HashFunction;
21
22/**
23* A cache for X.509 certificates
24*
25* This is primarily useful for system certificate stores (Windows, macOS)
26* where repeated lookups via native APIs return raw DER bytes that must
27* be parsed each time. The cache deduplicates these by keying on the
28* SHA-256 hash of the DER encoding.
29*/
31 public:
32 /**
33 * @param max_entries maximum number of certificates to cache.
34 * When the cache is full, an entry is evicted to make room.
35 * If 0, caching is disabled entirely.
36 */
37 explicit X509_Certificate_Cache(size_t max_entries = 64);
38
39 /**
40 * Look up a certificate by its DER encoding, or parse and cache it.
41 *
42 * If a certificate with the same DER encoding (by SHA-256 hash) is
43 * already in the cache, returns a (cheap, shared_ptr-backed) copy.
44 * Otherwise, parses the DER encoding into an X509_Certificate,
45 * inserts it into the cache, and returns it.
46 *
47 * If the cache was constructed with max_entries == 0, always parses
48 * and never caches.
49 *
50 * @param encoding DER-encoded certificate
51 * @return the cached or newly parsed certificate
52 * @throws Decoding_Error if the encoding is not a valid certificate
53 */
54 X509_Certificate find_or_insert(std::span<const uint8_t> encoding);
55
56 private:
57 class DER_Hash final {
58 public:
59 static constexpr size_t LEN = 32;
60
61 auto operator<=>(const DER_Hash&) const = default;
62
63 size_t hash() const noexcept {
64 size_t h = 0;
65 std::memcpy(&h, m_hash.data(), sizeof(h));
66 return h;
67 }
68
69 private:
70 DER_Hash() : m_hash{} {}
71
72 friend class X509_Certificate_Cache;
73 std::array<uint8_t, LEN> m_hash;
74 };
75
76 struct DER_Hash_Fn {
77 size_t operator()(const DER_Hash& h) const noexcept { return h.hash(); }
78 };
79
80 size_t m_max_entries;
81 mutex_type m_mutex;
82 std::unordered_map<DER_Hash, X509_Certificate, DER_Hash_Fn> m_cache;
83};
84
85} // namespace Botan
86
87#endif
X509_Certificate find_or_insert(std::span< const uint8_t > encoding)
X509_Certificate_Cache(size_t max_entries=64)
noop_mutex mutex_type
Definition mutex.h:37
auto operator<=>(const Strong< T, Tags... > &lhs, const Strong< T, Tags... > &rhs)