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