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

randombit / botan / 23114513202

15 Mar 2026 04:32PM UTC coverage: 91.99% (+2.3%) from 89.738%
23114513202

push

github

web-flow
Merge pull request #5446 from randombit/jack/fix-clang-tidy-22-warnings

Address (or silence) various new warnings from clang-tidy 22

106961 of 116275 relevant lines covered (91.99%)

11215912.22 hits per line

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

89.34
/src/tests/test_stream.cpp
1
/*
2
* (C) 2014,2015,2016 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_STREAM_CIPHER)
10
   #include <botan/exceptn.h>
11
   #include <botan/rng.h>
12
   #include <botan/stream_cipher.h>
13
   #include <botan/internal/fmt.h>
14
#endif
15

16
namespace Botan_Tests {
17

18
#if defined(BOTAN_HAS_STREAM_CIPHER)
19

20
namespace {
21

22
class Stream_Cipher_Tests final : public Text_Based_Test {
×
23
   public:
24
      Stream_Cipher_Tests() : Text_Based_Test("stream", "Key,Out", "In,Nonce,Seek") {}
2✔
25

26
      Test::Result run_one_test(const std::string& algo, const VarMap& vars) override {
3,646✔
27
         const std::vector<uint8_t> key = vars.get_req_bin("Key");
3,646✔
28
         const std::vector<uint8_t> expected = vars.get_req_bin("Out");
3,646✔
29
         const std::vector<uint8_t> nonce = vars.get_opt_bin("Nonce");
3,646✔
30
         const uint64_t seek = vars.get_opt_u64("Seek", 0);
3,646✔
31
         std::vector<uint8_t> input = vars.get_opt_bin("In");
3,646✔
32

33
         if(input.empty()) {
3,646✔
34
            input.resize(expected.size());
2,772✔
35
         }
36

37
         Test::Result result(algo);
3,646✔
38

39
         const std::vector<std::string> providers = provider_filter(Botan::StreamCipher::providers(algo));
3,646✔
40

41
         if(providers.empty()) {
3,646✔
42
            result.note_missing("stream cipher " + algo);
1✔
43
            return result;
1✔
44
         }
45

46
         for(const auto& provider_ask : providers) {
7,290✔
47
            auto cipher = Botan::StreamCipher::create(algo, provider_ask);
3,645✔
48

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

54
            const std::string provider(cipher->provider());
3,645✔
55
            result.test_str_not_empty("provider", provider);
3,645✔
56
            result.test_str_eq(provider, cipher->name(), algo);
3,645✔
57

58
            result.test_is_true("default iv length is valid", cipher->valid_iv_length(cipher->default_iv_length()));
3,645✔
59

60
            result.test_is_true("advertised buffer size is > 0", cipher->buffer_size() > 0);
3,645✔
61

62
            if(cipher->default_iv_length() == 0) {
3,645✔
63
               result.test_is_true("if default iv length is zero, no iv supported", nonce.empty());
2,365✔
64

65
               // This should still succeed
66
               cipher->set_iv(nullptr, 0);
2,365✔
67
            }
68

69
            try {
3,645✔
70
               std::vector<uint8_t> buf(128);
3,645✔
71
               cipher->cipher1(buf.data(), buf.size());
3,645✔
72
               result.test_failure("Was able to encrypt without a key being set");
×
73
            } catch(Botan::Invalid_State&) {
3,645✔
74
               result.test_success("Trying to encrypt with no key set fails");
3,645✔
75
            }
3,645✔
76

77
            try {
3,645✔
78
               cipher->seek(0);
3,645✔
79
               result.test_failure("Was able to seek without a key being set");
×
80
            } catch(Botan::Invalid_State&) {
3,645✔
81
               result.test_success("Trying to seek with no key set fails");
1,263✔
82
            } catch(Botan::Not_Implemented&) {
3,645✔
83
               result.test_success("Trying to seek failed because not implemented");
2,382✔
84
            }
2,382✔
85

86
            if(!cipher->valid_iv_length(nonce.size())) {
3,645✔
87
               throw Test_Error("Invalid nonce for " + algo);
×
88
            }
89

90
            bool accepted_nonce_early = false;
3,645✔
91
            if(!nonce.empty()) {
3,645✔
92
               try {
1,275✔
93
                  cipher->set_iv(nonce.data(), nonce.size());
1,275✔
94
                  accepted_nonce_early = true;
95
               } catch(Botan::Invalid_State&) {}
1,275✔
96
            }
97

98
            /*
99
            * Different providers may have additional restrictions on key sizes.
100
            * Avoid testing the cipher with a key size that it does not natively support.
101
            */
102
            if(!cipher->valid_keylength(key.size())) {
3,645✔
103
               result.test_note("Skipping test with provider " + provider + " as it does not support key length " +
×
104
                                std::to_string(key.size()));
×
105
               continue;
×
106
            }
107

108
            result.test_is_false("key not set", cipher->has_keying_material());
3,645✔
109
            cipher->set_key(key);
