Botan 3.4.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 <botan/internal/ct_utils.h>
11#include <botan/internal/stl_util.h>
12#include <limits>
13
14namespace Botan {
15
18 std::unique_ptr<KDF> kdf,
19 std::unique_ptr<MessageAuthenticationCode> mac,
20 size_t mac_key_length) :
21 DLIES_Encryptor(own_priv_key, rng, std::move(kdf), nullptr, 0, std::move(mac), mac_key_length) {}
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() {
41}
42
43std::vector<uint8_t> DLIES_Encryptor::enc(const uint8_t in[], size_t length, RandomNumberGenerator& /*unused*/) const {
44 if(m_other_pub_key.empty()) {
45 throw Invalid_State("DLIES: The other key was never set");
46 }
47
48 // calculate secret value
49 const SymmetricKey secret_value = m_ka.derive_key(0, m_other_pub_key);
50
51 // derive secret key from secret value
52 const size_t required_key_length = m_cipher ? m_cipher_key_len + m_mac_keylen : length + m_mac_keylen;
53 const secure_vector<uint8_t> secret_keys = m_kdf->derive_key(required_key_length, secret_value.bits_of());
54
55 if(secret_keys.size() != required_key_length) {
56 throw Encoding_Error("DLIES: KDF did not provide sufficient output");
57 }
58
59 secure_vector<uint8_t> ciphertext(in, in + length);
60 const size_t cipher_key_len = m_cipher ? m_cipher_key_len : length;
61
62 if(m_cipher) {
63 SymmetricKey enc_key(secret_keys.data(), cipher_key_len);
64 m_cipher->set_key(enc_key);
65
66 if(m_iv.empty() && !m_cipher->valid_nonce_length(m_iv.size())) {
67 throw Invalid_Argument("DLIES with " + m_cipher->name() + " requires an IV be set");
68 }
69 m_cipher->start(m_iv.bits_of());
70 m_cipher->finish(ciphertext);
71 } else {
72 xor_buf(ciphertext, secret_keys, cipher_key_len);
73 }
74
75 // calculate MAC
76 m_mac->set_key(secret_keys.data() + cipher_key_len, m_mac_keylen);
77 const auto tag = m_mac->process(ciphertext);
78
79 // out = (ephemeral) public key + ciphertext + tag
80 return concat(m_own_pub_key, ciphertext, tag);
81}
82
83/**
84* Return the max size, in bytes, of a message
85* We assume DLIES is only used for key transport and limit the maximum size
86* to 512 bits
87*/
88size_t DLIES_Encryptor::maximum_input_size() const {
89 return 64;
90}
91
92size_t DLIES_Encryptor::ciphertext_length(size_t ptext_len) const {
93 return m_own_pub_key.size() + m_mac->output_length() + m_cipher->output_length(ptext_len);
94}
95
98 std::unique_ptr<KDF> kdf,
99 std::unique_ptr<Cipher_Mode> cipher,
100 size_t cipher_key_len,
101 std::unique_ptr<MessageAuthenticationCode> mac,
102 size_t mac_key_length) :
103 m_pub_key_size(own_priv_key.public_value().size()),
104 m_ka(own_priv_key, rng, "Raw"),
105 m_kdf(std::move(kdf)),
106 m_cipher(std::move(cipher)),
107 m_cipher_key_len(cipher_key_len),
108 m_mac(std::move(mac)),
109 m_mac_keylen(mac_key_length),
110 m_iv() {
113}
114
117 std::unique_ptr<KDF> kdf,
118 std::unique_ptr<MessageAuthenticationCode> mac,
119 size_t mac_key_length) :
120 DLIES_Decryptor(own_priv_key, rng, std::move(kdf), nullptr, 0, std::move(mac), mac_key_length) {}
121
122size_t DLIES_Decryptor::plaintext_length(size_t ctext_len) const {
123 if(ctext_len < m_pub_key_size + m_mac->output_length()) {
124 return 0; // will throw if attempted
125 }
126
127 return ctext_len - (m_pub_key_size + m_mac->output_length());
128}
129
130secure_vector<uint8_t> DLIES_Decryptor::do_decrypt(uint8_t& valid_mask, const uint8_t msg[], size_t length) const {
131 if(length < m_pub_key_size + m_mac->output_length()) {
132 throw Decoding_Error("DLIES decryption: ciphertext is too short");
133 }
134
135 // calculate secret value
136 std::vector<uint8_t> other_pub_key(msg, msg + m_pub_key_size);
137 const SymmetricKey secret_value = m_ka.derive_key(0, other_pub_key);
138
139 const size_t ciphertext_len = length - m_pub_key_size - m_mac->output_length();
140 size_t cipher_key_len = m_cipher ? m_cipher_key_len : ciphertext_len;
141
142 // derive secret key from secret value
143 const size_t required_key_length = cipher_key_len + m_mac_keylen;
144 secure_vector<uint8_t> secret_keys = m_kdf->derive_key(required_key_length, secret_value.bits_of());
145
146 if(secret_keys.size() != required_key_length) {
147 throw Encoding_Error("DLIES: KDF did not provide sufficient output");
148 }
149
150 secure_vector<uint8_t> ciphertext(msg + m_pub_key_size, msg + m_pub_key_size + ciphertext_len);
151
152 // calculate MAC
153 m_mac->set_key(secret_keys.data() + cipher_key_len, m_mac_keylen);
154 secure_vector<uint8_t> calculated_tag = m_mac->process(ciphertext);
155
156 // calculated tag == received tag ?
157 secure_vector<uint8_t> tag(msg + m_pub_key_size + ciphertext_len,
158 msg + m_pub_key_size + ciphertext_len + m_mac->output_length());
159
160 valid_mask = CT::is_equal(tag.data(), calculated_tag.data(), tag.size()).value();
161
162 // decrypt
163 if(m_cipher) {
164 if(valid_mask) {
165 SymmetricKey dec_key(secret_keys.data(), cipher_key_len);
166 m_cipher->set_key(dec_key);
167
168 try {
169 // the decryption can fail:
170 // e.g. Invalid_Authentication_Tag is thrown if GCM is used and the message does not have a valid tag
171
172 if(m_iv.empty() && !m_cipher->valid_nonce_length(m_iv.size())) {
173 throw Invalid_Argument("DLIES with " + m_cipher->name() + " requires an IV be set");
174 }
175 m_cipher->start(m_iv.bits_of());
176 m_cipher->finish(ciphertext);
177 } catch(...) {
178 valid_mask = 0;
179 }
180
181 } else {
182 return secure_vector<uint8_t>();
183 }
184 } else {
185 xor_buf(ciphertext, secret_keys.data(), cipher_key_len);
186 }
187
188 return ciphertext;
189}
190
191} // namespace Botan
#define BOTAN_ASSERT_NONNULL(ptr)
Definition assert.h:86
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:115
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:16
secure_vector< uint8_t > bits_of() const
Definition symkey.h:36
size_t size() const
Definition symkey.h:29
bool empty() const
Definition symkey.h:31
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:231
constexpr CT::Mask< T > is_equal(const T x[], const T y[], size_t len)
Definition ct_utils.h:345
OctetString SymmetricKey
Definition symkey.h:141
constexpr void xor_buf(ranges::contiguous_output_range< uint8_t > auto &&out, ranges::contiguous_range< uint8_t > auto &&in)
Definition mem_ops.h:343
decltype(auto) concat(Ts &&... buffers)
Definition stl_util.h:258