Botan  2.7.0
Crypto and TLS for C++11
psk_db.cpp
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 #include <botan/psk_db.h>
8 #include <botan/exceptn.h>
9 #include <botan/nist_keywrap.h>
10 #include <botan/base64.h>
11 #include <botan/mac.h>
12 #include <botan/block_cipher.h>
13 
14 namespace Botan {
15 
17  {
18  m_cipher = BlockCipher::create_or_throw("AES-256");
19  m_hmac = MessageAuthenticationCode::create_or_throw("HMAC(SHA-256)");
20  m_hmac->set_key(master_key);
21 
22  m_cipher->set_key(m_hmac->process("wrap"));
23  m_hmac->set_key(m_hmac->process("hmac"));
24  }
25 
27  {
28  // for ~unique_ptr
29  }
30 
31 std::set<std::string> Encrypted_PSK_Database::list_names() const
32  {
33  const std::set<std::string> encrypted_names = kv_get_all();
34 
35  std::set<std::string> names;
36 
37  for(std::string enc_name : encrypted_names)
38  {
39  try
40  {
41  const secure_vector<uint8_t> raw_name = base64_decode(enc_name);
42  const secure_vector<uint8_t> name_bits =
43  nist_key_unwrap_padded(raw_name.data(), raw_name.size(), *m_cipher);
44 
45  std::string pt_name(cast_uint8_ptr_to_char(name_bits.data()), name_bits.size());
46  names.insert(pt_name);
47  }
48  catch(Integrity_Failure&)
49  {
50  }
51  }
52 
53  return names;
54  }
55 
56 void Encrypted_PSK_Database::remove(const std::string& name)
57  {
58  const std::vector<uint8_t> wrapped_name =
60  name.size(),
61  *m_cipher);
62 
63  this->kv_del(base64_encode(wrapped_name));
64  }
65 
67  {
68  const std::vector<uint8_t> wrapped_name =
70  name.size(),
71  *m_cipher);
72 
73  const std::string val_base64 = kv_get(base64_encode(wrapped_name));
74 
75  if(val_base64.empty())
76  throw Invalid_Argument("Named PSK not located");
77 
78  const secure_vector<uint8_t> val = base64_decode(val_base64);
79 
80  std::unique_ptr<BlockCipher> wrap_cipher(m_cipher->clone());
81  wrap_cipher->set_key(m_hmac->process(wrapped_name));
82 
83  return nist_key_unwrap_padded(val.data(), val.size(), *wrap_cipher);
84  }
85 
86 void Encrypted_PSK_Database::set(const std::string& name, const uint8_t val[], size_t len)
87  {
88  /*
89  * Both as a basic precaution wrt key seperation, and specifically to prevent
90  * cut-and-paste attacks against the database, each PSK is encrypted with a
91  * distinct key which is derived by hashing the wrapped key name with HMAC.
92  */
93  const std::vector<uint8_t> wrapped_name =
95  name.size(),
96  *m_cipher);
97 
98  std::unique_ptr<BlockCipher> wrap_cipher(m_cipher->clone());
99  wrap_cipher->set_key(m_hmac->process(wrapped_name));
100  const std::vector<uint8_t> wrapped_key = nist_key_wrap_padded(val, len, *wrap_cipher);
101 
102  this->kv_set(base64_encode(wrapped_name), base64_encode(wrapped_key));
103  }
104 
105 }
Encrypted_PSK_Database(const secure_vector< uint8_t > &master_key)
Definition: psk_db.cpp:16
secure_vector< uint8_t > get(const std::string &name) const override
Definition: psk_db.cpp:66
const uint8_t * cast_char_ptr_to_uint8(const char *s)
Definition: mem_ops.h:131
virtual void kv_set(const std::string &index, const std::string &value)=0
virtual std::set< std::string > kv_get_all() const =0
std::set< std::string > list_names() const override
Definition: psk_db.cpp:31
size_t base64_encode(char out[], const uint8_t in[], size_t input_length, size_t &input_consumed, bool final_inputs)
Definition: base64.cpp:35
size_t base64_decode(uint8_t output[], const char input[], size_t input_length, size_t &input_consumed, bool final_inputs, bool ignore_ws)
Definition: base64.cpp:100
secure_vector< uint8_t > nist_key_unwrap_padded(const uint8_t input[], size_t input_len, const BlockCipher &bc)
Definition: alg_id.cpp:13
void set(const std::string &name, const uint8_t psk[], size_t psk_len) override
Definition: psk_db.cpp:86
static std::unique_ptr< BlockCipher > create_or_throw(const std::string &algo_spec, const std::string &provider="")
const char * cast_uint8_ptr_to_char(const uint8_t *b)
Definition: mem_ops.h:136
std::vector< uint8_t > nist_key_wrap_padded(const uint8_t input[], size_t input_len, const BlockCipher &bc)
virtual void kv_del(const std::string &index)=0
virtual std::string kv_get(const std::string &index) const =0
static std::unique_ptr< MessageAuthenticationCode > create_or_throw(const std::string &algo_spec, const std::string &provider="")
Definition: mac.cpp:141
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:88
void remove(const std::string &name) override
Definition: psk_db.cpp:56