Botan 3.0.0
Crypto and TLS for C&
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
12namespace Botan {
13
16 std::unique_ptr<KDF> kdf,
17 std::unique_ptr<MessageAuthenticationCode> mac,
18 size_t mac_key_length) :
19 DLIES_Encryptor(own_priv_key, rng, std::move(kdf), nullptr, 0, std::move(mac), mac_key_length)
20 {
21 }
22
25 std::unique_ptr<KDF> kdf,
26 std::unique_ptr<Cipher_Mode> cipher,
27 size_t cipher_key_len,
28 std::unique_ptr<MessageAuthenticationCode> mac,
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(std::move(kdf)),
34 m_cipher(std::move(cipher)),
35 m_cipher_key_len(cipher_key_len),
36 m_mac(std::move(mac)),
37 m_mac_keylen(mac_key_length),
38 m_iv()
39 {
42 }
43
44std::vector<uint8_t> DLIES_Encryptor::enc(const uint8_t in[], size_t length,
45 RandomNumberGenerator& /*unused*/) 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.empty() && !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*/
100size_t DLIES_Encryptor::maximum_input_size() const
101 {
102 return 64;
103 }
104
105size_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 std::unique_ptr<KDF> kdf,
113 std::unique_ptr<Cipher_Mode> cipher,
114 size_t cipher_key_len,
115 std::unique_ptr<MessageAuthenticationCode> mac,
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(std::move(kdf)),
120 m_cipher(std::move(cipher)),
121 m_cipher_key_len(cipher_key_len),
122 m_mac(std::move(mac)),
123 m_mac_keylen(mac_key_length),
124 m_iv()
125 {
128 }
129
132 std::unique_ptr<KDF> kdf,
133 std::unique_ptr<MessageAuthenticationCode> mac,
134 size_t mac_key_length) :
135 DLIES_Decryptor(own_priv_key, rng, std::move(kdf), nullptr, 0, std::move(mac), mac_key_length)
136 {}
137
138size_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
146secure_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.empty() && !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}
#define BOTAN_ASSERT_NONNULL(ptr)
Definition: assert.h:106
DLIES_Decryptor(const DH_PrivateKey &own_priv_key, RandomNumberGenerator &rng, std::unique_ptr< KDF > kdf, std::unique_ptr< MessageAuthenticationCode > mac, size_t mac_key_len=20)
Definition: dlies.cpp:130
DLIES_Encryptor(const DH_PrivateKey &own_priv_key, RandomNumberGenerator &rng, std::unique_ptr< KDF > kdf, std::unique_ptr< MessageAuthenticationCode > mac, size_t mac_key_len=20)
Definition: dlies.cpp:14
secure_vector< uint8_t > bits_of() const
Definition: symkey.h:35
size_t size() const
Definition: symkey.h:29
bool empty() const
Definition: symkey.h:30
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:234
Definition: alg_id.cpp:12
size_t buffer_insert(std::vector< T, Alloc > &buf, size_t buf_offset, const T input[], size_t input_length)
Definition: mem_ops.h:221
std::vector< T > unlock(const secure_vector< T > &in)
Definition: secmem.h:77
OctetString SymmetricKey
Definition: symkey.h:145
uint8_t ct_compare_u8(const uint8_t x[], const uint8_t y[], size_t len)
Definition: mem_ops.cpp:66
void xor_buf(uint8_t out[], const uint8_t in[], size_t length)
Definition: mem_ops.h:255
Definition: bigint.h:1092