• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 5134090420

31 May 2023 03:12PM UTC coverage: 91.721% (-0.3%) from 91.995%
5134090420

push

github

randombit
Merge GH #3565 Disable noisy/pointless pylint warnings

76048 of 82912 relevant lines covered (91.72%)

11755290.1 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.0
/src/lib/pubkey/dlies/dlies.cpp
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

12
namespace Botan {
13

14
DLIES_Encryptor::DLIES_Encryptor(const DH_PrivateKey& own_priv_key,
4✔
15
                                 RandomNumberGenerator& rng,
16
                                 std::unique_ptr<KDF> kdf,
17
                                 std::unique_ptr<MessageAuthenticationCode> mac,
18
                                 size_t mac_key_length) :
4✔
19
      DLIES_Encryptor(own_priv_key, rng, std::move(kdf), nullptr, 0, std::move(mac), mac_key_length) {}
8✔
20

21
DLIES_Encryptor::DLIES_Encryptor(const DH_PrivateKey& own_priv_key,
76✔
22
                                 RandomNumberGenerator& rng,
23
                                 std::unique_ptr<KDF> kdf,
24
                                 std::unique_ptr<Cipher_Mode> cipher,
25
                                 size_t cipher_key_len,
26
                                 std::unique_ptr<MessageAuthenticationCode> mac,
27
                                 size_t mac_key_length) :
76✔
28
      m_other_pub_key(),
76✔
29
      m_own_pub_key(own_priv_key.public_value()),
76✔
30
      m_ka(own_priv_key, rng, "Raw"),
76✔
31
      m_kdf(std::move(kdf)),
76✔
32
      m_cipher(std::move(cipher)),
76✔
33
      m_cipher_key_len(cipher_key_len),
76✔
34
      m_mac(std::move(mac)),
76✔
35
      m_mac_keylen(mac_key_length),
76✔
36
      m_iv() {
152✔
37
   BOTAN_ASSERT_NONNULL(m_kdf);
76✔
38
   BOTAN_ASSERT_NONNULL(m_mac);
76✔
39
}
76✔
40

41
std::vector<uint8_t> DLIES_Encryptor::enc(const uint8_t in[], size_t length, RandomNumberGenerator& /*unused*/) const {
80✔
42
   if(m_other_pub_key.empty()) {
80✔
43
      throw Invalid_State("DLIES: The other key was never set");
4✔
44
   }
45

46
   // calculate secret value
47
   const SymmetricKey secret_value = m_ka.derive_key(0, m_other_pub_key);
76✔
48

49
   // derive secret key from secret value
50
   const size_t required_key_length = m_cipher ? m_cipher_key_len + m_mac_keylen : length + m_mac_keylen;
76✔
51
   const secure_vector<uint8_t> secret_keys = m_kdf->derive_key(required_key_length, secret_value.bits_of());
76✔
52

53
   if(secret_keys.size() != required_key_length) {
76✔
54
      throw Encoding_Error("DLIES: KDF did not provide sufficient output");
×
55
   }
56

57
   secure_vector<uint8_t> ciphertext(in, in + length);
76✔
58
   const size_t cipher_key_len = m_cipher ? m_cipher_key_len : length;
76✔
59

60
   if(m_cipher) {
76✔
61
      SymmetricKey enc_key(secret_keys.data(), cipher_key_len);
50✔
62
      m_cipher->set_key(enc_key);
50✔
63

64
      if(m_iv.empty() && !m_cipher->valid_nonce_length(m_iv.size())) {
50✔
65
         throw Invalid_Argument("DLIES with " + m_cipher->name() + " requires an IV be set");
×
66
      }
67
      m_cipher->start(m_iv.bits_of());
50✔
68
      m_cipher->finish(ciphertext);
50✔
69
   } else {
50✔
70
      xor_buf(ciphertext, secret_keys, cipher_key_len);
26✔
71
   }
72

73
   // calculate MAC
74
   m_mac->set_key(secret_keys.data() + cipher_key_len, m_mac_keylen);
76✔
75
   secure_vector<uint8_t> tag = m_mac->process(ciphertext);
76✔
76

77
   // out = (ephemeral) public key + ciphertext + tag
78
   secure_vector<uint8_t> out(m_own_pub_key.size() + ciphertext.size() + tag.size());
76✔
79
   buffer_insert(out, 0, m_own_pub_key);
76✔
80
   buffer_insert(out, 0 + m_own_pub_key.size(), ciphertext);
76✔
81
   buffer_insert(out, 0 + m_own_pub_key.size() + ciphertext.size(), tag);
76✔
82

83
   return unlock(out);
76✔
84
}
380✔
85

86
/**
87
* Return the max size, in bytes, of a message
88
* We assume DLIES is only used for key transport and limit the maximum size
89
* to 512 bits
90
*/
91
size_t DLIES_Encryptor::maximum_input_size() const { return 64; }
×
92

93
size_t DLIES_Encryptor::ciphertext_length(size_t ptext_len) const {
×
94
   return m_own_pub_key.size() + m_mac->output_length() + m_cipher->output_length(ptext_len);
×
95
}
96

97
DLIES_Decryptor::DLIES_Decryptor(const DH_PrivateKey& own_priv_key,
76✔
98
                                 RandomNumberGenerator& rng,
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) :
76✔
104
      m_pub_key_size(own_priv_key.public_value().size()),
76✔
105
      m_ka(own_priv_key, rng, "Raw"),
76✔
106
      m_kdf(std::move(kdf)),
76✔
107
      m_cipher(std::move(cipher)),
76✔
108
      m_cipher_key_len(cipher_key_len),
76✔
109
      m_mac(std::move(mac)),
76✔
110
      m_mac_keylen(mac_key_length),
76✔
111
      m_iv() {
152✔
112
   BOTAN_ASSERT_NONNULL(m_kdf);
76✔
113
   BOTAN_ASSERT_NONNULL(m_mac);
76✔
114
}
76✔
115

116
DLIES_Decryptor::DLIES_Decryptor(const DH_PrivateKey& own_priv_key,
4✔
117
                                 RandomNumberGenerator& rng,
118
                                 std::unique_ptr<KDF> kdf,
119
                                 std::unique_ptr<MessageAuthenticationCode> mac,
120
                                 size_t mac_key_length) :
4✔
121
      DLIES_Decryptor(own_priv_key, rng, std::move(kdf), nullptr, 0, std::move(mac), mac_key_length) {}
8✔
122

123
size_t DLIES_Decryptor::plaintext_length(size_t ctext_len) const {
×
124
   if(ctext_len < m_pub_key_size + m_mac->output_length()) {
×
125
      return 0;  // will throw if attempted
126
   }
127

128
   return ctext_len - (m_pub_key_size + m_mac->output_length());
×
129
}
130

131
secure_vector<uint8_t> DLIES_Decryptor::do_decrypt(uint8_t& valid_mask, const uint8_t msg[], size_t length) const {
1,600✔
132
   if(length < m_pub_key_size + m_mac->output_length()) {
1,600✔
133
      throw Decoding_Error("DLIES decryption: ciphertext is too short");
4✔
134
   }
135

136
   // calculate secret value
137
   std::vector<uint8_t> other_pub_key(msg, msg + m_pub_key_size);
1,596✔
138
   const SymmetricKey secret_value = m_ka.derive_key(0, other_pub_key);
1,596✔
139

140
   const size_t ciphertext_len = length - m_pub_key_size - m_mac->output_length();
1,596✔
141
   size_t cipher_key_len = m_cipher ? m_cipher_key_len : ciphertext_len;
1,596✔
142

143
   // derive secret key from secret value
144
   const size_t required_key_length = cipher_key_len + m_mac_keylen;
1,596✔
145
   secure_vector<uint8_t> secret_keys = m_kdf->derive_key(required_key_length, secret_value.bits_of());
1,596✔
146

147
   if(secret_keys.size() != required_key_length) {
1,596✔
148
      throw Encoding_Error("DLIES: KDF did not provide sufficient output");
×
149
   }
150

151
   secure_vector<uint8_t> ciphertext(msg + m_pub_key_size, msg + m_pub_key_size + ciphertext_len);
1,596✔
152

153
   // calculate MAC
154
   m_mac->set_key(secret_keys.data() + cipher_key_len, m_mac_keylen);
1,596✔
155
   secure_vector<uint8_t> calculated_tag = m_mac->process(ciphertext);
1,596✔
156

157
   // calculated tag == received tag ?
158
   secure_vector<uint8_t> tag(msg + m_pub_key_size + ciphertext_len,
3,192✔
159
                              msg + m_pub_key_size + ciphertext_len + m_mac->output_length());
1,596✔
160

161
   valid_mask = ct_compare_u8(tag.data(), calculated_tag.data(), tag.size());
1,596✔
162

163
   // decrypt
164
   if(m_cipher) {
1,596✔
165
      if(valid_mask) {
1,050✔
166
         SymmetricKey dec_key(secret_keys.data(), cipher_key_len);
50✔
167
         m_cipher->set_key(dec_key);
50✔
168

169
         try {
50✔
170
            // the decryption can fail:
171
            // e.g. Invalid_Authentication_Tag is thrown if GCM is used and the message does not have a valid tag
172

173
            if(m_iv.empty() && !m_cipher->valid_nonce_length(m_iv.size())) {
50✔
174
               throw Invalid_Argument("DLIES with " + m_cipher->name() + " requires an IV be set");
×
175
            }
176
            m_cipher->start(m_iv.bits_of());
50✔
177
            m_cipher->finish(ciphertext);
50✔
178
         } catch(...) {
×
179
            valid_mask = 0;
×
180
         }
×
181

182
      } else {
50✔
183
         return secure_vector<uint8_t>();
1,000✔
184
      }
185
   } else {
186
      xor_buf(ciphertext, secret_keys.data(), cipher_key_len);
546✔
187
   }
188

189
   return ciphertext;
1,596✔
190
}
8,980✔
191

192
}  // namespace Botan
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc