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

randombit / botan / 29673219783

18 Jul 2026 10:42PM UTC coverage: 89.416% (+0.009%) from 89.407%
29673219783

push

github

randombit
Fix EC_Scalar_Data_BN::square_self

It computed the square then failed to update the stored value

114352 of 127887 relevant lines covered (89.42%)

10766049.99 hits per line

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

89.06
/src/tests/test_block.cpp
1
/*
2
* (C) 2014,2015 Jack Lloyd
3
*
4
* Botan is released under the Simplified BSD License (see license.txt)
5
*/
6

7
#include "tests.h"
8

9
#if defined(BOTAN_HAS_BLOCK_CIPHER)
10
   #include <botan/block_cipher.h>
11
   #include <botan/exceptn.h>
12
   #include <botan/mem_ops.h>
13
   #include <botan/rng.h>
14
   #include <botan/internal/fmt.h>
15
#endif
16

17
namespace Botan_Tests {
18

19
namespace {
20

21
#if defined(BOTAN_HAS_BLOCK_CIPHER)
22

23
class Block_Cipher_Tests final : public Text_Based_Test {
×
24
   public:
25
      Block_Cipher_Tests() : Text_Based_Test("block", "Key,In,Out", "Tweak") {}
2✔
26

27
      std::vector<std::string> possible_providers(const std::string& algo) override {
17,163✔
28
         return provider_filter(Botan::BlockCipher::providers(algo));
17,163✔
29
      }
30

31
      Test::Result run_one_test(const std::string& algo, const VarMap& vars) override {
17,163✔
32
         const std::vector<uint8_t> key = vars.get_req_bin("Key");
17,163✔
33
         const std::vector<uint8_t> input = vars.get_req_bin("In");
17,163✔
34
         const std::vector<uint8_t> expected = vars.get_req_bin("Out");
17,163✔
35
         const std::vector<uint8_t> tweak = vars.get_opt_bin("Tweak");
17,163✔
36

37
         Test::Result result(algo);
17,163✔
38

39
         const std::vector<std::string> providers = possible_providers(algo);
17,163✔
40

41
         if(providers.empty()) {
17,163✔
42
            result.note_missing("block cipher " + algo);
×
43
            return result;
×
44
         }
45

46
         for(const auto& provider_ask : providers) {
34,326✔
47
            auto cipher = Botan::BlockCipher::create(algo, provider_ask);
17,163✔
48

49
            if(!cipher) {
17,163✔
50
               result.test_failure(Botan::fmt("Cipher {} supported by {} but not found", algo, provider_ask));
×
51
               continue;
×
52
            }
53

54
            const std::string provider(cipher->provider());
17,163✔
55
            result.test_str_not_empty("provider", provider);
17,163✔
56
            result.test_str_eq(provider, cipher->name(), algo);
17,163✔
57
            result.test_sz_gte(provider, cipher->parallelism(), 1);
17,163✔
58
            result.test_sz_gte(provider, cipher->block_size(), 8);
17,163✔
59
            result.test_sz_gte(provider, cipher->parallel_bytes(), cipher->block_size() * cipher->parallelism());
34,326✔
60

61
            result.test_is_false("no key set", cipher->has_keying_material());
17,163✔
62

63
            // Test that trying to encrypt or decrypt with no key set throws Botan::Invalid_State
64
            try {
17,163✔
65
               std::vector<uint8_t> block(cipher->block_size());
17,163✔
66
               cipher->encrypt(block);
17,163✔
67
               result.test_failure("Was able to encrypt without a key being set");
×
68
            } catch(Botan::Invalid_State&) {
34,326✔
69
               result.test_success("Trying to encrypt with no key set fails");
17,163✔
70
            }
17,163✔
71

72
            try {
17,163✔
73
               std::vector<uint8_t> block(cipher->block_size());
17,163✔
74
               cipher->decrypt(block);
17,163✔
75
               result.test_failure("Was able to decrypt without a key being set");
×
76
            } catch(Botan::Invalid_State&) {
34,326✔
77
               result.test_success("Trying to encrypt with no key set fails");
17,163✔
78
            }
17,163✔
79

80
            // Test to make sure clear() resets what we need it to
81
            cipher->set_key(this->rng().random_vec(cipher->key_spec().maximum_keylength()));
17,163✔
82
            Botan::secure_vector<uint8_t> garbage = this->rng().random_vec(cipher->block_size());
17,163✔
83
            cipher->encrypt(garbage);
17,163✔
84
            cipher->clear();
17,163✔
85

86
            /*
87
            * Different providers may have additional restrictions on key sizes.
88
            * Avoid testing the cipher with a key size that it does not natively support.
89
            */
90
            if(!cipher->valid_keylength(key.size())) {
17,163✔
91
               result.test_note("Skipping test with provider " + provider + " as it does not support key length " +
×
92
                                std::to_string(key.size()));
×
93
               continue;
×
94
            }
95

96
            cipher->set_key(key);
17,163✔
97
            result.test_is_true("key set", cipher->has_keying_material());
17,163✔
98

99
            if(!tweak.empty()) {
17,163✔
100
               Botan::Tweakable_Block_Cipher* tbc = dynamic_cast<Botan::Tweakable_Block_Cipher*>(cipher.get());
2✔
101
               if(tbc == nullptr) {
2✔
102
                  result.test_failure("Tweak set in test data but cipher is not a Tweakable_Block_Cipher");
×
103
               } else {
104
                  tbc->set_tweak(tweak.data(), tweak.size());
2✔
105
               }
106
            }
107

108
            // Test that clone works and does not affect parent object
109
            auto clone = cipher->new_object();
17,163✔
110
            result.test_is_true("Clone has different pointer", cipher.get() != clone.get());
17,163✔
111
            result.test_str_eq("Clone has same name", cipher->name(), clone->name());
17,163✔
112
            result.test_is_false("Clone has no key set", clone->has_keying_material());
17,163✔
113
            clone->set_key(this->rng().random_vec(cipher->maximum_keylength()));
17,163✔
114

115
            // have called set_key on clone: process input values
116
            std::vector<uint8_t> buf = input;
17,163✔
117

118
            cipher->encrypt(buf);
17,163✔
119

120
            result.test_bin_eq(provider + " encrypt", buf, expected);
17,163✔
121

122
            // always decrypt expected ciphertext vs what we produced above
123
            buf = expected;
17,163✔
124

125
            cipher->decrypt(buf);
17,163✔
126

127
            result.test_bin_eq(provider + " decrypt", buf, input);
17,163✔
128

129
            // Now test misaligned buffers
130
            const size_t blocks = input.size() / cipher->block_size();
17,163✔
131
            buf.resize(input.size() + 1);
17,163✔
132
            Botan::copy_mem(buf.data() + 1, input.data(), input.size());
17,163✔
133

134
            cipher->encrypt_n(buf.data() + 1, buf.data() + 1, blocks);
17,163✔
135

136
            result.test_bin_eq(provider + " encrypt misaligned", {buf.data() + 1, buf.size() - 1}, expected);
17,163✔
137

138
            // always decrypt expected ciphertext vs what we produced above
139
            Botan::copy_mem(buf.data() + 1, expected.data(), expected.size());
17,163✔
140

141
            cipher->decrypt_n(buf.data() + 1, buf.data() + 1, blocks);
17,163✔
142

143
            result.test_bin_eq(provider + " decrypt misaligned", std::span{buf.data() + 1, buf.size() - 1}, input);
17,163✔
144

145
            result.test_is_true("key set", cipher->has_keying_material());
17,163✔
146
            cipher->clear();
17,163✔
147
            result.test_is_false("key set", cipher->has_keying_material());
17,163✔
148

149
            try {
17,163✔
150
               std::vector<uint8_t> block(cipher->block_size());
17,163✔
151
               cipher->encrypt(block);
17,163✔
152
               result.test_failure("Was able to encrypt without a key being set");
×
153
            } catch(Botan::Invalid_State&) {
34,326✔
154
               result.test_success("Trying to encrypt with no key set (after clear) fails");
17,163✔
155
            }
17,163✔
156

157
            try {
17,163✔
158
               std::vector<uint8_t> block(cipher->block_size());
17,163✔
159
               cipher->decrypt(block);
17,163✔
160
               result.test_failure("Was able to decrypt without a key being set");
×
161
            } catch(Botan::Invalid_State&) {
34,326✔
162
               result.test_success("Trying to decrypt with no key set (after clear) fails");
17,163✔
163
            }
17,163✔
164
         }
68,652✔
165

166
         return result;
167
      }
85,815✔
168
};
169

170
BOTAN_REGISTER_SERIALIZED_SMOKE_TEST("block", "block_ciphers", Block_Cipher_Tests);
171

172
class BlockCipher_ParallelOp_Test final : public Test {
1✔
173
   public:
174
      std::vector<Test::Result> run() override {
1✔
175
         /*
176
         * This is somewhat intentionally not a list of all ciphers
177
         * but rather those that are or are likely in the future to be
178
         * implemented using some kind of bitslicing or SIMD technique.
179
         */
180
         const std::vector<std::string> ciphers = {"AES-128",
1✔
181
                                                   "AES-192",
182
                                                   "AES-256",
183
                                                   "ARIA-128",
184
                                                   "ARIA-256",
185
                                                   "Camellia-128",
186
                                                   "Camellia-192",
187
                                                   "Camellia-256",
188
                                                   "DES",
189
                                                   "TripleDES",
190
                                                   "IDEA",
191
                                                   "Noekeon",
192
                                                   "SEED",
193
                                                   "Serpent",
194
                                                   "SHACAL2",
195
                                                   "SM4"};
1✔
196

197
         std::vector<Test::Result> results;
1✔
198
         results.reserve(ciphers.size());
1✔
199
         for(const auto& cipher : ciphers) {
17✔
200
            results.push_back(test_parallel_op(cipher));
32✔
201
         }
202
         return results;
1✔
203
      }
1✔
204

205
   private:
206
      Test::Result test_parallel_op(const std::string& cipher_name) const {
16✔
207
         Test::Result result(cipher_name + " parallel operation");
16✔
208

209
         auto cipher = Botan::BlockCipher::create(cipher_name);
16✔
210
         if(cipher == nullptr) {
16✔
211
            result.note_missing(cipher_name);
×
212
            return result;
213
         }
214

215
         result.test_sz_gte("Has non-zero parallelism", cipher->parallelism(), 1);
16✔
216

217
         const size_t block_size = cipher->block_size();
16✔
218

219
         // Chosen to maximize coverage of handling of tail blocks
220
         constexpr size_t test_blocks = 128 + 64 + 32 + 16 + 8 + 4 + 2 + 1;
16✔
221

222
         std::vector<uint8_t> input(block_size * test_blocks);
16✔
223
         rng().randomize(input);
16✔
224

225
         cipher->set_key(rng().random_vec(cipher->maximum_keylength()));
16✔
226

227
         // Encrypt the message one block at a time
228
         std::vector<uint8_t> enc_1by1(input);
16✔
229

230
         for(size_t i = 0; i != test_blocks; ++i) {
4,096✔
231
            cipher->encrypt(&enc_1by1[i * block_size], &enc_1by1[i * block_size]);
4,080✔
232
         }
233

234
         // Encrypt the message with all blocks potentially in parallel
235
         std::vector<uint8_t> enc_all(input);
16✔
236

237
         cipher->encrypt(enc_all);
16✔
238

239
         result.test_bin_eq("Same output no matter how encrypted", enc_all, enc_1by1);
16✔
240

241
         // Decrypt the message one block at a time
242
         for(size_t i = 0; i != test_blocks; ++i) {
4,096✔
243
            cipher->decrypt(&enc_1by1[i * block_size], &enc_1by1[i * block_size]);
4,080✔
244
         }
245

246
         // Decrypt the message with all blocks potentially in parallel
247
         cipher->decrypt(enc_all);
16✔
248

249
         result.test_bin_eq("Same output no matter how decrypted", enc_all, enc_1by1);
16✔
250
         result.test_bin_eq("Original input recovered in 1-by-1", enc_1by1, input);
16✔
251
         result.test_bin_eq("Original input recovered in parallel processing", enc_all, input);
16✔
252

253
         return result;
16✔
254
      }
32✔
255
};
256

257
BOTAN_REGISTER_TEST("block", "bc_parop", BlockCipher_ParallelOp_Test);
258

259
#endif
260

261
}  // namespace
262

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

© 2026 Coveralls, Inc