/src/botan/src/lib/block/cascade/cascade.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Block Cipher Cascade |
3 | | * (C) 2010 Jack Lloyd |
4 | | * |
5 | | * Botan is released under the Simplified BSD License (see license.txt) |
6 | | */ |
7 | | |
8 | | #include <botan/internal/cascade.h> |
9 | | |
10 | | #include <botan/internal/fmt.h> |
11 | | |
12 | | namespace Botan { |
13 | | |
14 | 0 | void Cascade_Cipher::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const { |
15 | 0 | size_t c1_blocks = blocks * (block_size() / m_cipher1->block_size()); |
16 | 0 | size_t c2_blocks = blocks * (block_size() / m_cipher2->block_size()); |
17 | |
|
18 | 0 | m_cipher1->encrypt_n(in, out, c1_blocks); |
19 | 0 | m_cipher2->encrypt_n(out, out, c2_blocks); |
20 | 0 | } |
21 | | |
22 | 0 | void Cascade_Cipher::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const { |
23 | 0 | size_t c1_blocks = blocks * (block_size() / m_cipher1->block_size()); |
24 | 0 | size_t c2_blocks = blocks * (block_size() / m_cipher2->block_size()); |
25 | |
|
26 | 0 | m_cipher2->decrypt_n(in, out, c2_blocks); |
27 | 0 | m_cipher1->decrypt_n(out, out, c1_blocks); |
28 | 0 | } |
29 | | |
30 | 0 | void Cascade_Cipher::key_schedule(const uint8_t key[], size_t /*length*/) { |
31 | 0 | const uint8_t* key2 = key + m_cipher1->maximum_keylength(); |
32 | |
|
33 | 0 | m_cipher1->set_key(key, m_cipher1->maximum_keylength()); |
34 | 0 | m_cipher2->set_key(key2, m_cipher2->maximum_keylength()); |
35 | 0 | } |
36 | | |
37 | 0 | void Cascade_Cipher::clear() { |
38 | 0 | m_cipher1->clear(); |
39 | 0 | m_cipher2->clear(); |
40 | 0 | } |
41 | | |
42 | 0 | std::string Cascade_Cipher::name() const { return fmt("Cascade({},{})", m_cipher1->name(), m_cipher2->name()); } |
43 | | |
44 | 0 | bool Cascade_Cipher::has_keying_material() const { |
45 | 0 | return m_cipher1->has_keying_material() && m_cipher2->has_keying_material(); |
46 | 0 | } |
47 | | |
48 | 0 | std::unique_ptr<BlockCipher> Cascade_Cipher::new_object() const { |
49 | 0 | return std::make_unique<Cascade_Cipher>(m_cipher1->new_object(), m_cipher2->new_object()); |
50 | 0 | } |
51 | | |
52 | | namespace { |
53 | | |
54 | 0 | size_t euclids_algorithm(size_t a, size_t b) { |
55 | 0 | while(b != 0) { |
56 | 0 | size_t t = b; |
57 | 0 | b = a % b; |
58 | 0 | a = t; |
59 | 0 | } |
60 | |
|
61 | 0 | return a; |
62 | 0 | } |
63 | | |
64 | 0 | size_t block_size_for_cascade(size_t bs, size_t bs2) { |
65 | 0 | if(bs == bs2) { |
66 | 0 | return bs; |
67 | 0 | } |
68 | | |
69 | 0 | const size_t gcd = euclids_algorithm(bs, bs2); |
70 | |
|
71 | 0 | return (bs * bs2) / gcd; |
72 | 0 | } |
73 | | |
74 | | } // namespace |
75 | | |
76 | | Cascade_Cipher::Cascade_Cipher(std::unique_ptr<BlockCipher> cipher1, std::unique_ptr<BlockCipher> cipher2) : |
77 | | m_cipher1(std::move(cipher1)), |
78 | | m_cipher2(std::move(cipher2)), |
79 | 0 | m_block_size(block_size_for_cascade(m_cipher1->block_size(), m_cipher2->block_size())) { |
80 | 0 | BOTAN_ASSERT(m_block_size % m_cipher1->block_size() == 0 && m_block_size % m_cipher2->block_size() == 0, |
81 | 0 | "Combined block size is a multiple of each ciphers block"); |
82 | 0 | } |
83 | | |
84 | | } // namespace Botan |