Botan 3.9.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/mem_ops.h>
11#include <botan/internal/ct_utils.h>
12#include <botan/internal/stl_util.h>
13#include <span>
14
15namespace Botan {
16
19 std::unique_ptr<KDF> kdf,
20 std::unique_ptr<MessageAuthenticationCode> mac,
21 size_t mac_key_length) :
22 DLIES_Encryptor(own_priv_key, rng, std::move(kdf), nullptr, 0, std::move(mac), mac_key_length) {}
23
26 std::unique_ptr<KDF> kdf,
27 std::unique_ptr<Cipher_Mode> cipher,
28 size_t cipher_key_len,
29 std::unique_ptr<MessageAuthenticationCode> mac,
30 size_t mac_key_length) :
31
32 m_own_pub_key(own_priv_key.public_value()),
33 m_ka(own_priv_key, rng, "Raw"),
34 m_kdf(std::move(kdf)),
35 m_cipher(std::move(cipher)),
36 m_cipher_key_len(cipher_key_len),
37 m_mac(std::move(mac)),
38 m_mac_keylen(mac_key_length) {
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*/
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) {
112}
113
116 std::unique_ptr<KDF> kdf,
117 std::unique_ptr<MessageAuthenticationCode> mac,
118 size_t mac_key_length) :
119 DLIES_Decryptor(own_priv_key, rng, std::move(kdf), nullptr, 0, std::move(mac), mac_key_length) {}
120
121size_t DLIES_Decryptor::plaintext_length(size_t ctext_len) const {
122 if(ctext_len < m_pub_key_size + m_mac->output_length()) {
123 return 0; // will throw if attempted
124 }
125
126 return ctext_len - (m_pub_key_size + m_mac->output_length());
127}
128
129secure_vector<uint8_t> DLIES_Decryptor::do_decrypt(uint8_t& valid_mask, const uint8_t msg[], size_t length) const {
130 if(length < m_pub_key_size + m_mac->output_length()) {
131 throw Decoding_Error("DLIES decryption: ciphertext is too short");
132 }
133
134 // calculate secret value
135 std::vector<uint8_t> other_pub_key(msg, msg + m_pub_key_size);
136 const SymmetricKey secret_value = m_ka.derive_key(0, other_pub_key);
137
138 const size_t ciphertext_len = length - m_pub_key_size - m_mac->output_length();
139 size_t cipher_key_len = m_cipher ? m_cipher_key_len : ciphertext_len;
140
141 // derive secret key from secret value
142 const size_t required_key_length = cipher_key_len + m_mac_keylen;
143 secure_vector<uint8_t> secret_keys = m_kdf->derive_key(required_key_length, secret_value.bits_of());
144
145 if(secret_keys.size() != required_key_length) {
146 throw Encoding_Error("DLIES: KDF did not provide sufficient output");
147 }
148
149 secure_vector<uint8_t> ciphertext(msg + m_pub_key_size, msg + m_pub_key_size + ciphertext_len);
150
151 // calculate MAC
152 m_mac->set_key(secret_keys.data() + cipher_key_len, m_mac_keylen);
153 secure_vector<uint8_t> calculated_tag = m_mac->process(ciphertext);
154
155 // calculated tag == received tag ?
156
157 std::span<const uint8_t> tag(msg + m_pub_key_size + ciphertext_len, m_mac->output_length());
158
159 valid_mask = CT::is_equal(tag.data(), calculated_tag.data(), tag.size()).value();
160
161 // decrypt
162 if(m_cipher) {
163 if(valid_mask == 0xFF) {
164 SymmetricKey dec_key(secret_keys.data(), cipher_key_len);
165 m_cipher->set_key(dec_key);
166
167 try {
168 // the decryption can fail:
169 // e.g. Invalid_Authentication_Tag is thrown if GCM is used and the message does not have a valid tag
170
171 if(m_iv.empty() && !m_cipher->valid_nonce_length(m_iv.size())) {
172 throw Invalid_Argument("DLIES with " + m_cipher->name() + " requires an IV be set");
173 }
174 m_cipher->start(m_iv.bits_of());
175 m_cipher->finish(ciphertext);
176 } catch(...) {
177 valid_mask = 0;
178 }
179
180 } else {
181 return secure_vector<uint8_t>();
182 }
183 } else {
184 xor_buf(ciphertext, secret_keys.data(), cipher_key_len);
185 }
186
187 return ciphertext;
188}
189
190} // namespace Botan
#define BOTAN_ASSERT_NONNULL(ptr)
Definition assert.h:114
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:114
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:17
virtual size_t maximum_input_size() const =0
SymmetricKey derive_key(size_t key_len, std::span< const uint8_t > peer_key, std::span< const uint8_t > salt) const
Definition pubkey.cpp:247
constexpr CT::Mask< T > is_equal(const T x[], const T y[], size_t len)
Definition ct_utils.h:826
OctetString SymmetricKey
Definition symkey.h:140
constexpr auto concat(Rs &&... ranges)
Definition stl_util.h:255
constexpr void xor_buf(ranges::contiguous_output_range< uint8_t > auto &&out, ranges::contiguous_range< uint8_t > auto &&in)
Definition mem_ops.h:342
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:69