3,645✔
110
            result.test_is_true("key set", cipher->has_keying_material());
3,645✔
111

112
            /*
113
            Test invalid nonce sizes. this assumes no implemented cipher supports a nonce of 65000
114
            */
115
            const size_t large_nonce_size = 65000;
3,645✔
116
            result.test_is_true("Stream cipher does not support very large nonce",
3,645✔
117
                                cipher->valid_iv_length(large_nonce_size) == false);
3,645✔
118

119
            result.test_throws("Throws if invalid nonce size given",
3,645✔
120
                               [&]() { cipher->set_iv(nullptr, large_nonce_size); });
7,290✔
121

122
            /*
123
            If the set_nonce call earlier succeeded, then we require that it also
124
            worked (ie saved the nonce for later use) even though the key was
125
            not set. So, don't set the nonce now, to ensure the previous call
126
            had an effect.
127
            */
128
            if(!nonce.empty() && accepted_nonce_early == false) {
3,645✔
129
               cipher->set_iv(nonce.data(), nonce.size());
1,275✔
130
            }
131

132
            if(seek != 0) {
3,645✔
133
               cipher->seek(seek);
700✔
134
            }
135

136
            // Test that clone works and does not affect parent object
137
            auto clone = cipher->new_object();
3,645✔
138
            result.test_is_true("Clone has different pointer", cipher.get() != clone.get());
3,645✔
139
            result.test_str_eq("Clone has same name", cipher->name(), clone->name());
3,645✔
140
            clone->set_key(this->rng().random_vec(cipher->maximum_keylength()));
3,645✔
141

142
            {
3,645✔
143
               std::vector<uint8_t> buf = input;
3,645✔
144
               cipher->encrypt(buf);
3,645✔
145
               result.test_bin_eq(provider + " encrypt", buf, expected);
7,290✔
146
            }
×
147

148
            {
3,645✔
149
               if(nonce.empty()) {
3,645✔
150
                  cipher->set_key(key);
2,370✔
151
               } else {
152
                  cipher->set_iv(nonce.data(), nonce.size());
1,275✔
153
               }
154
               if(seek != 0) {
3,645✔
155
                  cipher->seek(seek);
700✔
156
               }
157
               std::vector<uint8_t> buf = input;
3,645✔
158
               cipher->encrypt(buf);
3,645✔
159
               result.test_bin_eq(provider + " encrypt 2", buf, expected);
7,290✔
160
            }
×
161

162
            if(!nonce.empty()) {
3,645✔
163
               cipher->set_iv(nonce.data(), nonce.size());
1,275✔
164
               if(seek != 0) {
1,275✔
165
                  cipher->seek(seek);
700✔
166
               }
167
               std::vector<uint8_t> buf = input;
1,275✔
168
               cipher->encrypt(buf);
1,275✔
169
               result.test_bin_eq(provider + " second encrypt", buf, expected);
2,550✔
170
            }
1,275✔
171

172
            {
3,645✔
173
               cipher->set_key(key);
3,645✔
174

175
               cipher->set_iv(nonce.data(), nonce.size());
3,645✔
176

177
               if(seek != 0) {
3,645✔
178
                  cipher->seek(seek);
700✔
179
               }
180

181
               std::vector<uint8_t> buf(input.size(), 0xAB);
3,645✔
182

183
               uint8_t* buf_ptr = buf.data();
3,645✔
184
               size_t buf_len = buf.size();
3,645✔
185

186
               while(buf_len > 0) {
9,256✔
187
                  const size_t next = std::min<size_t>(buf_len, this->rng().next_byte());
5,611✔
188
                  cipher->write_keystream(buf_ptr, next);
5,611✔
189
                  buf_ptr += next;
5,611✔
190
                  buf_len -= next;
5,611✔
191
               }
192

193
               for(size_t i = 0; i != input.size(); ++i) {
356,147✔
194
                  buf[i] ^= input[i];
352,502✔
195
               }
196
               result.test_bin_eq(provider + " write_keystream", buf, expected);
7,290✔
197
            }
×
198

199
            result.test_is_true("key set", cipher->has_keying_material());
3,645✔
200
            cipher->clear();
3,645✔
201
            result.test_is_false("key not set", cipher->has_keying_material());
3,645✔
202

203
            try {
3,645✔
204
               std::vector<uint8_t> buf(128);
3,645✔
205
               cipher->cipher1(buf.data(), buf.size());
3,645✔
206
               result.test_failure("Was able to encrypt without a key being set (after clear)");
×
207
            } catch(Botan::Invalid_State&) {
3,645✔
208
               result.test_success("Trying to encrypt with no key set (after clear) fails");
3,645✔
209
            }
3,645✔
210
         }
7,290✔
211

212
         return result;
213
      }
28,070✔
214
};
215

216
BOTAN_REGISTER_SERIALIZED_SMOKE_TEST("stream", "stream_ciphers", Stream_Cipher_Tests);
217

218
}  // namespace
219

220
#endif
221

222
}  // namespace Botan_Tests
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