Botan  2.8.0
Crypto and TLS for C++11
dlies.cpp
Go to the documentation of this file.
1 /*
2 * DLIES
3 * (C) 1999-2007 Jack Lloyd
4 * (C) 2016 Daniel Neus, Rohde & Schwarz Cybersecurity
5 *
6 * Botan is released under the Simplified BSD License (see license.txt)
7 */
8 
9 #include <botan/dlies.h>
10 #include <botan/internal/ct_utils.h>
11 #include <limits>
12 
13 namespace Botan {
14 
17  KDF* kdf,
19  size_t mac_key_length) :
20  DLIES_Encryptor(own_priv_key, rng, kdf, nullptr, 0, mac, mac_key_length)
21  {
22  }
23 
26  KDF* kdf,
27  Cipher_Mode* cipher,
28  size_t cipher_key_len,
30  size_t mac_key_length) :
31  m_other_pub_key(),
32  m_own_pub_key(own_priv_key.public_value()),
33  m_ka(own_priv_key, rng, "Raw"),
34  m_kdf(kdf),
35  m_cipher(cipher),
36  m_cipher_key_len(cipher_key_len),
37  m_mac(mac),
38  m_mac_keylen(mac_key_length),
39  m_iv()
40  {
43  }
44 
45 std::vector<uint8_t> DLIES_Encryptor::enc(const uint8_t in[], size_t length,
46  RandomNumberGenerator&) const
47  {
48  if(m_other_pub_key.empty())
49  {
50  throw Invalid_State("DLIES: The other key was never set");
51  }
52 
53  // calculate secret value
54  const SymmetricKey secret_value = m_ka.derive_key(0, m_other_pub_key);
55 
56  // derive secret key from secret value
57  const size_t required_key_length = m_cipher ? m_cipher_key_len + m_mac_keylen : length + m_mac_keylen;
58  const secure_vector<uint8_t> secret_keys = m_kdf->derive_key(required_key_length, secret_value.bits_of());
59 
60  if(secret_keys.size() != required_key_length)
61  {
62  throw Encoding_Error("DLIES: KDF did not provide sufficient output");
63  }
64 
65  secure_vector<uint8_t> ciphertext(in, in + length);
66  const size_t cipher_key_len = m_cipher ? m_cipher_key_len : length;
67 
68  if(m_cipher)
69  {
70  SymmetricKey enc_key(secret_keys.data(), cipher_key_len);
71  m_cipher->set_key(enc_key);
72 
73  if(m_iv.size())
74  {
75  m_cipher->start(m_iv.bits_of());
76  }
77 
78  m_cipher->finish(ciphertext);
79  }
80  else
81  {
82  xor_buf(ciphertext, secret_keys, cipher_key_len);
83  }
84 
85  // calculate MAC
86  m_mac->set_key(secret_keys.data() + cipher_key_len, m_mac_keylen);
87  secure_vector<uint8_t> tag = m_mac->process(ciphertext);
88 
89  // out = (ephemeral) public key + ciphertext + tag
90  secure_vector<uint8_t> out(m_own_pub_key.size() + ciphertext.size() + tag.size());
91  buffer_insert(out, 0, m_own_pub_key);
92  buffer_insert(out, 0 + m_own_pub_key.size(), ciphertext);
93  buffer_insert(out, 0 + m_own_pub_key.size() + ciphertext.size(), tag);
94 
95  return unlock(out);
96  }
97 
98 /**
99 * Return the max size, in bytes, of a message
100 * We assume DLIES is only used for key transport and limit the maximum size
101 * to 512 bits
102 */
103 size_t DLIES_Encryptor::maximum_input_size() const
104  {
105  return 64;
106  }
107 
108 size_t DLIES_Encryptor::ciphertext_length(size_t ptext_len) const
109  {
110  return m_own_pub_key.size() + m_mac->output_length() + m_cipher->output_length(ptext_len);
111  }
112 
115  KDF* kdf,
116  Cipher_Mode* cipher,
117  size_t cipher_key_len,
119  size_t mac_key_length) :
120  m_pub_key_size(own_priv_key.public_value().size()),
121  m_ka(own_priv_key, rng, "Raw"),
122  m_kdf(kdf),
123  m_cipher(cipher),
124  m_cipher_key_len(cipher_key_len),
125  m_mac(mac),
126  m_mac_keylen(mac_key_length),
127  m_iv()
128  {
131  }
132 
135  KDF* kdf,
137  size_t mac_key_length) :
138  DLIES_Decryptor(own_priv_key, rng, kdf, nullptr, 0, mac, mac_key_length)
139  {}
140 
141 size_t DLIES_Decryptor::plaintext_length(size_t ctext_len) const
142  {
143  if(ctext_len < m_pub_key_size + m_mac->output_length())
144  return 0; // will throw if attempted
145 
146  return ctext_len - (m_pub_key_size + m_mac->output_length());
147  }
148 
149 secure_vector<uint8_t> DLIES_Decryptor::do_decrypt(uint8_t& valid_mask,
150  const uint8_t msg[], size_t length) const
151  {
152  if(length < m_pub_key_size + m_mac->output_length())
153  {
154  throw Decoding_Error("DLIES decryption: ciphertext is too short");
155  }
156 
157  // calculate secret value
158  std::vector<uint8_t> other_pub_key(msg, msg + m_pub_key_size);
159  const SymmetricKey secret_value = m_ka.derive_key(0, other_pub_key);
160 
161  const size_t ciphertext_len = length - m_pub_key_size - m_mac->output_length();
162  size_t cipher_key_len = m_cipher ? m_cipher_key_len : ciphertext_len;
163 
164  // derive secret key from secret value
165  const size_t required_key_length = cipher_key_len + m_mac_keylen;
166  secure_vector<uint8_t> secret_keys = m_kdf->derive_key(required_key_length, secret_value.bits_of());
167 
168  if(secret_keys.size() != required_key_length)
169  {
170  throw Encoding_Error("DLIES: KDF did not provide sufficient output");
171  }
172 
173  secure_vector<uint8_t> ciphertext(msg + m_pub_key_size, msg + m_pub_key_size + ciphertext_len);
174 
175  // calculate MAC
176  m_mac->set_key(secret_keys.data() + cipher_key_len, m_mac_keylen);
177  secure_vector<uint8_t> calculated_tag = m_mac->process(ciphertext);
178 
179  // calculated tag == received tag ?
180  secure_vector<uint8_t> tag(msg + m_pub_key_size + ciphertext_len,
181  msg + m_pub_key_size + ciphertext_len + m_mac->output_length());
182 
183  valid_mask = CT::expand_mask<uint8_t>(constant_time_compare(tag.data(), calculated_tag.data(), tag.size()));
184 
185  // decrypt
186  if(m_cipher)
187  {
188  if(valid_mask)
189  {
190  SymmetricKey dec_key(secret_keys.data(), cipher_key_len);
191  m_cipher->set_key(dec_key);
192 
193  try
194  {
195  // the decryption can fail:
196  // e.g. Integrity_Failure is thrown if GCM is used and the message does not have a valid tag
197 
198  if(m_iv.size())
199  {
200  m_cipher->start(m_iv.bits_of());
201  }
202 
203  m_cipher->finish(ciphertext);
204  }
205  catch(...)
206  {
207  valid_mask = 0;
208  }
209 
210  }
211  else
212  {
213  return secure_vector<uint8_t>();
214  }
215  }
216  else
217  {
218  xor_buf(ciphertext, secret_keys.data(), cipher_key_len);
219  }
220 
221  return ciphertext;
222  }
223 
224 }
size_t size() const
Definition: symkey.h:26
bool constant_time_compare(const uint8_t x[], const uint8_t y[], size_t len)
Definition: mem_ops.cpp:51
DLIES_Decryptor(const DH_PrivateKey &own_priv_key, RandomNumberGenerator &rng, KDF *kdf, MessageAuthenticationCode *mac, size_t mac_key_len=20)
Definition: dlies.cpp:133
void xor_buf(uint8_t out[], const uint8_t in[], size_t length)
Definition: mem_ops.h:174
#define BOTAN_ASSERT_NONNULL(ptr)
Definition: assert.h:107
SymmetricKey derive_key(size_t key_len, const uint8_t in[], size_t in_len, const uint8_t params[], size_t params_len) const
Definition: pubkey.cpp:218
Definition: alg_id.cpp:13
OctetString SymmetricKey
Definition: symkey.h:136
std::vector< T > unlock(const secure_vector< T > &in)
Definition: secmem.h:95
Definition: kdf.h:20
size_t buffer_insert(std::vector< T, Alloc > &buf, size_t buf_offset, const T input[], size_t input_length)
Definition: secmem.h:103
secure_vector< uint8_t > bits_of() const
Definition: symkey.h:31
DLIES_Encryptor(const DH_PrivateKey &own_priv_key, RandomNumberGenerator &rng, KDF *kdf, MessageAuthenticationCode *mac, size_t mac_key_len=20)
Definition: dlies.cpp:15