Botan  2.15.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() == 0 && !m_cipher->valid_nonce_length(m_iv.size()))
73  throw Invalid_Argument("DLIES with " + m_cipher->name() + " requires an IV be set");
74  m_cipher->start(m_iv.bits_of());
75  m_cipher->finish(ciphertext);
76  }
77  else
78  {
79  xor_buf(ciphertext, secret_keys, cipher_key_len);
80  }
81 
82  // calculate MAC
83  m_mac->set_key(secret_keys.data() + cipher_key_len, m_mac_keylen);
84  secure_vector<uint8_t> tag = m_mac->process(ciphertext);
85 
86  // out = (ephemeral) public key + ciphertext + tag
87  secure_vector<uint8_t> out(m_own_pub_key.size() + ciphertext.size() + tag.size());
88  buffer_insert(out, 0, m_own_pub_key);
89  buffer_insert(out, 0 + m_own_pub_key.size(), ciphertext);
90  buffer_insert(out, 0 + m_own_pub_key.size() + ciphertext.size(), tag);
91 
92  return unlock(out);
93  }
94 
95 /**
96 * Return the max size, in bytes, of a message
97 * We assume DLIES is only used for key transport and limit the maximum size
98 * to 512 bits
99 */
100 size_t DLIES_Encryptor::maximum_input_size() const
101  {
102  return 64;
103  }
104 
105 size_t DLIES_Encryptor::ciphertext_length(size_t ptext_len) const
106  {
107  return m_own_pub_key.size() + m_mac->output_length() + m_cipher->output_length(ptext_len);
108  }
109 
112  KDF* kdf,
113  Cipher_Mode* cipher,
114  size_t cipher_key_len,
116  size_t mac_key_length) :
117  m_pub_key_size(own_priv_key.public_value().size()),
118  m_ka(own_priv_key, rng, "Raw"),
119  m_kdf(kdf),
120  m_cipher(cipher),
121  m_cipher_key_len(cipher_key_len),
122  m_mac(mac),
123  m_mac_keylen(mac_key_length),
124  m_iv()
125  {
128  }
129 
132  KDF* kdf,
134  size_t mac_key_length) :
135  DLIES_Decryptor(own_priv_key, rng, kdf, nullptr, 0, mac, mac_key_length)
136  {}
137 
138 size_t DLIES_Decryptor::plaintext_length(size_t ctext_len) const
139  {
140  if(ctext_len < m_pub_key_size + m_mac->output_length())
141  return 0; // will throw if attempted
142 
143  return ctext_len - (m_pub_key_size + m_mac->output_length());
144  }
145 
146 secure_vector<uint8_t> DLIES_Decryptor::do_decrypt(uint8_t& valid_mask,
147  const uint8_t msg[], size_t length) const
148  {
149  if(length < m_pub_key_size + m_mac->output_length())
150  {
151  throw Decoding_Error("DLIES decryption: ciphertext is too short");
152  }
153 
154  // calculate secret value
155  std::vector<uint8_t> other_pub_key(msg, msg + m_pub_key_size);
156  const SymmetricKey secret_value = m_ka.derive_key(0, other_pub_key);
157 
158  const size_t ciphertext_len = length - m_pub_key_size - m_mac->output_length();
159  size_t cipher_key_len = m_cipher ? m_cipher_key_len : ciphertext_len;
160 
161  // derive secret key from secret value
162  const size_t required_key_length = cipher_key_len + m_mac_keylen;
163  secure_vector<uint8_t> secret_keys = m_kdf->derive_key(required_key_length, secret_value.bits_of());
164 
165  if(secret_keys.size() != required_key_length)
166  {
167  throw Encoding_Error("DLIES: KDF did not provide sufficient output");
168  }
169 
170  secure_vector<uint8_t> ciphertext(msg + m_pub_key_size, msg + m_pub_key_size + ciphertext_len);
171 
172  // calculate MAC
173  m_mac->set_key(secret_keys.data() + cipher_key_len, m_mac_keylen);
174  secure_vector<uint8_t> calculated_tag = m_mac->process(ciphertext);
175 
176  // calculated tag == received tag ?
177  secure_vector<uint8_t> tag(msg + m_pub_key_size + ciphertext_len,
178  msg + m_pub_key_size + ciphertext_len + m_mac->output_length());
179 
180  valid_mask = ct_compare_u8(tag.data(), calculated_tag.data(), tag.size());
181 
182  // decrypt
183  if(m_cipher)
184  {
185  if(valid_mask)
186  {
187  SymmetricKey dec_key(secret_keys.data(), cipher_key_len);
188  m_cipher->set_key(dec_key);
189 
190  try
191  {
192  // the decryption can fail:
193  // e.g. Invalid_Authentication_Tag is thrown if GCM is used and the message does not have a valid tag
194 
195  if(m_iv.size() == 0 && !m_cipher->valid_nonce_length(m_iv.size()))
196  throw Invalid_Argument("DLIES with " + m_cipher->name() + " requires an IV be set");
197  m_cipher->start(m_iv.bits_of());
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
DLIES_Decryptor(const DH_PrivateKey &own_priv_key, RandomNumberGenerator &rng, KDF *kdf, MessageAuthenticationCode *mac, size_t mac_key_len=20)
Definition: dlies.cpp:130
void xor_buf(uint8_t out[], const uint8_t in[], size_t length)
Definition: mem_ops.h:233
uint8_t ct_compare_u8(const uint8_t x[], const uint8_t y[], size_t len)
Definition: mem_ops.cpp:56
#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:141
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