• 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

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
#endif
12

13
namespace Botan_Tests {
14

15
#if defined(BOTAN_HAS_STREAM_CIPHER)
16

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

213
#endif
214

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