1 /** 2 * Lion 3 * 4 * Copyright: 5 * (C) 1999-2007,2014 Jack Lloyd 6 * (C) 2014-2015 Etienne Cimon 7 * 8 * License: 9 * Botan is released under the Simplified BSD License (see LICENSE.md) 10 */ 11 module botan.block.lion; 12 13 import botan.constants; 14 static if (BOTAN_HAS_LION): 15 16 import botan.block.block_cipher; 17 import botan.stream.stream_cipher; 18 import botan.hash.hash; 19 import botan.utils.xor_buf; 20 import botan.utils.parsing; 21 import botan.utils.mem_ops; 22 import std.conv : to; 23 import std.algorithm : max; 24 import botan.utils.mem_ops; 25 26 /** 27 * Lion is a block cipher construction designed by Ross Anderson and 28 * Eli Biham, described in "Two Practical and Provably Secure Block 29 * Ciphers: BEAR and LION". It has a variable block size and is 30 * designed to encrypt very large blocks (up to a megabyte) 31 32 * http://www.cl.cam.ac.uk/~rja14/Papers/bear-lion.pdf 33 */ 34 final class Lion : BlockCipher, SymmetricAlgorithm 35 { 36 public: 37 /* 38 * Lion Encryption 39 */ 40 override void encryptN(const(ubyte)* input, ubyte* output, size_t blocks) 41 { 42 const size_t LEFT_SIZE = leftSize(); 43 const size_t RIGHT_SIZE = right_size(); 44 45 SecureVector!ubyte buffer_vec = SecureVector!ubyte(LEFT_SIZE); 46 ubyte* buffer = buffer_vec.ptr; 47 48 foreach (size_t i; 0 .. blocks) 49 { 50 xorBuf(buffer, input, m_key1.ptr, LEFT_SIZE); 51 m_cipher.setKey(buffer, LEFT_SIZE); 52 m_cipher.cipher(input + LEFT_SIZE, output + LEFT_SIZE, RIGHT_SIZE); 53 54 m_hash.update(output + LEFT_SIZE, RIGHT_SIZE); 55 m_hash.flushInto(buffer); 56 xorBuf(output, input, buffer, LEFT_SIZE); 57 58 xorBuf(buffer, output, m_key2.ptr, LEFT_SIZE); 59 m_cipher.setKey(buffer, LEFT_SIZE); 60 m_cipher.cipher1(output + LEFT_SIZE, RIGHT_SIZE); 61 62 input += m_block_size; 63 output += m_block_size; 64 } 65 } 66 67 /* 68 * Lion Decryption 69 */ 70 override void decryptN(const(ubyte)* input, ubyte* output, size_t blocks) 71 { 72 const size_t LEFT_SIZE = leftSize(); 73 const size_t RIGHT_SIZE = right_size(); 74 75 SecureVector!ubyte buffer_vec = SecureVector!ubyte(LEFT_SIZE); 76 ubyte* buffer = buffer_vec.ptr; 77 78 foreach (size_t i; 0 .. blocks) 79 { 80 xorBuf(buffer, input, m_key2.ptr, LEFT_SIZE); 81 m_cipher.setKey(buffer, LEFT_SIZE); 82 m_cipher.cipher(input + LEFT_SIZE, output + LEFT_SIZE, RIGHT_SIZE); 83 84 m_hash.update(output + LEFT_SIZE, RIGHT_SIZE); 85 m_hash.flushInto(buffer); 86 xorBuf(output, input, buffer, LEFT_SIZE); 87 88 xorBuf(buffer, output, m_key1.ptr, LEFT_SIZE); 89 m_cipher.setKey(buffer, LEFT_SIZE); 90 m_cipher.cipher1(output + LEFT_SIZE, RIGHT_SIZE); 91 92 input += m_block_size; 93 output += m_block_size; 94 } 95 } 96 97 override size_t blockSize() const { return m_block_size; } 98 99 override KeyLengthSpecification keySpec() const 100 { 101 return KeyLengthSpecification(2, 2*m_hash.outputLength, 2); 102 } 103 104 /* 105 * Clear memory of sensitive data 106 */ 107 override void clear() 108 { 109 zeroise(m_key1); 110 zeroise(m_key2); 111 m_hash.clear(); 112 m_cipher.clear(); 113 } 114 115 /* 116 * Return the name of this type 117 */ 118 override @property string name() const 119 { 120 return "Lion(" ~ m_hash.name ~ "," ~ 121 m_cipher.name ~ "," ~ 122 to!string(blockSize()) ~ ")"; 123 } 124 125 /* 126 * Return a clone of this object 127 */ 128 override BlockCipher clone() const 129 { 130 return new Lion(m_hash.clone(), m_cipher.clone(), blockSize()); 131 } 132 133 134 /** 135 * Params: 136 * hash = the hash to use internally 137 * cipher = the stream cipher to use internally 138 * block_size = the size of the block to use 139 */ 140 this(HashFunction hash, StreamCipher cipher, size_t block_size) 141 { 142 m_block_size = max(2*hash.outputLength + 1, block_size); 143 m_hash = hash; 144 m_cipher = cipher; 145 146 if (2*leftSize() + 1 > m_block_size) 147 throw new InvalidArgument(name ~ ": Chosen block size is too small"); 148 149 if (!m_cipher.validKeylength(leftSize())) 150 throw new InvalidArgument(name ~ ": This stream/hash combo is invalid"); 151 152 m_key1.resize(leftSize()); 153 m_key2.resize(leftSize()); 154 } 155 override @property size_t parallelism() const { return 1; } 156 protected: 157 158 /* 159 * Lion Key Schedule 160 */ 161 override void keySchedule(const(ubyte)* key, size_t length) 162 { 163 clear(); 164 165 const size_t half = length / 2; 166 copyMem(m_key1.ptr, key, half); 167 copyMem(m_key2.ptr, key + half, half); 168 } 169 170 private: 171 size_t leftSize() const { return m_hash.outputLength; } 172 size_t right_size() const { return m_block_size - leftSize(); } 173 174 const size_t m_block_size; 175 Unique!HashFunction m_hash; 176 Unique!StreamCipher m_cipher; 177 SecureVector!ubyte m_key1, m_key2; 178 }