Botan  2.4.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 * Not_Implemented if DLIES is used in XOR encryption mode
101 */
102 size_t DLIES_Encryptor::maximum_input_size() const
103  {
104  if(m_cipher)
105  {
106  // no limit in block cipher mode
107  return std::numeric_limits<size_t>::max();
108  }
109  else
110  {
111  // No way to determine if the KDF will output enough bits for XORing with the plaintext?!
112  throw Not_Implemented("Not implemented for XOR encryption mode");
113  }
114  }
115 
118  KDF* kdf,
119  Cipher_Mode* cipher,
120  size_t cipher_key_len,
122  size_t mac_key_length) :
123  m_pub_key_size(own_priv_key.public_value().size()),
124  m_ka(own_priv_key, rng, "Raw"),
125  m_kdf(kdf),
126  m_cipher(cipher),
127  m_cipher_key_len(cipher_key_len),
128  m_mac(mac),
129  m_mac_keylen(mac_key_length),
130  m_iv()
131  {
134  }
135 
138  KDF* kdf,
140  size_t mac_key_length) :
141  DLIES_Decryptor(own_priv_key, rng, kdf, nullptr, 0, mac, mac_key_length)
142  {}
143 
144 secure_vector<uint8_t> DLIES_Decryptor::do_decrypt(uint8_t& valid_mask,
145  const uint8_t msg[], size_t length) const
146  {
147  if(length < m_pub_key_size + m_mac->output_length())
148  {
149  throw Decoding_Error("DLIES decryption: ciphertext is too short");
150  }
151 
152  // calculate secret value
153  std::vector<uint8_t> other_pub_key(msg, msg + m_pub_key_size);
154  const SymmetricKey secret_value = m_ka.derive_key(0, other_pub_key);
155 
156  const size_t ciphertext_len = length - m_pub_key_size - m_mac->output_length();
157  size_t cipher_key_len = m_cipher ? m_cipher_key_len : ciphertext_len;
158 
159  // derive secret key from secret value
160  const size_t required_key_length = cipher_key_len + m_mac_keylen;
161  secure_vector<uint8_t> secret_keys = m_kdf->derive_key(required_key_length, secret_value.bits_of());
162 
163  if(secret_keys.size() != required_key_length)
164  {
165  throw Encoding_Error("DLIES: KDF did not provide sufficient output");
166  }
167 
168  secure_vector<uint8_t> ciphertext(msg + m_pub_key_size, msg + m_pub_key_size + ciphertext_len);
169 
170  // calculate MAC
171  m_mac->set_key(secret_keys.data() + cipher_key_len, m_mac_keylen);
172  secure_vector<uint8_t> calculated_tag = m_mac->process(ciphertext);
173 
174  // calculated tag == received tag ?
175  secure_vector<uint8_t> tag(msg + m_pub_key_size + ciphertext_len,
176  msg + m_pub_key_size + ciphertext_len + m_mac->output_length());
177 
178  valid_mask = CT::expand_mask<uint8_t>(constant_time_compare(tag.data(), calculated_tag.data(), tag.size()));
179 
180  // decrypt
181  if(m_cipher)
182  {
183  if(valid_mask)
184  {
185  SymmetricKey dec_key(secret_keys.data(), cipher_key_len);
186  m_cipher->set_key(dec_key);
187 
188  try
189  {
190  // the decryption can fail:
191  // e.g. Integrity_Failure is thrown if GCM is used and the message does not have a valid tag
192 
193  if(m_iv.size())
194  {
195  m_cipher->start(m_iv.bits_of());
196  }
197 
198  m_cipher->finish(ciphertext);
199  }
200  catch(...)
201  {
202  valid_mask = 0;
203  }
204 
205  }
206  else
207  {
208  return secure_vector<uint8_t>();
209  }
210  }
211  else
212  {
213  xor_buf(ciphertext, secret_keys.data(), cipher_key_len);
214  }
215 
216  return ciphertext;
217  }
218 
219 }
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:44
DLIES_Decryptor(const DH_PrivateKey &own_priv_key, RandomNumberGenerator &rng, KDF *kdf, MessageAuthenticationCode *mac, size_t mac_key_len=20)
Definition: dlies.cpp:136
void xor_buf(uint8_t out[], const uint8_t in[], size_t length)
Definition: mem_ops.h:163
#define BOTAN_ASSERT_NONNULL(ptr)
Definition: assert.h:81
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:203
Definition: alg_id.cpp:13
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
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:88
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