summaryrefslogtreecommitdiffstats
path: root/comm/third_party/botan/src/lib/psk_db/psk_db.h
blob: 06358935c136ea19d8e9dbfc07df55eaef45038e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/*
* (C) 2017 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#ifndef BOTAN_PSK_DB_H_
#define BOTAN_PSK_DB_H_

#include <botan/secmem.h>
#include <memory>
#include <string>
#include <set>

namespace Botan {

class BlockCipher;
class MessageAuthenticationCode;

/**
* This is an interface to a generic PSK (pre-shared key) database.
* It might be implemented as a plaintext storage or via some mechanism
* that encrypts the keys and/or values.
*/
class BOTAN_PUBLIC_API(2,4) PSK_Database
   {
   public:
      /**
      * Return the set of names for which get() will return a value.
      */
      virtual std::set<std::string> list_names() const = 0;

      /**
      * Return the value associated with the specified @param name or otherwise
      * throw an exception.
      */
      virtual secure_vector<uint8_t> get(const std::string& name) const = 0;

      /**
      * Set a value that can later be accessed with get().
      * If name already exists in the database, the old value will be overwritten.
      */
      virtual void set(const std::string& name, const uint8_t psk[], size_t psk_len) = 0;

      /**
      * Remove a PSK from the database
      */
      virtual void remove(const std::string& name) = 0;

      /**
      * Returns if the values in the PSK database are encrypted. If
      * false, saved values are being stored in plaintext.
      */
      virtual bool is_encrypted() const = 0;

      /**
      * Get a PSK in the form of a string (eg if the PSK is a password)
      */
      std::string get_str(const std::string& name) const
         {
         secure_vector<uint8_t> psk = get(name);
         return std::string(cast_uint8_ptr_to_char(psk.data()), psk.size());
         }

      void set_str(const std::string& name, const std::string& psk)
         {
         set(name, cast_char_ptr_to_uint8(psk.data()), psk.size());
         }

      template<typename Alloc>
      void set_vec(const std::string& name,
                   const std::vector<uint8_t, Alloc>& psk)

         {
         set(name, psk.data(), psk.size());
         }

      virtual ~PSK_Database() = default;
   };

/**
* A mixin for an encrypted PSK database.
* Both keys and values are encrypted with NIST AES-256 key wrapping.
* Values are padded to obscure their length before encryption, allowing
* it to be used as a password vault.
*
* Subclasses must implement the virtual calls to handle storing and
* getting raw (base64 encoded) values.
*/
class BOTAN_PUBLIC_API(2,4) Encrypted_PSK_Database : public PSK_Database
   {
   public:
      /**
      * @param master_key specifies the master key used to encrypt all
      * keys and value. It can be of any length, but should be at least 256 bits.
      *
      * Subkeys for the cryptographic algorithms used are derived from this
      * master key. No key stretching is performed; if encrypting a PSK database
      * using a password, it is recommended to use PBKDF2 to derive the database
      * master key.
      */
      Encrypted_PSK_Database(const secure_vector<uint8_t>& master_key);

      ~Encrypted_PSK_Database();

      std::set<std::string> list_names() const override;

      secure_vector<uint8_t> get(const std::string& name) const override;

      void set(const std::string& name, const uint8_t psk[], size_t psk_len) override;

      void remove(const std::string& name) override;

      bool is_encrypted() const override { return true; }

   protected:
      /**
      * Save a encrypted (name.value) pair to the database. Both will be base64 encoded strings.
      */
      virtual void kv_set(const std::string& index, const std::string& value) = 0;

      /**
      * Get a value previously saved with set_raw_value. Should return an empty
      * string if index is not found.
      */
      virtual std::string kv_get(const std::string& index) const = 0;

      /**
      * Remove an index
      */
      virtual void kv_del(const std::string& index) = 0;

      /**
      * Return all indexes in the table.
      */
      virtual std::set<std::string> kv_get_all() const = 0;

   private:
      std::unique_ptr<BlockCipher> m_cipher;
      std::unique_ptr<MessageAuthenticationCode> m_hmac;
      secure_vector<uint8_t> m_wrap_key;
   };

class SQL_Database;

class BOTAN_PUBLIC_API(2,4) Encrypted_PSK_Database_SQL : public Encrypted_PSK_Database
   {
   public:
      Encrypted_PSK_Database_SQL(const secure_vector<uint8_t>& master_key,
                                 std::shared_ptr<SQL_Database> db,
                                 const std::string& table_name);

      ~Encrypted_PSK_Database_SQL();
   private:
      void kv_set(const std::string& index, const std::string& value) override;
      std::string kv_get(const std::string& index) const override;
      void kv_del(const std::string& index) override;
      std::set<std::string> kv_get_all() const override;

      std::shared_ptr<SQL_Database> m_db;
      const std::string m_table_name;
   };

}

#endif