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