Coverage Report

Created: 2025-11-16 06:36

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/botan/src/lib/stream/stream_cipher.cpp
Line
Count
Source
1
/*
2
* Stream Ciphers
3
* (C) 2015,2016 Jack Lloyd
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7
8
#include <botan/stream_cipher.h>
9
10
#include <botan/exceptn.h>
11
#include <botan/mem_ops.h>
12
#include <botan/internal/scan_name.h>
13
14
#if defined(BOTAN_HAS_CHACHA)
15
   #include <botan/internal/chacha.h>
16
#endif
17
18
#if defined(BOTAN_HAS_SALSA20)
19
   #include <botan/internal/salsa20.h>
20
#endif
21
22
#if defined(BOTAN_HAS_SHAKE_CIPHER)
23
   #include <botan/internal/shake_cipher.h>
24
#endif
25
26
#if defined(BOTAN_HAS_CTR_BE)
27
   #include <botan/internal/ctr.h>
28
#endif
29
30
#if defined(BOTAN_HAS_OFB)
31
   #include <botan/internal/ofb.h>
32
#endif
33
34
#if defined(BOTAN_HAS_RC4)
35
   #include <botan/internal/rc4.h>
36
#endif
37
38
namespace Botan {
39
40
276
std::unique_ptr<StreamCipher> StreamCipher::create(std::string_view algo_spec, std::string_view provider) {
41
276
#if defined(BOTAN_HAS_SHAKE_CIPHER)
42
276
   if(algo_spec == "SHAKE-128" || algo_spec == "SHAKE-128-XOF") {
43
0
      if(provider.empty() || provider == "base") {
44
0
         return std::make_unique<SHAKE_128_Cipher>();
45
0
      }
46
0
   }
47
48
276
   if(algo_spec == "SHAKE-256" || algo_spec == "SHAKE-256-XOF") {
49
0
      if(provider.empty() || provider == "base") {
50
0
         return std::make_unique<SHAKE_256_Cipher>();
51
0
      }
52
0
   }
53
276
#endif
54
55
276
#if defined(BOTAN_HAS_CHACHA)
56
276
   if(algo_spec == "ChaCha20") {
57
0
      if(provider.empty() || provider == "base") {
58
0
         return std::make_unique<ChaCha>(20);
59
0
      }
60
0
   }
61
276
#endif
62
63
276
#if defined(BOTAN_HAS_SALSA20)
64
276
   if(algo_spec == "Salsa20") {
65
0
      if(provider.empty() || provider == "base") {
66
0
         return std::make_unique<Salsa20>();
67
0
      }
68
0
   }
69
276
#endif
70
71
276
   const SCAN_Name req(algo_spec);
72
73
276
#if defined(BOTAN_HAS_CTR_BE)
74
276
   if((req.algo_name() == "CTR-BE" || req.algo_name() == "CTR") && req.arg_count_between(1, 2)) {
75
0
      if(provider.empty() || provider == "base") {
76
0
         auto cipher = BlockCipher::create(req.arg(0));
77
0
         if(cipher) {
78
0
            size_t ctr_size = req.arg_as_integer(1, cipher->block_size());
79
0
            return std::make_unique<CTR_BE>(std::move(cipher), ctr_size);
80
0
         }
81
0
      }
82
0
   }
83
276
#endif
84
85
276
#if defined(BOTAN_HAS_CHACHA)
86
276
   if(req.algo_name() == "ChaCha") {
87
0
      if(provider.empty() || provider == "base") {
88
0
         return std::make_unique<ChaCha>(req.arg_as_integer(0, 20));
89
0
      }
90
0
   }
91
276
#endif
92
93
276
#if defined(BOTAN_HAS_OFB)
94
276
   if(req.algo_name() == "OFB" && req.arg_count() == 1) {
95
0
      if(provider.empty() || provider == "base") {
96
0
         if(auto cipher = BlockCipher::create(req.arg(0))) {
97
0
            return std::make_unique<OFB>(std::move(cipher));
98
0
         }
99
0
      }
100
0
   }
101
276
#endif
102
103
276
#if defined(BOTAN_HAS_RC4)
104
105
276
   if(req.algo_name() == "RC4" || req.algo_name() == "ARC4" || req.algo_name() == "MARK-4") {
106
0
      const size_t skip = (req.algo_name() == "MARK-4") ? 256 : req.arg_as_integer(0, 0);
107
108
0
      if(provider.empty() || provider == "base") {
109
0
         return std::make_unique<RC4>(skip);
110
0
      }
111
0
   }
112
113
276
#endif
114
115
276
   BOTAN_UNUSED(req);
116
276
   BOTAN_UNUSED(provider);
117
118
276
   return nullptr;
119
276
}
120
121
//static
122
0
std::unique_ptr<StreamCipher> StreamCipher::create_or_throw(std::string_view algo, std::string_view provider) {
123
0
   if(auto sc = StreamCipher::create(algo, provider)) {
124
0
      return sc;
125
0
   }
126
0
   throw Lookup_Error("Stream cipher", algo, provider);
127
0
}
128
129
0
std::vector<std::string> StreamCipher::providers(std::string_view algo_spec) {
130
0
   return probe_providers_of<StreamCipher>(algo_spec);
131
0
}
132
133
0
void StreamCipher::cipher(std::span<const uint8_t> in, std::span<uint8_t> out) {
134
0
   BOTAN_ARG_CHECK(in.size() <= out.size(), "Output buffer of stream cipher must be at least as long as input buffer");
135
0
   cipher_bytes(in.data(), out.data(), in.size());
136
0
}
137
138
0
size_t StreamCipher::default_iv_length() const {
139
0
   return 0;
140
0
}
141
142
0
void StreamCipher::generate_keystream(uint8_t out[], size_t len) {
143
0
   clear_mem(out, len);
144
0
   cipher1(out, len);
145
0
}
146
147
}  // namespace Botan