Botan 3.13.0
Crypto and TLS for C&
psk_db.h
Go to the documentation of this file.
1/*
2* (C) 2017 Jack Lloyd
3*
4* Botan is released under the Simplified BSD License (see license.txt)
5*/
6
7#ifndef BOTAN_PSK_DB_H_
8#define BOTAN_PSK_DB_H_
9
10#include <botan/secmem.h>
11#include <memory>
12#include <set>
13#include <span>
14#include <string>
15
16namespace Botan {
17
18class BlockCipher;
20
21/**
22* This is an interface to a generic PSK (pre-shared key) database.
23* It might be implemented as a plaintext storage or via some mechanism
24* that encrypts the keys and/or values.
25*/
26class BOTAN_PUBLIC_API(2, 4) PSK_Database /* NOLINT(*-special-member-functions) */ {
27 public:
28 /**
29 * List the names stored in the database
30 * @returns the set of names for which get() will return a value.
31 */
32 virtual std::set<std::string> list_names() const = 0;
33
34 /**
35 * Retrieve a PSK from the database
36 * @returns the value associated with the specified @p name or otherwise
37 * throw an exception.
38 */
39 virtual secure_vector<uint8_t> get(std::string_view name) const = 0;
40
41 /**
42 * Set a value that can later be accessed with get().
43 * If name already exists in the database, the old value will be overwritten.
44 */
45 virtual void set(std::string_view name, const uint8_t psk[], size_t psk_len) = 0;
46
47 /**
48 * Remove the PSK with the given @p name from the database
49 */
50 virtual void remove(std::string_view name) = 0;
51
52 /**
53 * Test whether values in this database are stored encrypted
54 * @returns true if the values in the PSK database are encrypted. If false,
55 * saved values are being stored in plaintext.
56 */
57 virtual bool is_encrypted() const = 0;
58
59 /**
60 * Get a PSK in the form of a string (eg if the PSK is a password)
61 */
62 std::string get_str(std::string_view name) const;
63
64 /**
65 * Like set() but accepts the PSK as a string (eg for a password).
66 */
67 void set_str(std::string_view name, std::string_view psk);
68
69 /**
70 * Like set() but accepting an arbitrary contiguous byte array.
71 */
72 void set_vec(std::string_view name, std::span<const uint8_t> psk) { set(name, psk.data(), psk.size()); }
73
74 virtual ~PSK_Database() = default;
75};
76
77/**
78* A mixin for an encrypted PSK database.
79*
80* Both names and values are encrypted using NIST key wrapping (see NIST
81* SP800-38F) with AES-256. First the master key is used with HMAC(SHA-256) to
82* derive two 256-bit keys, one for encrypting all names and the other to key an
83* instance of HMAC(SHA-256). Values are each encrypted under an individual key
84* created by hashing the encrypted name with HMAC. This associates the encrypted
85* key with the name, and prevents an attacker with write access to the data
86* store from taking an encrypted key associated with one entity and copying it
87* to another entity.
88*
89* Names and PSKs are both padded to the next multiple of 8 bytes, providing some
90* obfuscation of the length.
91*
92* Subclasses must implement the virtual calls to handle storing and getting raw
93* (base64 encoded) values.
94*/
95class BOTAN_PUBLIC_API(2, 4) Encrypted_PSK_Database : public PSK_Database /* NOLINT(*-special-member-functions) */ {
96 public:
97 /**
98 * Initializes or opens a PSK database. The @p master_key is used to secure
99 * the contents. It may be of any length. If encrypting PSKs under a
100 * passphrase, use a suitable key derivation scheme (such as Argon2id) to
101 * derive the secret key. If the master key is lost, all PSKs stored are
102 * unrecoverable.
103 *
104 * One artifact of the names being encrypted is that is is possible to use
105 * multiple different master keys with the same underlying storage. Each
106 * master key will be responsible for a subset of the keys. An attacker who
107 * knows one of the keys will be able to tell there are other values
108 * encrypted under another key, but will not be able to tell how many other
109 * master keys are in use.
110 *
111 * @param master_key specifies the master key used to encrypt all
112 * keys and value. It can be of any length, but should be at least 256 bits.
113 *
114 * Subkeys for the cryptographic algorithms used are derived from this
115 * master key. No key stretching is performed; if encrypting a PSK database
116 * using a password, it is recommended to use Argon2id to derive the database
117 * master key.
118 */
120
122
123 /**
124 * List the names stored in the database
125 * @return the set of names for which get() will return a value
126 */
127 std::set<std::string> list_names() const override;
128
129 /**
130 * Retrieve a PSK from the database
131 * @param name the name of the PSK to retrieve
132 * @return the value associated with name, or throw if not found
133 */
134 secure_vector<uint8_t> get(std::string_view name) const override;
135
136 /**
137 * Set a value that can later be accessed with get()
138 * If name already exists in the database, the old value will be overwritten.
139 * @param name the name to store the PSK under
140 * @param psk the PSK to store
141 * @param psk_len length of psk in bytes
142 */
143 void set(std::string_view name, const uint8_t psk[], size_t psk_len) override;
144
145 /**
146 * Remove the PSK with the given name from the database
147 * @param name the name of the PSK to remove
148 */
149 void remove(std::string_view name) override;
150
151 /**
152 * Test whether values in this database are stored encrypted
153 * @return always true for this type
154 */
155 bool is_encrypted() const override { return true; }
156
157 protected:
158 /**
159 * Save a encrypted (name/value) pair to the database. Both will be base64
160 * encoded strings.
161 */
162 virtual void kv_set(std::string_view index, std::string_view value) = 0;
163
164 /**
165 * Get a value previously saved with kv_set(). Should return an empty
166 * string if @p index is not found.
167 */
168 virtual std::string kv_get(std::string_view index) const = 0;
169
170 /**
171 * Remove an @p index
172 */
173 virtual void kv_del(std::string_view index) = 0;
174
175 /**
176 * Return all indexes in the table (ie values for which ``kv_get`` will
177 * return a non-empty string)
178 */
179 virtual std::set<std::string> kv_get_all() const = 0;
180
181 private:
182 std::unique_ptr<BlockCipher> m_cipher;
183 std::unique_ptr<MessageAuthenticationCode> m_hmac;
184};
185
186class SQL_Database;
187
188/**
189* An Encrypted_PSK_Database which stores its key/value pairs in a SQL table
190*/
192 public:
193 /**
194 * Creates or uses the named table in @p db. The SQL schema of the table is
195 * `(psk_name TEXT PRIMARY KEY, psk_value TEXT)`.
196 */
198 std::shared_ptr<SQL_Database> db,
199 std::string_view table_name);
200
202
207
208 private:
209 void kv_set(std::string_view index, std::string_view value) override;
210 std::string kv_get(std::string_view index) const override;
211 void kv_del(std::string_view index) override;
212 std::set<std::string> kv_get_all() const override;
213
214 std::shared_ptr<SQL_Database> m_db;
215 const std::string m_table_name;
216};
217
218} // namespace Botan
219
220#endif
#define BOTAN_PUBLIC_API(maj, min)
Definition api.h:21
#define BOTAN_FUTURE_EXPLICIT
Definition api.h:52
Encrypted_PSK_Database_SQL & operator=(const Encrypted_PSK_Database_SQL &other)=delete
Encrypted_PSK_Database_SQL(const Encrypted_PSK_Database_SQL &other)=delete
Encrypted_PSK_Database_SQL(const secure_vector< uint8_t > &master_key, std::shared_ptr< SQL_Database > db, std::string_view table_name)
Encrypted_PSK_Database_SQL & operator=(Encrypted_PSK_Database_SQL &&other)=delete
Encrypted_PSK_Database_SQL(Encrypted_PSK_Database_SQL &&other)=delete
bool is_encrypted() const override
Definition psk_db.h:155
virtual void kv_set(std::string_view index, std::string_view value)=0
virtual void kv_del(std::string_view index)=0
virtual std::string kv_get(std::string_view index) const =0
secure_vector< uint8_t > get(std::string_view name) const override
Definition psk_db.cpp:62
BOTAN_FUTURE_EXPLICIT Encrypted_PSK_Database(const secure_vector< uint8_t > &master_key)
Definition psk_db.cpp:27
std::set< std::string > list_names() const override
Definition psk_db.cpp:38
virtual std::set< std::string > kv_get_all() const =0
void remove(std::string_view name) override
Definition psk_db.cpp:56
void set(std::string_view name, const uint8_t psk[], size_t psk_len) override
Definition psk_db.cpp:79
void set_str(std::string_view name, std::string_view psk)
Definition psk_db.cpp:22
virtual std::set< std::string > list_names() const =0
virtual void set(std::string_view name, const uint8_t psk[], size_t psk_len)=0
void set_vec(std::string_view name, std::span< const uint8_t > psk)
Definition psk_db.h:72
virtual bool is_encrypted() const =0
std::string get_str(std::string_view name) const
Definition psk_db.cpp:18
virtual ~PSK_Database()=default
virtual secure_vector< uint8_t > get(std::string_view name) const =0
virtual void remove(std::string_view name)=0
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:128