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