9#include <botan/dlies.h>
10#include <botan/mem_ops.h>
11#include <botan/internal/concat_util.h>
12#include <botan/internal/ct_utils.h>
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) {}
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) :
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) {
43std::vector<uint8_t> DLIES_Encryptor::enc(
const uint8_t in[],
size_t length,
RandomNumberGenerator& )
const {
44 if(m_other_pub_key.empty()) {
52 const size_t required_key_length = m_cipher ? m_cipher_key_len + m_mac_keylen : length + m_mac_keylen;
55 if(secret_keys.size() != required_key_length) {
56 throw Encoding_Error(
"DLIES: KDF did not provide sufficient output");
60 const size_t cipher_key_len = m_cipher ? m_cipher_key_len : length;
63 const SymmetricKey enc_key(secret_keys.data(), cipher_key_len);
64 m_cipher->set_key(enc_key);
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");
69 m_cipher->start(m_iv.bits_of());
70 m_cipher->finish(ciphertext);
72 xor_buf(ciphertext, secret_keys, cipher_key_len);
76 m_mac->set_key(secret_keys.data() + cipher_key_len, m_mac_keylen);
77 const auto tag = m_mac->process(ciphertext);
80 return concat(m_own_pub_key, ciphertext, tag);
92size_t DLIES_Encryptor::ciphertext_length(
size_t ptext_len)
const {
93 const size_t ctext_len = (m_cipher !=
nullptr) ? m_cipher->output_length(ptext_len) : ptext_len;
94 return m_own_pub_key.size() + m_mac->output_length() + ctext_len;
99 std::unique_ptr<KDF> kdf,
100 std::unique_ptr<Cipher_Mode> cipher,
101 size_t cipher_key_len,
102 std::unique_ptr<MessageAuthenticationCode> mac,
103 size_t mac_key_length) :
104 m_pub_key_size(own_priv_key.public_value().size()),
105 m_ka(own_priv_key, rng,
"Raw"),
106 m_kdf(std::move(kdf)),
107 m_cipher(std::move(cipher)),
108 m_cipher_key_len(cipher_key_len),
109 m_mac(std::move(mac)),
110 m_mac_keylen(mac_key_length) {
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) {}
122size_t DLIES_Decryptor::plaintext_length(
size_t ctext_len)
const {
123 if(ctext_len < m_pub_key_size + m_mac->output_length()) {
127 return ctext_len - (m_pub_key_size + m_mac->output_length());
130size_t DLIES_Decryptor::ciphertext_length(
size_t ptext_len)
const {
131 const auto ctext_len = [&]() ->
size_t {
132 if(m_cipher !=
nullptr) {
135 return cipher->output_length(ptext_len);
141 return m_pub_key_size + m_mac->output_length() + ctext_len;
144secure_vector<uint8_t> DLIES_Decryptor::do_decrypt(uint8_t& valid_mask,
const uint8_t msg[],
size_t length)
const {
145 if(length < m_pub_key_size + m_mac->output_length()) {
146 throw Decoding_Error(
"DLIES decryption: ciphertext is too short");
150 std::vector<uint8_t> other_pub_key(msg, msg + m_pub_key_size);
151 const SymmetricKey secret_value = m_ka.derive_key(0, other_pub_key);
153 const size_t ciphertext_len = length - m_pub_key_size - m_mac->output_length();
154 const size_t cipher_key_len = m_cipher ? m_cipher_key_len : ciphertext_len;
157 const size_t required_key_length = cipher_key_len + m_mac_keylen;
160 if(secret_keys.size() != required_key_length) {
161 throw Encoding_Error(
"DLIES: KDF did not provide sufficient output");
167 m_mac->set_key(secret_keys.data() + cipher_key_len, m_mac_keylen);
172 const std::span<const uint8_t> tag(msg + m_pub_key_size + ciphertext_len, m_mac->output_length());
178 if(valid_mask == 0xFF) {
179 const SymmetricKey dec_key(secret_keys.data(), cipher_key_len);
180 m_cipher->set_key(dec_key);
186 if(m_iv.empty() && !m_cipher->valid_nonce_length(m_iv.size())) {
187 throw Invalid_Argument(
"DLIES with " + m_cipher->name() +
" requires an IV be set");
189 m_cipher->start(m_iv.bits_of());
190 m_cipher->finish(ciphertext);
199 xor_buf(ciphertext, secret_keys.data(), cipher_key_len);
#define BOTAN_ASSERT_NONNULL(ptr)
static std::unique_ptr< Cipher_Mode > create(std::string_view algo, Cipher_Dir direction, std::string_view provider="")
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)
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)
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
constexpr CT::Mask< T > is_equal(const T x[], const T y[], size_t len)
constexpr auto concat(Rs &&... ranges)
constexpr void xor_buf(ranges::contiguous_output_range< uint8_t > auto &&out, ranges::contiguous_range< uint8_t > auto &&in)
std::vector< T, secure_allocator< T > > secure_vector