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

randombit / botan / 5356326050

23 Jun 2023 01:05PM UTC coverage: 91.728% (-0.008%) from 91.736%
5356326050

Pull #3595

github

web-flow
Merge a5b917599 into 92171c524
Pull Request #3595: Improve clang-tidy coverage

78163 of 85212 relevant lines covered (91.73%)

12690161.35 hits per line

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

90.98
/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/stream_cipher.h>
11
   #include <botan/internal/fmt.h>
12
#endif
13

14
namespace Botan_Tests {
15

16
#if defined(BOTAN_HAS_STREAM_CIPHER)
17

18
class Stream_Cipher_Tests final : public Text_Based_Test {
×
19
   public:
20
      Stream_Cipher_Tests() : Text_Based_Test("stream", "Key,Out", "In,Nonce,Seek") {}
2✔
21

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

29
         if(input.empty()) {
3,538✔
30
            input.resize(expected.size());
2,664✔
31
         }
32

33
         Test::Result result(algo);
7,076✔
34

35
         const std::vector<std::string> providers = provider_filter(Botan::StreamCipher::providers(algo));
3,538✔
36

37
         if(providers.empty()) {
3,538✔
38
            result.note_missing("stream cipher " + algo);
1✔
39
            return result;
1✔
40
         }
41

42
         for(const auto& provider_ask : providers) {
7,074✔
43
            auto cipher = Botan::StreamCipher::create(algo, provider_ask);
3,537✔
44

45
            if(!cipher) {
3,537✔
46
               result.test_failure(Botan::fmt("Stream cipher {} supported by {} but not found", algo, provider_ask));
×
47
               continue;
×
48
            }
49

50
            const std::string provider(cipher->provider());
3,537✔
51
            result.test_is_nonempty("provider", provider);
3,537✔
52
            result.test_eq(provider, cipher->name(), algo);
3,537✔
53

54
            result.confirm("default iv length is valid", cipher->valid_iv_length(cipher->default_iv_length()));
7,074✔
55

56
            result.confirm("advertised buffer size is > 0", cipher->buffer_size() > 0);
7,074✔
57

58
            if(cipher->default_iv_length() == 0) {
3,537✔
59
               result.confirm("if default iv length is zero, no iv supported", nonce.empty());
4,730✔
60

61
               // This should still succeed
62
               cipher->set_iv(nullptr, 0);
2,365✔
63
            }
64

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

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

82
            if(!cipher->valid_iv_length(nonce.size())) {
3,537✔
83
               throw Test_Error("Invalid nonce for " + algo);
×
84
            }
85

86
            bool accepted_nonce_early = false;
3,537✔
87
            if(!nonce.empty()) {
3,537✔
88
               try {
1,168✔
89
                  cipher->set_iv(nonce.data(), nonce.size());
1,168✔
90
                  accepted_nonce_early = true;
91
               } catch(Botan::Invalid_State&) {}
1,168✔
92
            }
93

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

104
            result.test_eq("key not set", cipher->has_keying_material(), false);
3,537✔
105
            cipher->set_key(key);
3,537✔
106
            result.test_eq("key set", cipher->has_keying_material(), true);
3,537✔
107

108
            /*
109
            Test invalid nonce sizes. this assumes no implemented cipher supports a nonce of 65000
110
            */
111
            const size_t large_nonce_size = 65000;
3,537✔
112
            result.confirm("Stream cipher does not support very large nonce",
7,074✔
113
                           cipher->valid_iv_length(large_nonce_size) == false);
3,537✔
114

115
            result.test_throws("Throws if invalid nonce size given",
7,074✔
116
                               [&]() { cipher->set_iv(nullptr, large_nonce_size); });
3,537✔
117

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

128
            if(seek != 0) {
3,537✔
129
               cipher->seek(seek);
626✔
130
            }
131

132
            // Test that clone works and does not affect parent object
133
            auto clone = cipher->new_object();
3,537✔
134
            result.confirm("Clone has different pointer", cipher.get() != clone.get());
7,074✔
135
            result.test_eq("Clone has same name", cipher->name(), clone->name());
7,292✔
136
            clone->set_key(Test::rng().random_vec(cipher->maximum_keylength()));
3,537✔
137

138
            {
3,537✔
139
               std::vector<uint8_t> buf = input;
3,537✔
140
               cipher->encrypt(buf);
3,537✔
141
               result.test_eq(provider, "encrypt", buf, expected);
7,074✔
142
            }
×
143

144
            {
3,537✔
145
               if(nonce.empty()) {
3,537✔
146
                  cipher->set_key(key);
2,369✔
147
               } else {
148
                  cipher->set_iv(nonce.data(), nonce.size());
1,168✔
149
               }
150
               if(seek != 0) {
3,537✔
151
                  cipher->seek(seek);
626✔
152
               }
153
               std::vector<uint8_t> buf = input;
3,537✔
154
               cipher->encrypt(buf);
3,537✔
155
               result.test_eq(provider, "encrypt 2", buf, expected);
7,074✔
156
            }
×
157

158
            if(!nonce.empty()) {
3,537✔
159
               cipher->set_iv(nonce.data(), nonce.size());
1,168✔
160
               if(seek != 0) {
1,168✔
161
                  cipher->seek(seek);
626✔
162
               }
163
               std::vector<uint8_t> buf = input;
1,168✔
164
               cipher->encrypt(buf);
1,168✔
165
               result.test_eq(provider, "second encrypt", buf, expected);
2,336✔
166
            }
1,168✔
167

168
            {
3,537✔
169
               cipher->set_key(key);
3,537✔
170

171
               cipher->set_iv(nonce.data(), nonce.size());
3,537✔
172

173
               if(seek != 0) {
3,537✔
174
                  cipher->seek(seek);
626✔
175
               }
176

177
               std::vector<uint8_t> buf(input.size(), 0xAB);
3,537✔
178

179
               uint8_t* buf_ptr = buf.data();
3,537✔
180
               size_t buf_len = buf.size();
3,537✔
181

182
               while(buf_len > 0) {
8,893✔
183
                  size_t next = std::min<size_t>(buf_len, rng().next_byte());
5,356✔
184
                  cipher->write_keystream(buf_ptr, next);
5,356✔
185
                  buf_ptr += next;
5,356✔
186
                  buf_len -= next;
5,356✔
187
               }
188

189
               for(size_t i = 0; i != input.size(); ++i) {
340,721✔
190
                  buf[i] ^= input[i];
337,184✔
191
               }
192
               result.test_eq(provider, "write_keystream", buf, expected);
7,074✔
193
            }
×
194

195
            result.test_eq("key set", cipher->has_keying_material(), true);
3,537✔
196
            cipher->clear();
3,537✔
197
            result.test_eq("key not set", cipher->has_keying_material(), false);
3,537✔
198

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

208
         return result;
209
      }
15,321✔
210
};
211

212
BOTAN_REGISTER_SERIALIZED_SMOKE_TEST("stream", "stream_ciphers", Stream_Cipher_Tests);
213

214
#endif
215

216
}  // 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

© 2025 Coveralls, Inc